]> git.openfabrics.org - ~shefty/rdma-win.git/commitdiff
[OPENSM] Wof 2.2 build 3.0.0 version of opensm.exe for failback purposes.
authorstansmith <stansmith@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Mon, 14 Dec 2009 19:31:42 +0000 (19:31 +0000)
committerstansmith <stansmith@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Mon, 14 Dec 2009 19:31:42 +0000 (19:31 +0000)
git-svn-id: svn://openib.tc.cornell.edu/gen1@2637 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

282 files changed:
branches/WOF2-2/ulp/opensm/user_3_0_0/README.opensm-build [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/TODO [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/config.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/dirs [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/doc/OpenSM_PKey_Mgr.txt [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/doc/OpenSM_RN_0_3_1.pdf [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/doc/OpenSM_UM_0_3.pdf [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/doc/current-routing.txt [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/doc/modular-routing.txt [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/doc/opensm_release_notes_openib-2.0.5.txt [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/doc/qos-config.txt [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/Makefile [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/SOURCES [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/ibtrapgen.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/ibtrapgen.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/main.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_byteswap.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_dispatcher.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_event_wheel.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_signal_osd.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/iba/ib_types.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/iba/ib_types_extended.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/cl_dispatcher.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/cl_event_wheel.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_attrib_req.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_base.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_console.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_db.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_db_pack.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_drop_mgr.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_errors.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_fwd_tbl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_helper.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_inform.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lid_mgr.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lin_fwd_rcv.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lin_fwd_rcv_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lin_fwd_tbl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_link_mgr.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_log.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mad_pool.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_madw.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_matrix.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_fwd_rcv.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_fwd_rcv_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_mgr.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_tbl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcm_info.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcm_port.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_msgdef.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mtl_bind.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mtree.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_multicast.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_desc_rcv.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_desc_rcv_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_info_rcv.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_info_rcv_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_opensm.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_partition.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_path.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey_mgr.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey_rcv.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey_rcv_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port_info_rcv.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port_info_rcv_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port_profile.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_rand_fwd_tbl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_remote_sm.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_req.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_req_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_resp.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_router.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_class_port_info.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_class_port_info_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_guidinfo_record.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_guidinfo_record_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_informinfo.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_informinfo_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_lft_record.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_lft_record_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_link_record.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_link_record_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mad_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mcmember_record.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mcmember_record_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mft_record.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mft_record_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_multipath_record.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_multipath_record_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_node_record.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_node_record_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_path_record.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_path_record_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_pkey_record.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_pkey_record_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_portinfo_record.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_portinfo_record_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_response.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_service_record.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_service_record_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_slvl_record.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_slvl_record_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sminfo_record.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sminfo_record_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sw_info_record.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sw_info_record_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_vlarb_record.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_vlarb_record_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_service.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_slvl_map_rcv.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_slvl_map_rcv_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sm.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sm_mad_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sm_state_mgr.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sminfo_rcv.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sminfo_rcv_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_state_mgr.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_state_mgr_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_stats.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_subnet.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sw_info_rcv.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sw_info_rcv_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sweep_fail_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_switch.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_trap_rcv.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_trap_rcv_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_ts_useraccess.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_ucast_mgr.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_umadt.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_version.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_vl15intf.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_vl_arb_rcv.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_vl_arb_rcv_ctrl.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/st.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/unistd.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_al.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_api.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_sa_api.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_select.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/winosm_common.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/Makefile [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/SOURCES [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/osm_helper.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/osm_log.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/osm_mad_pool.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/Makefile [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/SOURCES [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/osm_vendor_al.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/osm_vendor_mlx_sa.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/winosm_common.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/Makefile [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/SOURCES [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/cl_dispatcher.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/cl_event_wheel.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/main.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/opensm.opts [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/opensm.rc [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm.mc [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_console.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_db_files.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_db_pack.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_drop_mgr.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_files.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_fwd_tbl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_inform.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lid_mgr.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lin_fwd_rcv.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lin_fwd_rcv_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lin_fwd_tbl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_link_mgr.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_matrix.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_fwd_rcv.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_fwd_rcv_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_mgr.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_tbl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcm_info.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcm_port.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mtree.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_multicast.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_desc_rcv.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_desc_rcv_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_info_rcv.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_info_rcv_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_opensm.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey_mgr.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey_rcv.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey_rcv_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_port.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_port_info_rcv.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_port_info_rcv_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_prtn.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_prtn_config.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_qos.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_remote_sm.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_req.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_req_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_resp.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_router.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_class_port_info.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_class_port_info_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_guidinfo_record.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_guidinfo_record_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_informinfo.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_informinfo_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_lft_record.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_lft_record_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_link_record.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_link_record_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mad_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mcmember_record.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mcmember_record_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mft_record.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mft_record_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_multipath_record.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_multipath_record_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_node_record.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_node_record_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_path_record.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_path_record_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_pkey_record.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_pkey_record_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_portinfo_record.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_portinfo_record_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_response.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_service_record.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_service_record_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_slvl_record.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_slvl_record_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sminfo_record.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sminfo_record_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sw_info_record.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sw_info_record_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_vlarb_record.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_vlarb_record_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_service.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_slvl_map_rcv.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_slvl_map_rcv_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sm.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sm_mad_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sm_state_mgr.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sminfo_rcv.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sminfo_rcv_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_state_mgr.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_state_mgr_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_subnet.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sw_info_rcv.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sw_info_rcv_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sweep_fail_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_switch.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_trap_rcv.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_trap_rcv_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_file.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_ftree.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_mgr.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_updn.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_vl15intf.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_vl_arb_rcv.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_vl_arb_rcv_ctrl.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/st.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/Makefile [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/SOURCES [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/error.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmt_inform.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmt_mtl_regular_qp.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmtest.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmtest_base.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmtest_subnet.h [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/main.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_inform.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_mtl_regular_qp.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_multicast.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_service.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_slvl_vl_arb.c [new file with mode: 0644]
branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmtest.c [new file with mode: 0644]

diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/README.opensm-build b/branches/WOF2-2/ulp/opensm/user_3_0_0/README.opensm-build
new file mode 100644 (file)
index 0000000..cccd07a
--- /dev/null
@@ -0,0 +1,24 @@
+##### Begin svn/gen1/trunk/src/userspace/osm/README.opensm-build
+
+# How to Build the OpenSM Subnet Manager
+# ----------------------------------------
+
+# This file is arranged as a shell script so you can paste or execute
+# it.  This is for building from the SVN source at openib.org.
+                                                                                          
+# 1. Complete steps outlined in README.kernel-build.
+# 2. Complete steps outlined in README.user-build.
+
+# set TOP to wherever you've checked out the openib repository.
+TOP=/usr/src/openib
+
+export TSHOME=$TOP/src/linux-kernel/infiniband/include/
+export MTHOME=$TOP/src/userspace/hw/mellanox-hca/mthome/
+
+# Add util dir to path for makedepend
+export PATH=$TOP/src/userspace/osm/util:$PATH
+
+cd $TOP/src/userspace/osm
+make VENDOR=ts
+
+##### end
\ No newline at end of file
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/TODO b/branches/WOF2-2/ulp/opensm/user_3_0_0/TODO
new file mode 100644 (file)
index 0000000..684ef45
--- /dev/null
@@ -0,0 +1,16 @@
+Support new HOQ value for the ports feeding HCA ports
+
+Support Static Lid assignment with a flag for specifying a file with guid to lid.
+
+Support PKey comp in Path Record
+Support SL comp in Path Record
+
+Support VL traversal in Path Record - compute the SL accordingly 
+ Make it a runtime option, So we do not pay the price if no SL are used.
+
+Support a fast Path Record mode - if the fabric is totally uniform in rate and
+ MTU. No need to traverse the path at all...
+
+Improve the MinHop routing algorithm such that it only calc the min hops 
+for switches, then 
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/config.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/config.h
new file mode 100644 (file)
index 0000000..5d7c42d
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+/*
+ * Abstract:
+ *     Windows-specific definitions
+ *
+ * Environment:
+ *     Windows
+ *
+ * $Revision: $
+ */
+
+#ifndef _CONFIG_h_
+#define _CONFIG_h_
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <io.h>
+
+#define chmod(a,b) _chmod(a,b)
+#define S_IRUSR _S_IREAD
+#define S_IWUSR _S_IWRITE
+
+#define snprintf _snprintf
+#define fileno _fileno
+
+#define stat _stat
+#define fstat(a,b) fstat_alias((a),(b))
+
+inline int 
+fstat_alias(int filedes, struct _stat *buf)
+{
+    return _fstat(filedes, buf);
+}
+
+#endif /*_CONFIG_h_ */
+
+
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/dirs b/branches/WOF2-2/ulp/opensm/user_3_0_0/dirs
new file mode 100644 (file)
index 0000000..cbfc709
--- /dev/null
@@ -0,0 +1,5 @@
+DIRS=\
+   libvendor \
+   libopensm \
+   opensm
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/OpenSM_PKey_Mgr.txt b/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/OpenSM_PKey_Mgr.txt
new file mode 100644 (file)
index 0000000..df4031c
--- /dev/null
@@ -0,0 +1,79 @@
+OpenSM Partition Management
+---------------------------
+
+Roadmap:
+Phase 1 - provide partition management at the EndPort (HCA, Router and Switch 
+          Port 0) level with no routing affects.
+Phase 2 - routing engine should take partitions into account.
+
+Phase 1 functionality:
+
+Supported Policy:
+
+1. EndPort partition groups are to be defined by listing the 
+   PortGUIDs as full and limited members.
+
+2. Each partition group might be assigned an explicit P_Key (only the 15 
+   LSB bits are valid) or the SM should assign it randomly. 
+
+3. A flag should control the generation of IPoIB broadcast group for
+   that partition. Extra optional MGIDs can be provided to be setup (on
+   top of the IPoIB broadcast group). 
+
+4. A global flag "Disconnect Unconfigured EndPorts": If TRUE prevents
+   EndPorts that are not explicitly defined as part of any partition
+   (thus "unconfigured") to communicate with any other EndPort. Otherwise, it
+   will let these EndPorts send packets to all other EndPorts.
+
+Functionality:
+
+1. The policy should be updated:
+   - during SM bringup
+   - after kill -HUP
+   - through SNMP (once it is supported)
+
+2. Partition tables will be updated on full sweep (new port/trap etc).
+   As a first step, the policy feasibility should be
+   verified. Feasibility could be limited by the EndPorts supports for
+   number of partitions, etc. Unrealizable policy should be reported
+   and extra rules ignored after providing error messages. 
+
+3. Each EndPort will be assigned P_Keys as follows:
+
+   a. Default partition group limited membership as defined by rule #4 below.
+     (only the SM port will get 0xffff).
+
+   b. P_Keys for all partition groups it is part of as defined in 
+      the policy.
+
+   c. P_Key update will preserve index for the existing P_Keys on the
+      port. If port has limited resources that will require reuse of,
+      on index a message will be provided and some of the settings will be
+      ommitted. P_Key indexes will not change under any circumstances.
+
+4. Each Switch Leaf Port (a switch port that is connected to an
+   EndPort) should be configured according to the same rules that
+   apply to the EndPort connected to that switch port. 
+   This actually enables unauthorized port isolation (with future
+   usage of M_Key and ProtectBits). 
+
+5. Policy entries matching a non EndPort will be flagged as
+   erroneous in the log file and ignored. 
+
+6. At the end of the P_Key setting phase, a check for successful
+   setting should be made.
+   Errors should be clearly logged and cause a new sweep. 
+   
+7. Each partition that is marked to support IPoIB should define a
+   broadcast MGRP. If the partition does not support IPoIB, it should 
+   define a dummy MGRP with parameters blocking IPoIB drivers from 
+   registering to it.
+
+Phase 2 functionality:
+
+The partition policy should be considered during the routing such that
+links are associated with particular partition or a set of
+partitions. Policy should be enhanced to provide hints for how to do
+that (correlating to QoS too). The exact algorithm is TBD. 
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/OpenSM_RN_0_3_1.pdf b/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/OpenSM_RN_0_3_1.pdf
new file mode 100644 (file)
index 0000000..4eaacf8
Binary files /dev/null and b/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/OpenSM_RN_0_3_1.pdf differ
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/OpenSM_UM_0_3.pdf b/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/OpenSM_UM_0_3.pdf
new file mode 100644 (file)
index 0000000..9951171
Binary files /dev/null and b/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/OpenSM_UM_0_3.pdf differ
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/current-routing.txt b/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/current-routing.txt
new file mode 100644 (file)
index 0000000..3cc6f99
--- /dev/null
@@ -0,0 +1,202 @@
+Current OpenSM Routing
+1/2/07
+
+OpenSM offers three routing engines:
+
+1.  Min Hop Algorithm - based on the minimum hops to each node where the 
+path length is optimized.
+
+2.  UPDN Unicast routing algorithm - also based on the minimum hops to each 
+node, but it is constrained to ranking rules. This algorithm should be chosen 
+if the subnet is not a pure Fat Tree, and deadlock may occur due to a 
+loop in the subnet.
+
+3.  Fat-tree Unicast routing algorithm - this algorithm optimizes routing
+of fat-trees for congestion-free "shift" communication pattern. 
+It should be chosen if a subnet is a symmetrical fat-tree. 
+Similar to UPDN routing, Fat-tree routing is credit-loop-free.
+
+OpenSM now also offers a file method which can load routes from a table. See 
+modular-routing.txt for more information on this.
+
+The basic routing algorithm is comprised of two stages:
+1. MinHop matrix calculation
+   How many hops are required to get from each port to each LID ?
+   The algorithm to fill these tables is different if you run standard
+(min hop) or Up/Down.
+   For standard routing, a "relaxation" algorithm is used to propagate
+min hop from every destination LID through neighbor switches
+   For Up/Down routing, a BFS from every target is used. The BFS tracks link
+direction (up or down) and avoid steps that will perform up after a down
+step was used.
+
+2. Once MinHop matrices exist, each switch is visited and for each target LID a
+decision is made as to what port should be used to get to that LID.
+   This step is common to standard and Up/Down routing. Each port has a
+counter counting the number of target LIDs going through it.
+   When there are multiple alternative ports with same MinHop to a LID,
+the one with less previously assigned ports is selected. 
+   If LMC > 0, more checks are added: Within each group of LIDs assigned to 
+same target port, 
+   a. use only ports which have same MinHop 
+   b. first prefer the ones that go to different systemImageGuid (then
+the previous LID of the same LMC group)
+   c. if none - prefer those which go through another NodeGuid
+   d. fall back to the number of paths method (if all go to same node).
+
+
+Effect of Topology Changes
+
+OpenSM will preserve existing routing in any case where there is no change in
+the fabric switches unless the -r (--reassign_lids) option is specified.
+
+-r
+--reassign_lids
+          This option causes OpenSM to reassign LIDs to all
+          end nodes. Specifying -r on a running subnet
+          may disrupt subnet traffic.
+          Without -r, OpenSM attempts to preserve existing
+          LID assignments resolving multiple use of same LID.
+
+If a link is added or removed, OpenSM does not recalculate
+the routes that do not have to change. A route has to change 
+if the port is no longer UP or no longer the MinHop. When routing changes 
+are performed, the same algorithm for balancing the routes is invoked.
+
+In the case of using the file based routing, any topology changes are
+currently ignored The 'file' routing engine just loads the LFTs from the file 
+specified, with no reaction to real topology. Obviously, this will not be able 
+to recheck LIDs (by GUID) for disconnected nodes, and LFTs for non-existent 
+switches will be skipped. Multicast is not affected by 'file' routing engine 
+(this uses min hop tables).
+
+
+Min Hop Algorithm
+-----------------
+
+The Min Hop algorithm is invoked when neither UPDN or the file method are
+specified.
+The Min Hop algorithm is divided into two stages: computation of
+min-hop tables on every switch and LFT output port assignment. Link
+subscription is also equalized with the ability to override based on
+port GUID. The latter is supplied by:
+
+-i <equalize-ignore-guids-file>
+-ignore-guids <equalize-ignore-guids-file>
+          This option provides the means to define a set of ports
+          (by guids) that will be ignored by the link load
+          equalization algorithm.
+
+LMC awareness routes based on (remote) system or switch basis.
+
+
+UPDN Routing Algorithm
+----------------------
+
+Purpose of UPDN Algorithm
+
+The UPDN algorithm is designed to prevent deadlocks from occurring in loops 
+of the subnet. A loop-deadlock is a situation in which it is no longer 
+possible to send data between any two hosts connected through the loop. As 
+such, the UPDN routing algorithm should be used if the subnet is not a pure 
+Fat Tree, and one of its loops may experience a deadlock (due, for example, 
+to high pressure).
+
+The UPDN algorithm is based on the following main stages:
+
+1.  Auto-detect root nodes - based on the CA hop length from any switch in 
+the subnet, a statistical histogram is built for each switch (hop num vs 
+number of occurrences). If the histogram reflects a specific column (higher
+than others) for a certain node, then it is marked as a root node. Since 
+the algorithm is statistical, it may not find any root nodes. The list of 
+the root nodes found by this auto-detect stage is used by the ranking 
+process stage.
+
+    Note 1: The user can override the node list manually.
+    Note 2: If this stage cannot find any root nodes, and the user did not 
+            specify a guid list file, OpenSM defaults back to the Min Hop 
+            routing algorithm.
+
+2.  Ranking process - All root switch nodes (found in stage 1) are assigned 
+a rank of 0. Using the BFS algorithm, the rest of the switch nodes in the 
+subnet are ranked incrementally. This ranking aids in the process of enforcing 
+rules that ensure loop-free paths.
+
+3.  Min Hop Table setting - after ranking is done, a BFS algorithm is run from 
+each (CA or switch) node in the subnet. During the BFS process, the FDB table 
+of each switch node traversed by BFS is updated, in reference to the starting 
+node, based on the ranking rules and guid values.
+
+At the end of the process, the updated FDB tables ensure loop-free paths 
+through the subnet.
+
+
+UPDN Algorithm Usage
+
+Activation through OpenSM
+
+Use '-R updn' option (instead of old '-u') to activate the UPDN algorithm.
+Use `-a <guid_list_file>' for adding an UPDN guid file that contains the 
+root nodes for ranking.
+If the `-a' option is not used, OpenSM uses its auto-detect root nodes 
+algorithm.
+
+Notes on the guid list file:
+1.   A valid guid file specifies one guid in each line. Lines with an invalid 
+format will be discarded.
+2.   The user should specify the root switch guids. However, it is also 
+possible to specify CA guids; OpenSM will use the guid of the switch (if 
+it exists) that connects the CA to the subnet as a root node.
+
+
+To learn more about deadlock-free routing, see the article 
+"Deadlock Free Message Routing in Multiprocessor Interconnection Networks" 
+by William J Dally and Charles L Seitz (1985).
+
+
+Fat-tree Routing Algorithm
+--------------------------
+
+Purpose:
+
+The fat-tree algorithm optimizes routing for "shift" communication pattern. 
+It should be chosen if a subnet is a symmetrical fat-tree of various types.
+It supports not just K-ary-N-Trees, by handling for non-constant K, 
+cases where not all leafs (CAs) are present, any CBB ratio.
+As in UPDN, fat-tree also prevents credit-loop-deadlocks.
+Fat-tree algorithm supports topologies that comply with the following rules:
+  - Tree rank should be between two and eight (inclusively)
+  - Switches of the same rank should have the same number
+    of UP-going port groups*, unless they are root switches,
+    in which case the shouldn't have UP-going ports at all.
+  - Switches of the same rank should have the same number
+    of DOWN-going port groups, unless they are leaf switches.
+  - Switches of the same rank should have the same number
+    of ports in each UP-going port group.
+  - Switches of the same rank should have the same number
+    of ports in each DOWN-going port group.
+*ports that are connected to the same remote switch are referenced as
+'port group'. 
+
+Note that although fat-tree algorithm supports trees with non-integer CBB 
+ratio, the routing will not be as balanced as in case of integer CBB ratio.
+In addition to this, although the algorithm allows leaf switches to have any 
+number of CAs, the closer the tree is to be fully populated, the more effective
+the "shift" communication pattern will be.
+
+The algorithm also dumps CA ordering file (osm-ftree-ca-order.dump) in the
+same directory where the OpenSM log resides. This ordering file provides the 
+CA order that may be used to create efficient communication pattern, that
+will match the routing tables.
+
+
+Usage:
+
+Activation through OpenSM
+
+Use '-R ftree' option to activate the fat-tree algorithm.
+
+Note: LMC > 0 is not supported by fat-tree routing. If this is
+specified, the default routing algorithm is invoked instead.
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/modular-routing.txt b/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/modular-routing.txt
new file mode 100644 (file)
index 0000000..0a59346
--- /dev/null
@@ -0,0 +1,78 @@
+Modular Routine Engine
+
+Modular routing engine structure has been added to allow
+for ease of "plugging" new routing modules.
+
+Currently, only unicast callbacks are supported. Multicast
+can be added later.
+
+One of existing routing modules is up-down "updn", which may
+be activated with '-R updn' option (instead of old '-u').
+
+General usage is:
+$ opensm -R 'module-name'
+
+There is also a trivial routing module which is able
+to load LFT tables from a dump file.
+
+Main features:
+
+- this will load switch LFTs and/or LID matrices (min hops tables)
+- this will load switch LFTs according to the path entries introduced in
+  the dump file
+- no additional checks will be performed (such as "is port connected", etc.)
+- in case when fabric LIDs were changed this will try to reconstruct LFTs
+  correctly if endport GUIDs are represented in the dump file (in order
+  to disable this GUIDs may be removed from the dump file or zeroed)
+
+The dump file format is compatible with output of 'ibroute' util and for
+whole fabric may be generated with script like this:
+
+  for sw_lid in `ibswitches | awk '{print $NF}'` ; do
+       ibroute $sw_lid
+  done > /path/to/dump_file
+
+, or using DR paths:
+
+  for sw_dr in `ibnetdiscover -v \
+               | sed -ne '/^DR path .* switch /s/^DR path \[\(.*\)\].*$/\1/p' \
+               | sed -e 's/\]\[/,/g' \
+               | sort -u` ; do
+       ibroute -D ${sw_dr}
+  done > /path/to/dump_file
+
+This script is dump_lfts.sh
+
+In order to activate new module use:
+
+  opensm -R file -U /path/to/dump_file
+
+If the dump_file is not found or is in error, the default routing 
+algorithm is utilized.
+
+The ability to dump switch lid matrices (aka min hops tables) to file and
+later to load these is also supported.
+
+The usage is similar to unicast forwarding tables loading from dump
+file (introduced by 'file' routing engine), but new lid matrix file
+name should be specified by -M or --lid_matrix_file option. For example:
+
+  opensm -R file -M ./opensm-lid-matrix.dump
+
+The dump file is named 'opensm-lid-matrix.dump' and will be generated in
+standard opensm dump directory (/var/log by default) when
+OSM_LOG_ROUTING logging flag is set.
+
+When routing engine 'file' is activated, but dump file is not specified
+or not cannot be open default lid matrix algorithm will be used.
+
+There is also a switch forwarding tables dumper which generates
+a file compatible with dump_lfts.sh output. This file can be used
+as input for forwarding tables loading by 'file' routing engine.
+Both or one of options -U and -M can be specified together with '-R file'.
+
+NOTE: ibroute has been updated (for switch management ports) to support this.
+Also, lmc was added to switch management ports. ibroute needs to be r7855 or
+later from the trunk.
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/opensm_release_notes_openib-2.0.5.txt b/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/opensm_release_notes_openib-2.0.5.txt
new file mode 100644 (file)
index 0000000..a655573
--- /dev/null
@@ -0,0 +1,487 @@
+                        OpenSM Release Notes 2.0.5
+                       ============================
+
+Version: OpenFabrics Enterprise Distribution (OFED) 1.1
+Repo:    https://openib.org/svn/gen2/branches/1.1/src/userspace/management/osm
+Version: 9535 (openib-2.0.5)
+Date:    October 2006
+
+1 Overview
+----------
+This document describes the contents of the OpenSM OFED 1.1 release. 
+OpenSM is an InfiniBand compliant Subnet Manager and Administration,
+and runs on top of OpenIB. The OpenSM version for this release 
+is openib-2.0.5
+
+This document includes the following sections:
+1 This Overview section (describing new features and software
+  dependencies)
+2 Known Issues And Limitations
+3 Unsupported IB compliance statements
+4 Major Bug Fixes
+5 Main Verification Flows
+6 Qualified software stacks and devices
+
+1.1 Major New Features
+
+* Partition manager: 
+  The partition manager provides a means to setup multiple partitions 
+  by providing a partition policy file. For details please read the
+  doc/partition-config.txt or the opensm man page.
+
+* Basic QoS Manager: 
+  Provides a uniform configuration of the entire fabric with values defined 
+  in the OpenSM options file. The options support different settings for 
+  CAs, Switches, and Routers. Note that this is disabled by default and
+  using -Q enables QoS fabric setup. 
+
+* Loading pre-routes from a file:
+  A new routing module enables loading pre-routes from a file. 
+  To use this option you should use the command line options:
+  "-R file --U <your routing file>" or 
+  "--routing_engine file --ucast_file <your routing file>"
+  For more information refer to the file doc/modular-routing.txt
+  or the opensm man page.
+
+* SA MultiPathRecord support:
+  The SA can now handle requests for multiple PathRecords in one query.
+  This includes methods SA GetMulti/GetMultiResp and dual sided RMPP.
+
+* PPC64 is now QAed and supported
+
+* Support LMC > 0 for Switch Enhanced Port 0:
+  Allows enhanced switch port 0 (ESP0) to have a non zero
+  LMC. Use the configured subnet wide LMC for this. Modifications were
+  necessary to the LID assignment and routing to support this. 
+  Also, added an option to the configuration to use LMC configured for
+  subnet for enhanced switch port 0 or set it to 0 even if a non zero
+  LMC is configured for the subnet. The default is currently the
+  latter option. The new configuration option is: lmc_esp0
+
+1.2 Minor New Features:
+
+* IPoIB broadcast group configuration:
+  It is now possible to control the IPoIB broadcast group parameters
+  (MTU, rate, SL) through the partitions configuration file.
+
+* Limiting OpenSM log file size:
+  By providing the command line option: "-L <size in MB>" or
+  "--log_limit <size in MB>" the user can limit the generated log 
+  file size. When specified, the log file will be truncated upon reaching
+  this limit.
+
+* Favor 1K MTU for Tavor (MT23108) HCA
+  In cases where a PathRecord or MultiPathRecord is queried and the
+  requestor does not specify the MTU or does specify it in a way
+  that allows for MTU to be 1K and one of the path ends in a Tavor,
+  limit the MTU to 1K max.
+
+* Man pages:
+  Added opensm.8 and osmtest.8
+
+* Leaf VL stall count control:
+  A new parameter (leaf_vl_stall_count) for controlling the number of
+  sequential packets dropped on a switch port driving a HCA/TCA/Router
+  that cause the port to enter the VLStalled state was added to the
+  options file.
+
+* SM Polling/Handover defaults changed
+  The default SMInfo polling retries was decreased from 18 to 4
+  which reduces the default handover time from 3 min to 40 seconds.
+
+1.3 Library API Changes
+
+* cl_mem* APIs deprecated in complib:
+  These functions are now considered as deprecated and should be
+  replaced by direct calls to malloc, free, memset, etc.
+
+* osm_log_init_v2 API added in libopensm:
+  Supports providing the new option for log file truncation.
+
+1.4 Software Dependencies
+
+OpenSM depends on the installation of either OFED 1.1, OFED 1.0,
+OpenIB gen2 (e.g. IBG2 distribution), OpenIB gen1 (e.g. IBGD
+distribution), or Mellanox VAPI stacks. The qualified driver versions
+are provided in Table 2, "Qualified IB Stacks".
+
+1.5 Supported Devices Firmware
+
+The main task of OpenSM is to initialize InfiniBand devices. The
+qualified devices and their corresponding firmware versions 
+are listed in Table 3.
+
+2 Known Issues And Limitations
+------------------------------
+
+* No Service / Key associations:
+  There is no way to manage Service access by Keys. 
+
+* No SM to SM SMDB synchronization: 
+  Puts the burden of re-registering services, multicast groups, and
+  inform-info on the client application (or IB access layer core). 
+
+* No "port down" event handling:
+  Changing the switch port through which OpenSM connects to the IB
+  fabric may cause incorrect operation. Please restart OpenSM whenever
+  such a connectivity change is made.
+
+* Changing connections during SM operation:
+  Under some conditions the SM can get confused by a change in 
+  cabling (moving a cable from one switch port to the other) and 
+  momentarily see this as having the same GUID appear connected 
+  to two different IB ports. Under some conditions, when the SM fails to 
+  get the corresponding change event it might mistakenly report this case
+  as a "duplicated GUID" case and abort. It is advisable to double-check
+  the syslog after each such change in connectivity and restart
+  OpenSM if it has exited.
+  
+3 Unsupported IB Compliance Statements
+--------------------------------------
+The following section lists all the IB compliance statements which
+OpenSM does not support. Please refer to the IB specification for detailed
+information regarding each compliance statement. 
+
+* C14-22 (Authentication):
+  M_Key M_KeyProtectBits and M_KeyLeasePeriod shall be set in one
+  SubnSet method. As a work-around, an OpenSM option is provided for
+  defining the protect bits.
+
+* C14-67 (Authentication):
+  On SubnGet(SMInfo) and SubnSet(SMInfo) - if M_Key is not zero then
+  the SM shall generate a SubnGetResp if the M_Key matches, or
+  silently drop the packet if M_Key does not match.
+
+* C15-0.1.23.4 (Authentication):
+  InformInfoRecords shall always be provided with the QPN set to 0,
+  except for the case of a trusted request, in which case the actual
+  subscriber QPN shall be returned. 
+
+* o13-17.1.2 (Event-FWD):
+  If no permission to forward, the subscription should be removed and
+  no further forwarding should occur.
+
+* C14-24.1.1.5 and C14-62.1.1.22 (Initialization):
+  GUIDInfo - SM should enable assigning Port GUIDInfo.
+
+* C14-44 (Initialization):
+  If the SM discovers that it is missing an M_Key to update CA/RT/SW,
+  it should notify the higher level.
+
+* C14-62.1.1.12 (Initialization):
+  PortInfo:M_Key - Set the M_Key to a node based random value.
+
+* C14-62.1.1.13 (Initialization):
+  PortInfo:P_KeyProtectBits - set according to an optional policy.
+
+* C14-62.1.1.24 (Initialization):
+  SwitchInfo:DefaultPort - should be configured for random FDB.
+
+* C14-62.1.1.32 (Initialization):
+  RandomForwardingTable should be configured.
+
+* o15-0.1.12 (Multicast):
+  If the JoinState is SendOnlyNonMember = 1 (only), then the endport
+  should join as sender only.
+
+* o15-0.1.8 (Multicast):
+  If a request for creating an MCG with fields that cannot be met,
+  return ERR_REQ_INVALID (currently ignores SL and FlowLabelTClass).
+
+* C15-0.1.8.6 (SA-Query):
+  Respond to SubnAdmGetTraceTable - this is an optional attribute.
+
+* C15-0.1.13 Services:
+  Reject ServiceRecord create, modify or delete if the given
+  ServiceP_Key does not match the one included in the ServiceGID port
+  and the port that sent the request.
+
+* C15-0.1.14 (Services):
+  Provide means to associate service name and ServiceKeys.
+
+4 Major Bug Fixes
+-----------------
+
+The following is a list of bugs that were fixed. Note that other less critical
+or visible bugs were also fixed.
+
+* "Broken" fabric (duplicated port GUIDs) handling improved
+  Replace assert with a real check to handle invalid physical port
+  in osm_node_info_rcv.c which could occur on a broken fabric
+
+* SA client synchronous request failed but status returned was IB_SUCCESS
+  even if there was no response.
+  There was a missing setting of the status in the synchronous case.
+* Memory leak fixes:
+  1. In libvendor/osm_vendor_ibumad.c:osm_vendor_get_all_port_attr
+  2. In libvendor/osm_vendor_ibumad_sa.c:__osmv_sa_mad_rcv_cb
+  3. On receiving SMInfo SA request from a node that does not share a 
+         partition, the response mad was allocated but never free'd 
+         as it was never sent.
+
+* Set(InformInfo) OpenSM Deadlock:
+  When receiving a request with unknown LID
+
+* PathRecord to inconsistent multicast destination:
+  Fix the return error when multicast destination is not consistently
+  indicated.
+
+* Remove double calculation of reversible path 
+  In osm_sa_path_record.c:__osm_pr_rcv_get_lid_pair_path a PathRecord 
+  query used to double check if the path is reversible
+
+* Some PathRecord log messages use "net order":
+  Fix GUID net to host conversion in some osm_log messages
+
+* DR/LID routed SMPs direction bit handling:
+  osm_resp.c:osm_resp_make_resp_smp, set direction bit only if direct
+  routed class. This bug caused two issues:
+  1. Get/Set responses always had direction bit set. 
+  2. Trap represses never had direction bit set.
+  The direction bit needs setting in direct routed responses and it
+  doesn't exist in LID routed responses. 
+  osm_sm_mad_ctrl.c: did not detect the "direction bit" correctly.
+
+* OpenSM crash due to transaction lookup (interop with Cisco stack)
+  When a wire TID that maps to internal TID of zero (after applying
+  mask) was received the lookup of the transaction was successful.
+  The stale transaction pointed to "free'd" memory.
+
+* Better handling for Path/MultiPath requests for raw traffic
+
+* Wrong ProducerType provided in Notice Reports:
+  When formating an SM generated report, the ProducerType was using
+  CL_NTOH32 which can not be used to format a 24bit network order number.
+
+* OpenSM break on PPC64 
+  complib: Fixed memory corruption in cl_pool.c:cl_qcpool_init. This
+  affected big endian 64-bit architectures only. 
+
+* Illegal Set(InformInfo) was wrongly successful in updating the SMDB
+  osm_sa_informinfo.c: In osm_infr_rcv_process_set_method, if sending
+  error, don't call osm_infr_rcv_process_set_method 
+
+* RMPP queries of InformInfoRecord fail
+  ib_types.h: Pad ib_inform_info_record_t to be modulo 8 in size so
+  that attribute offset is calculated properly 
+
+* Returning "invalid request" rather than "unsupported method/attribute"
+  In these cases, a noncompliant response was being provided.
+
+* Noncompliant response for SubnAdmGet(PortInfoRecord) with no match
+  osm_pir_rcv_process, now returns "SA no records error" for SubnAdmGet
+  with 0 records found
+
+* Noncompliant non base LID returned by some queries:
+  The following attributes used to return the request LID rather than
+  its base LID in responses: PKeyTableRecord, GUIDInfoRecord,
+  SLtoVLMappingTableRecord, VLArbitrationTableRecord, LinkRecord
+
+* Noncompliant SubnAdmGet and SubnAdmGetTable:
+  Mixing of error codes in case of no records or multiple records
+  fixed for the attributes: 
+  LinearForwardingTableRecord, GUIDInfoRecord,
+  VLArbitrationTableRecord, LinkRecord, PathRecord
+
+* segfault in InformInfo flows
+  Under stress concurrent Set/Delete/Get flows. Fixed by adding
+  missing lock.
+
+* SA queries containing LID out if range did not return ERR_REQ_INVALID
+
+5 Main Verification Flows
+-------------------------
+
+OpenSM verification is run using the following activities:
+* osmtest - a stand-alone program
+* ibmgtsim (IB management simulator) based - a set of flows that
+  simulate clusters, inject errors and verify OpenSM capability to
+  respond and bring up the network correctly.
+* small cluster regression testing - where the SM is used on back to
+  back or single switch configurations. The regression includes
+  multiple OpenSM dedicated tests.
+* cluster testing - when we run OpenSM to setup a large cluster, perform
+  hand-off, reboots and reconnects, verify routing correctness and SA
+  responsiveness at the ULP level (IPoIB and SDP).
+
+5.1 osmtest
+
+osmtest is an automated verification tool used for OpenSM
+testing. Its verification flows are described by list below. 
+
+* Inventory File: Obtain and verify all port info, node info, link and path
+  records parameters.
+
+* Service Record:
+   - Register new service
+   - Register another service (with a lease period)
+   - Register another service (with service p_key set to zero)
+   - Get all services by name
+   - Delete the first service
+   - Delete the third service
+   - Added bad flows of get/delete  non valid service
+   - Add / Get same service with different data 
+   - Add / Get / Delete by different component  mask values (services
+     by Name & Key / Name & Data / Name & Id / Id only )
+
+* Multicast Member Record: 
+   - Query of existing Groups (IPoIB)
+   - BAD Join with insufficient comp mask (o15.0.1.3)
+   - Create given MGID=0 (o15.0.1.4)
+   - Create given MGID=0xFF12A01C,FE800000,00000000,12345678 (o15.0.1.4)
+   - Create BAD MGID=0xFA. (o15.0.1.6)
+   - Create BAD MGID=0xFF12A01B w/ link-local not set (o15.0.1.6)
+   - New MGID with invalid join state (o15.0.1.9)
+   - Retry of existing MGID - See JoinState update (o15.0.1.11)
+   - BAD RATE when connecting to existing MGID (o15.0.1.13)
+   - Partial JoinState delete request - removing FullMember (o15.0.1.14)
+   - Full Delete of a group (o15.0.1.14)
+   - Verify Delete by trying to Join deleted group (o15.0.1.14)
+   - BAD Delete of IPoIB membership (no prev join) (o15.0.1.15)
+
+* GUIDInfo Record:
+   - All GUIDInfoRecords in subnet are obtained
+
+* MultiPathRecord:
+   - Perform some compliant and noncompliant MultiPathRecord requests
+   - Validation is via status in responses and IB analyzer
+
+* PKeyTableRecord:
+  - Perform some compliant and noncompliant PKeyTableRecord queries
+  - Validation is via status in responses and IB analyzer
+
+* LinearForwardingTableRecord:
+  - Perform some compliant and noncompliant LinearForwardingTableRecord queries
+  - Validation is via status in responses and IB analyzer
+
+* Event Forwarding: Register for trap forwarding using reports
+   - Send a trap and wait for report
+   - Unregister non-existing
+
+* Trap 64/65 Flow: Register to Trap 64-65, create traps (by
+  disconnecting/connecting ports) and wait for report, then unregister.
+
+* Stress Test: send PortInfoRecord queries, both single and RMPP and
+  check for the rate of responses as well as their validity.
+
+
+5.2 IB Management Simulator OpenSM Test Flows:
+
+The simulator provides ability to simulate the SM handling of virtual
+topologies that are not limited to actual lab equipment availability.
+OpenSM was simulated to bring up clusters of up to 10,000 nodes. Daily
+regressions use smaller (16 and 128 nodes clusters).
+
+The following test flows are run on the IB management simulator:
+
+* Stability:
+  Up to 12 links from the fabric are randomly selected to drop packets
+  at drop rates up to 90%. The SM is required to succeed in bringing the
+  fabric up. The resulting routing is verified to be correct as well.
+
+* LID Manager:
+  Using LMC = 2 the fabric is initialized with LIDs. Faults such as
+  zero LID, Duplicated LID, non-aligned (to LMC) LIDs are 
+  randomly assigned to various nodes and other errors are randomly
+  output to the guid2lid cache file. The SM sweep is run 5 times and
+  after each iteration a complete verification is made to ensure that all
+  LIDs that could possibly be maintained are kept, as well as that all nodes
+  were assigned a legal LID range.
+
+* Multicast Routing:
+  Nodes randomly join the 0xc000 group and eventually the
+  resulting routing is verified for completeness and adherence to
+  Up/Down routing rules. 
+
+* osmtest:
+  The complete osmtest flow as described in the previous table is run on
+  the simulated fabrics.
+
+* Stress Test:
+  This flow merges fabric, LID and stability issues with continuous 
+  PathRecord, ServiceRecord and Multicast Join/Leave activity to
+  stress the SM/SA during continuous sweeps. InformInfo Set/Delete/Get
+  were added to the test such both existing and non existing nodes
+  perform them in random order.
+
+5.3 OpenSM Regression
+
+Using a back-to-back or single switch connection, the following set of
+tests is run nightly on the stacks described in table 2. The included
+tests are:
+
+* Stress Testing: Flood the SA with queries from multiple channel
+  adapters to check the robustness of the entire stack up to the SA.
+
+* Dynamic Changes: Dynamic Topology changes, through randomly
+  dropping SMP packets, used to test OpenSM adaptation to an unstable
+  network & verify DB correctness.
+
+* Trap Injection: This flow injects traps to the SM and verifies that it
+  handles them gracefully. 
+
+* SA Query Test: This test exhaustively checks the SA responses to all
+  possible single component mask. To do that the test examines the
+  entire set of records the SA can provide, classifies them by their
+  field values and then selects every field (using component mask and a
+  value) and verifies that the response matches the expected set of records.
+  A random selection using multiple component mask bits is also performed.
+
+5.4 Cluster testing:
+
+Cluster testing is usually run before a distribution release. It
+involves real hardware setups of 16 to 32 nodes (or more if a beta site
+is available). Each test is validated by running all-to-all ping through the IB
+interface. The test procedure includes:
+
+* Cluster bringup 
+
+* Hand-off between 2 or 3 SM's while performing:
+  - Node reboots
+  - Switch power cycles (disconnecting the SM's)
+
+* Unresponsive port detection and recovery
+
+* osmtest from multiple nodes
+
+* Trap injection and recovery
+
+
+6 Qualification 
+----------------
+
+Table 2 - Qualified IB Stacks
+=============================
+
+Stack                                    | Version
+-----------------------------------------|--------------------------
+OFED                                     |   1.1
+OFED                                     |   1.0
+OpenIB Gen2 (IBG2 distribution)          |   1.0
+OpenIB Gen1 (IBGD distribution)          |   1.8.0
+VAPI (Mellanox InfiniBand HCA Driver)    |   3.2 and later
+
+Table 3 - Qualified Devices and Corresponding Firmware 
+======================================================
+
+Mellanox
+Device  |   FW versions 
+--------|-----------------------------------------------------------
+MT43132 |   InfiniScale - fw-43132  5.2.0 (and later)
+MT47396 |   InfiniScale III - fw-47396 0.5.0 (and later)
+MT23108 |   InfiniHost - fw-23108   3.3.2 (and later)
+MT25204 |   InfiniHost III Lx - fw-25204  1.0.1i (and later)
+MT25208 |   InfiniHost III Ex (InfiniHost Mode) - fw-25208  4.6.2 (and later)
+MT25208 |   InfiniHost III Ex (MemFree Mode) - fw-25218  5.0.1 (and later)
+
+QLogic/PathScale
+Device  |   Note
+--------|-----------------------------------------------------------
+iPath   | QHT6040 (PathScale InfiniPath HT-460)
+iPath   | QHT6140 (PathScale InfiniPath HT-465)
+iPath   | QLE6140 (PathScale InfiniPath PE-880)
+
+Note: OpenSM does not run on an IBM Galaxy (eHCA) as it does not expose 
+QP0 and QP1. However, it does support it as a device on the subnet.
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/qos-config.txt b/branches/WOF2-2/ulp/opensm/user_3_0_0/doc/qos-config.txt
new file mode 100644 (file)
index 0000000..c90e6f7
--- /dev/null
@@ -0,0 +1,45 @@
+Trivial low level QoS configuration proposition
+===============================================
+
+Basically there is a set of QoS related low-level configuration parameters.
+All these parameter names are prefixed by "qos_" string. Here is a full
+list of these parameters:
+
+  qos_max_vls    - The maximum number of VLs that will be on the subnet
+  qos_high_limit - The limit of High Priority component of VL Arbitration
+                   table (IBA 7.6.9)
+  qos_vlarb_low  - High priority VL Arbitration table (IBA 7.6.9) template
+  qos_vlarb_high - Low priority VL Arbitration table (IBA 7.6.9) template
+                   Both VL arbitration templates are pairs of VL and weight
+  qos_sl2vl      - SL2VL Mapping table (IBA 7.6.6) template. It is a list
+                   of VLs corresponding to SLs 0-15 (Note the VL15 used
+                   here means drop this SL)
+
+Typical default values (hard-coded in OpenSM initialization) are:
+
+  qos_max_vls=15
+  qos_high_limit=0
+  qos_vlarb_low=0:0,1:4,2:4,3:4,4:4,5:4,6:4,7:4,8:4,9:4,10:4,11:4,12:4,13:4,14:4
+  qos_vlarb_high=0:4,1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0,10:0,11:0,12:0,13:0,14:0
+  qos_sl2vl=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,7
+
+The syntax is compatible with rest of OpenSM configuration options and
+values may be stored in OpenSM config file (cached options file).
+
+In addition to the above, we may define separate QoS configuration
+parameters sets for various target types. As targets, we currently support
+CAs, routers, switch external ports, and switch's enhanced port 0. The
+names of such specialized parameters are prefixed by "qos_<type>_"
+string. Here is a full list of the currently supported sets:
+
+  qos_ca_  - QoS configuration parameters set for CAs.
+  qos_rtr_ - parameters set for routers.
+  qos_sw0_ - parameters set for switches' port 0.
+  qos_swe_ - parameters set for switches' external ports.
+
+Examples:
+
+  qos_sw0_max_vls=2
+  qos_ca_sl2vl=0,1,2,3,5,5,5,12,12,0,
+  qos_swe_high_limit=0
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/Makefile b/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/Makefile
new file mode 100644 (file)
index 0000000..9c985f5
--- /dev/null
@@ -0,0 +1,7 @@
+#\r
+# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source\r
+# file to this component.  This file merely indirects to the real make file\r
+# that is shared by all the driver components of the Windows NT DDK\r
+#\r
+\r
+!INCLUDE $(NTMAKEENV)\makefile.def\r
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/SOURCES b/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/SOURCES
new file mode 100644 (file)
index 0000000..c58e0c7
--- /dev/null
@@ -0,0 +1,64 @@
+!if $(FREEBUILD)\r
+TARGETNAME=ibtrapgen\r
+!else\r
+TARGETNAME=ibtrapgend\r
+!endif\r
+\r
+!if !defined(WINIBHOME)\r
+WINIBHOME=..\..\..\..\r
+!endif\r
+\r
+LIBPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)\r
+\r
+!if defined(OSM_TARGET)\r
+TARGETPATH=$(OSM_TARGET)\bin\user\obj$(BUILD_ALT_DIR)\r
+!else\r
+TARGETPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)\r
+!endif\r
+\r
+TARGETTYPE=PROGRAM\r
+UMTYPE=console\r
+USE_MSVCRT=1\r
+OVR_DIR=..\addon\r
+\r
+\r
+SOURCES=\\r
+       main.c \\r
+       ibtrapgen.c\r
+\r
+\r
+\r
+OSM_HOME=..\r
+\r
+TARGETLIBS=\\r
+!if $(FREEBUILD)\r
+                       $(LIBPATH)\*\ibal.lib \\r
+                       $(LIBPATH)\*\complib.lib \\r
+                       $(TARGETPATH)\*\osmv_ibal.lib \\r
+                       $(TARGETPATH)\*\opensm_ibal.lib\r
+!else\r
+                       $(LIBPATH)\*\ibald.lib \\r
+                       $(LIBPATH)\*\complibd.lib \\r
+                       $(TARGETPATH)\*\osmv_ibald.lib \\r
+                       $(TARGETPATH)\*\opensm_ibald.lib\r
+!endif\r
+\r
+#DO NOT TOUCH the order of search path , until ib_types.h merging process will be done\r
+INCLUDES= \\r
+       $(OSM_HOME)\include; \\r
+       $(OSM_HOME); \\r
+       $(WINIBHOME)\inc; \\r
+       $(WINIBHOME)\inc\user;\r
+\r
+# Could be any special flag needed for this project \r
+USER_C_FLAGS=$(USER_C_FLAGS) /MD\r
+#Add preproccessor definitions\r
+C_DEFINES=$(C_DEFINES) -DWIN32 -D__WIN__ -D__i386__ -Dinline=__inline -DMT_LITTLE_ENDIAN -DOSM_VENDOR_INTF_AL\r
+!if !$(FREEBUILD)\r
+#C_DEFINES=$(C_DEFINES) -D_DEBUG -DDEBUG -DDBG\r
+C_DEFINES=$(C_DEFINES) \r
+!endif\r
+\r
+LINKER_FLAGS= $(LINKER_FLAGS)\r
+MSC_WARNING_LEVEL= /W3\r
+\r
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/ibtrapgen.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/ibtrapgen.c
new file mode 100644 (file)
index 0000000..bd37882
--- /dev/null
@@ -0,0 +1,442 @@
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+  This software program is available to you under a choice of one of two
+  licenses.  You may choose to be licensed under either the GNU General Public
+  License (GPL) Version 2, June 1991, available at
+  http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License,
+  the text of which follows:
+
+  "Recipient" has requested a license and Intel Corporation ("Intel")
+  is willing to grant a license for the software entitled
+  InfiniBand(tm) System Software (the "Software") being provided by
+  Intel Corporation.
+
+  The following definitions apply to this License:
+
+  "Licensed Patents" means patent claims licensable by Intel Corporation which
+  are necessarily infringed by the use or sale of the Software alone or when
+  combined with the operating system referred to below.
+
+  "Recipient" means the party to whom Intel delivers this Software.
+  "Licensee" means Recipient and those third parties that receive a license to
+  any operating system available under the GNU Public License version 2.0 or
+  later.
+
+  Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+
+  The license is provided to Recipient and Recipient's Licensees under the
+  following terms.
+
+  Redistribution and use in source and binary forms of the Software, with or
+  without modification, are permitted provided that the following
+  conditions are met:
+  Redistributions of source code of the Software may retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form of the Software may reproduce the above
+  copyright notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of Intel Corporation nor the names of its contributors shall
+  be used to endorse or promote products derived from this Software without
+  specific prior written permission.
+
+  Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+  royalty-free patent license under Licensed Patents to make, use, sell, offer
+  to sell, import and otherwise transfer the Software, if any, in source code
+  and object code form. This license shall include changes to the Software that
+  are error corrections or other minor changes to the Software that do not add
+  functionality or features when the Software is incorporated in any version of
+  a operating system that has been distributed under the GNU General Public
+  License 2.0 or later.  This patent license shall apply to the combination of
+  the Software and any operating system licensed under the GNU Public License
+  version 2.0 or later if, at the time Intel provides the Software to
+  Recipient, such addition of the Software to the then publicly
+  available versions of such operating system available under the GNU
+  Public License version 2.0 or later (whether in gold, beta or alpha
+  form) causes such combination to be covered by the Licensed
+  Patents. The patent license shall not apply to any other
+  combinations which include the Software. No hardware per se is
+  licensed hereunder.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS CONTRIBUTORS
+  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+  OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+  --------------------------------------------------------------------------*/
+
+/*
+ * Abstract:
+ *    Implementation of ibtrapgen_t.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+#include <complib/cl_qmap.h>
+#include <opensm/osm_log.h>
+#include <complib/cl_debug.h>
+#include <vendor/osm_vendor_api.h>
+#include <vendor/osm_vendor_sa_api.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_helper.h>
+#include "ibtrapgen.h"
+
+#define GUID_ARRAY_SIZE 64
+
+/**********************************************************************
+ **********************************************************************/
+/*
+  This function initializes the main object, the log and the Osm Vendor
+*/
+ib_api_status_t
+ibtrapgen_init( IN ibtrapgen_t * const p_ibtrapgen,
+              IN ibtrapgen_opt_t * const p_opt,
+              IN const osm_log_level_t log_flags
+              )
+{
+  ib_api_status_t status;
+
+  /* just making sure - cleanup the static global obj */
+  cl_memclr( p_ibtrapgen, sizeof( *p_ibtrapgen ) );
+
+  /* construct and init the log */
+  p_ibtrapgen->p_log = (osm_log_t *)cl_malloc(sizeof(osm_log_t));
+  osm_log_construct( p_ibtrapgen->p_log );
+  status = osm_log_init( p_ibtrapgen->p_log, p_opt->force_log_flush,
+                         0x0001, p_opt->log_file,FALSE );
+  if( status != IB_SUCCESS )
+    return ( status );
+
+  osm_log_set_level( p_ibtrapgen->p_log, log_flags );
+
+  /* finaly can declare we are here ... */
+  osm_log( p_ibtrapgen->p_log, OSM_LOG_FUNCS,
+           "ibtrapgen_init: [\n" );
+
+  /* assign all the opts */
+  p_ibtrapgen->p_opt = p_opt;
+
+  /* initialize the osm vendor service object */
+  p_ibtrapgen->p_vendor = osm_vendor_new( p_ibtrapgen->p_log,
+                                        p_opt->transaction_timeout );
+
+  if( p_ibtrapgen->p_vendor == NULL )
+  {
+    status = IB_INSUFFICIENT_RESOURCES;
+    osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR,
+             "ibtrapgen_init: ERR 0001: "
+             "Unable to allocate vendor object" );
+    goto Exit;
+  }
+
+  /* all mads (actually wrappers) are taken and returned to a pool */
+  osm_mad_pool_construct( &p_ibtrapgen->mad_pool );
+  status = osm_mad_pool_init(
+    &p_ibtrapgen->mad_pool, p_ibtrapgen->p_log );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+ Exit:
+  osm_log( p_ibtrapgen->p_log, OSM_LOG_FUNCS,
+           "ibtrapgen_init: ]\n" );
+  return ( status );
+}
+
+/****f* opensm: SM/__ibtrapgen_rcv_callback
+ * NAME
+ * __osm_sm_mad_ctrl_rcv_callback
+ *
+ * DESCRIPTION
+ * This is the callback from the transport layer for received MADs.
+ *
+ * SYNOPSIS
+ */
+void
+__ibtrapgen_rcv_callback(
+  IN osm_madw_t *p_madw,
+  IN void *bind_context,
+  IN osm_madw_t *p_req_madw )
+{
+  ibtrapgen_t* p_ibtrapgen = (ibtrapgen_t*)bind_context;
+
+  OSM_LOG_ENTER( p_ibtrapgen->p_log, __ibtrapgen_rcv_callback );
+
+  CL_ASSERT( p_madw );
+
+  osm_log( p_ibtrapgen->p_log, OSM_LOG_VERBOSE,
+           "__ibtrapgen_rcv_callback: Got callback\n",
+           cl_ntoh64(p_madw->p_mad->trans_id) );
+
+  OSM_LOG_EXIT( p_ibtrapgen->p_log );
+}
+
+/****f* opensm: SM/__ibtrapgen_send_err_cb
+ * NAME
+ * __ibtrapgen_send_err_cb
+ *
+ * DESCRIPTION
+ * This is the callback from the transport layer for received MADs.
+ *
+ * SYNOPSIS
+ */
+void
+__ibtrapgen_send_err_cb(
+  IN void *bind_context,
+  IN osm_madw_t *p_madw )
+{
+  ibtrapgen_t* p_ibtrapgen = (ibtrapgen_t*)bind_context;
+
+  OSM_LOG_ENTER( p_ibtrapgen->p_log, __ibtrapgen_send_err_callback );
+
+  osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR,
+           "__ibtrapgen_send_err_cb: ERR 0011: "
+           "MAD completed in error (%s).\n",
+           ib_get_err_str( p_madw->status ) );
+
+  CL_ASSERT( p_madw );
+
+  osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR,
+           "__ibtrapgen_send_err_cb: ERR 0012: "
+           "We shouldn't be here!! TID:0x%016" PRIx64 ".\n",
+           cl_ntoh64(p_madw->p_mad->trans_id) );
+  OSM_LOG_EXIT( p_ibtrapgen->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+ibtrapgen_bind( IN ibtrapgen_t * p_ibtrapgen )
+{
+  ib_api_status_t status;
+  uint32_t num_ports = GUID_ARRAY_SIZE;
+  ib_port_attr_t attr_array[GUID_ARRAY_SIZE];
+  osm_bind_info_t bind_info;
+  uint8_t i;
+
+  OSM_LOG_ENTER( p_ibtrapgen->p_log, ibtrapgen_bind );
+
+  /*
+   * Call the transport layer for a list of local port
+   * GUID values.
+   */
+  status = osm_vendor_get_all_port_attr( p_ibtrapgen->p_vendor,
+                                         attr_array, &num_ports );
+  if ( status != IB_SUCCESS )
+  {
+    osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR,
+             "ibtrapgen_bind: ERR 0002: "
+             "Failure getting local port attributes (%s)\n",
+             ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  /* make sure the requested port exists */
+  if ( p_ibtrapgen->p_opt->port_num > num_ports )
+  {
+    osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR,
+             "ibtrapgen_bind: ERR 0003: "
+             "Given port number out of range %u > %u\n",
+             p_ibtrapgen->p_opt->port_num , num_ports );
+    status = IB_NOT_FOUND;
+    goto Exit;
+  }
+
+  for ( i = 0 ; i < num_ports ; i++ )
+  {
+    osm_log(p_ibtrapgen->p_log, OSM_LOG_INFO,
+            "ibtrapgen_bind: Found port number:%u "
+            " with GUID:0x%016" PRIx64 "\n",
+            i, cl_ntoh64(attr_array[i].port_guid) );
+  }
+  /* check if the port is active */
+/*   if (attr_array[p_ibtrapgen->p_opt->port_num - 1].link_state < 4) */
+/*   { */
+/*     osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR, */
+/*              "ibtrapgen_bind: ERR 0004: " */
+/*              "Given port number link state is not active: %s.\n", */
+/*              ib_get_port_state_str( */
+/*                attr_array[p_ibtrapgen->p_opt->port_num - 1].link_state ) */
+/*              ); */
+/*     status = IB_NOT_FOUND; */
+/*     goto Exit; */
+/*   } */
+
+  p_ibtrapgen->port_guid = attr_array[p_ibtrapgen->p_opt->port_num - 1].port_guid;
+ /* save sm_lid as we need it when sending the Trap (dest lid)*/
+  p_ibtrapgen->p_opt->sm_lid = attr_array[p_ibtrapgen->p_opt->port_num - 1].sm_lid;
+
+  osm_log(p_ibtrapgen->p_log, OSM_LOG_DEBUG,
+          "ibtrapgen_bind: Port Num:%u "
+          "GUID:0x%016"PRIx64"\n",
+          p_ibtrapgen->p_opt->port_num,
+          p_ibtrapgen->port_guid );
+
+  /* ok finaly bind the sa interface to this port */
+  /* TODO - BIND LIKE THE osm_sm_mad_ctrl does */
+  bind_info.class_version = 1;
+  bind_info.is_report_processor = TRUE;
+  bind_info.is_responder = TRUE;
+  bind_info.is_trap_processor = TRUE;
+  bind_info.mad_class = IB_MCLASS_SUBN_LID;
+  bind_info.port_guid = p_ibtrapgen->port_guid;
+  bind_info.recv_q_size = OSM_SM_DEFAULT_QP0_RCV_SIZE;
+  bind_info.send_q_size = OSM_SM_DEFAULT_QP0_SEND_SIZE;
+
+  osm_log(p_ibtrapgen->p_log, OSM_LOG_DEBUG,
+          "ibtrapgen_bind: Trying to bind to GUID:0x%016"PRIx64"\n",
+          bind_info.port_guid );
+  p_ibtrapgen->h_bind = osm_vendor_bind( p_ibtrapgen->p_vendor,
+                                    &bind_info,
+                                    &p_ibtrapgen->mad_pool,
+                                    __ibtrapgen_rcv_callback,
+                                    __ibtrapgen_send_err_cb,
+                                    p_ibtrapgen );
+
+  if(  p_ibtrapgen->h_bind == OSM_BIND_INVALID_HANDLE )
+  {
+    osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR,
+             "ibtrapgen_bind: ERR 0005: "     
+             "Unable to bind to SA\n" );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_ibtrapgen->p_log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+ibtrapgen_destroy( IN ibtrapgen_t * p_ibtrapgen )
+{
+  if( p_ibtrapgen->p_vendor )
+  {
+    osm_vendor_delete( &p_ibtrapgen->p_vendor );
+  }
+
+  osm_log_destroy( p_ibtrapgen->p_log );
+  cl_free( p_ibtrapgen->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+ibtrapgen_run( IN ibtrapgen_t * const p_ibtrapgen )
+{
+  osm_madw_t*    p_report_madw;
+  ib_mad_notice_attr_t*   p_report_ntc;
+  ib_mad_t*               p_mad;
+  ib_smp_t*               p_smp_mad;
+  osm_mad_addr_t          mad_addr;
+  static atomic32_t       trap_fwd_trans_id = 0x02DAB000; 
+  ib_api_status_t         status;
+  osm_log_t *p_log =      p_ibtrapgen->p_log;
+  uint16_t                i;
+
+  OSM_LOG_ENTER( p_log, ibtrapgen_run );
+
+  osm_log( p_log, OSM_LOG_INFO,
+           "ibtrapgen_run: "
+           "Sending trap:%u from LID:0x%X %u times\n",
+           p_ibtrapgen->p_opt->trap_num,
+           p_ibtrapgen->p_opt->lid,
+           p_ibtrapgen->p_opt->number );
+  
+  printf("-V- SM lid is : 0x%04X\n",cl_ntoh16(p_ibtrapgen->p_opt->sm_lid));
+  mad_addr.dest_lid = (p_ibtrapgen->p_opt->sm_lid);
+  /* ??? - what is path_bits? What should be the value here?? */
+  mad_addr.path_bits = 0;
+  /* ??? - what is static_rate? What should be the value here?? */
+  mad_addr.static_rate = 0;
+  
+  mad_addr.addr_type.smi.source_lid = cl_hton16(p_ibtrapgen->p_opt->lid);
+  mad_addr.addr_type.smi.port_num = p_ibtrapgen->p_opt->src_port;
+  
+  for (i = 1 ; i <= p_ibtrapgen->p_opt->number ; i++ )
+  {
+    p_report_madw = osm_mad_pool_get( &p_ibtrapgen->mad_pool,
+                                      p_ibtrapgen->h_bind,
+                                      MAD_BLOCK_SIZE,
+                                      &mad_addr );
+    
+    if( !p_report_madw )
+    {
+      osm_log(p_log, OSM_LOG_ERROR,
+              "ibtrapgen_run: ERR 00020: "
+              "osm_mad_pool_get failed.\n" );
+      status = IB_ERROR;
+      goto Exit;
+    }
+                                    
+    p_report_madw->resp_expected = FALSE;
+
+    /* advance trap trans id (cant simply ++ on some systems inside ntoh) */
+    p_mad = osm_madw_get_mad_ptr( p_report_madw );
+    ib_mad_init_new(p_mad,
+                    IB_MCLASS_SUBN_LID,
+                    1,
+                    IB_MAD_METHOD_TRAP,
+                    cl_hton64( (uint64_t)cl_atomic_inc( &trap_fwd_trans_id ) ),
+                    IB_MAD_ATTR_NOTICE,
+                    0);
+    
+    p_smp_mad = osm_madw_get_smp_ptr( p_report_madw );
+    
+    /* The payload is analyzed as mad notice attribute */
+    p_report_ntc = (ib_mad_notice_attr_t*)(ib_smp_get_payload_ptr(p_smp_mad));
+    
+    cl_memclr( p_report_ntc, sizeof(*p_report_ntc) );
+    p_report_ntc->generic_type = 0x83; /* is generic subn mgt type */
+    ib_notice_set_prod_type(p_report_ntc, 2); /* A switch generator */
+    p_report_ntc->g_or_v.generic.trap_num = cl_hton16(p_ibtrapgen->p_opt->trap_num);
+    p_report_ntc->issuer_lid = cl_hton16(p_ibtrapgen->p_opt->lid);
+    if (p_ibtrapgen->p_opt->trap_num == 128)
+    {
+      p_report_ntc->data_details.ntc_128.sw_lid = cl_hton16(p_ibtrapgen->p_opt->lid);
+    }
+    else 
+    {
+      p_report_ntc->data_details.ntc_129_131.lid = 
+        cl_hton16(p_ibtrapgen->p_opt->lid);
+      p_report_ntc->data_details.ntc_129_131.port_num = 
+        p_ibtrapgen->p_opt->src_port;
+    }
+
+    status = osm_vendor_send(p_report_madw->h_bind, p_report_madw, FALSE );
+    if (status != IB_SUCCESS)
+    {
+      osm_log(p_log, OSM_LOG_ERROR,
+              "ibtrapgen_run: ERR 0021: "
+              "osm_vendor_send. status = %s\n",
+              ib_get_err_str(status));
+      goto Exit;
+    }
+    osm_log(p_log, OSM_LOG_INFO,
+            "ibtrapgen_run: "
+            "Sent trap number:%u out of:%u\n",
+            i,
+            p_ibtrapgen->p_opt->number );
+    /* sleep according to rate time. The usleep is in usec - need to revert
+       the milisecs to usecs. */
+    usleep(p_ibtrapgen->p_opt->rate*1000);
+  }
+
+ Exit:
+  //  sleep(3);
+  OSM_LOG_EXIT( p_log );
+  return(status);
+}
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/ibtrapgen.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/ibtrapgen.h
new file mode 100644 (file)
index 0000000..6fe5486
--- /dev/null
@@ -0,0 +1,313 @@
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+  This software program is available to you under a choice of one of two
+  licenses.  You may choose to be licensed under either the GNU General Public
+  License (GPL) Version 2, June 1991, available at
+  http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License,
+  the text of which follows:
+
+  "Recipient" has requested a license and Intel Corporation ("Intel")
+  is willing to grant a license for the software entitled
+  InfiniBand(tm) System Software (the "Software") being provided by
+  Intel Corporation.
+
+  The following definitions apply to this License:
+
+  "Licensed Patents" means patent claims licensable by Intel Corporation which
+  are necessarily infringed by the use or sale of the Software alone or when
+  combined with the operating system referred to below.
+
+  "Recipient" means the party to whom Intel delivers this Software.
+  "Licensee" means Recipient and those third parties that receive a license to
+  any operating system available under the GNU Public License version 2.0 or
+  later.
+
+  Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+
+  The license is provided to Recipient and Recipient's Licensees under the
+  following terms.
+
+  Redistribution and use in source and binary forms of the Software, with or
+  without modification, are permitted provided that the following
+  conditions are met:
+  Redistributions of source code of the Software may retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form of the Software may reproduce the above
+  copyright notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of Intel Corporation nor the names of its contributors shall
+  be used to endorse or promote products derived from this Software without
+  specific prior written permission.
+
+  Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+  royalty-free patent license under Licensed Patents to make, use, sell, offer
+  to sell, import and otherwise transfer the Software, if any, in source code
+  and object code form. This license shall include changes to the Software that
+  are error corrections or other minor changes to the Software that do not add
+  functionality or features when the Software is incorporated in any version of
+  a operating system that has been distributed under the GNU General Public
+  License 2.0 or later.  This patent license shall apply to the combination of
+  the Software and any operating system licensed under the GNU Public License
+  version 2.0 or later if, at the time Intel provides the Software to
+  Recipient, such addition of the Software to the then publicly
+  available versions of such operating system available under the GNU
+  Public License version 2.0 or later (whether in gold, beta or alpha
+  form) causes such combination to be covered by the Licensed
+  Patents. The patent license shall not apply to any other
+  combinations which include the Software. No hardware per se is
+  licensed hereunder.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS CONTRIBUTORS
+  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+  OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+  --------------------------------------------------------------------------*/
+
+
+/*
+ * Abstract:
+ *    Declaration of ibtrapgen_t.
+ * This object represents the ibtrapgen object.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.1 $
+ */
+
+#ifndef _IBTRAPGEN_H_
+#define _IBTRAPGEN_H_
+
+#include <complib/cl_qmap.h>
+#include <vendor/osm_vendor_api.h>
+#include <vendor/osm_vendor_sa_api.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_helper.h>
+
+/****h* Trap_Generator_App/Ibtrapgen
+ * NAME
+ * Ibtrapgen
+ *
+ * DESCRIPTION
+ * The Ibtrapgen object create/join and leave multicast group.
+ *
+ * AUTHOR
+ * Yael Kalka, Mellanox.
+ *
+ *********/
+
+/****s* Trap_Generator_App/ibtrapgen_opt_t
+ * NAME
+ * ibtrapgen_opt_t
+ *
+ * DESCRIPTION
+ * Ibtrapgen options structure.  This structure contains the various
+ * specific configuration parameters for ibtrapgen.
+ *
+ * SYNOPSYS
+ */
+typedef struct _ibtrapgen_opt
+{
+  uint8_t   trap_num;
+  uint16_t  number;
+  uint16_t  rate;
+  uint16_t  lid;
+  uint16_t  sm_lid;
+  uint8_t  src_port;
+  uint8_t  port_num;
+  uint32_t  transaction_timeout;
+  boolean_t force_log_flush;
+  char *log_file;
+} ibtrapgen_opt_t;
+/*
+ * FIELDS
+ *
+ * trap_num
+ *    Trap number to generate.
+ *
+ * number
+ *    Number of times trap should be generated.
+ *
+ * rate
+ *    Rate of trap generation (in miliseconds)
+ *
+ * lid
+ *    Lid from which the trap should be generated.
+ *
+ * src_port
+ *   Source port from which the trap should be generated.
+ *
+ * port_num
+ *   Port num used for communicating with the SA.
+ * 
+ * SEE ALSO
+ *********/
+
+/****s* Trap Generator App/ibtrapgen_t
+ * NAME
+ * ibtrapgen_t
+ *
+ * DESCRIPTION
+ * Ibtrapgen structure.
+ *
+ * This object should be treated as opaque and should
+ * be manipulated only through the provided functions.
+ *
+ * SYNOPSYS
+ */
+typedef struct _ibtrapgen
+{
+  osm_log_t          *p_log;
+  struct _osm_vendor *p_vendor;
+  osm_bind_handle_t   h_bind;
+  osm_mad_pool_t      mad_pool;
+
+  ibtrapgen_opt_t    *p_opt;
+  ib_net64_t          port_guid;
+} ibtrapgen_t;
+/*
+ * FIELDS
+ * p_log
+ *    Log facility used by all Ibtrapgen components.
+ *
+ * p_vendor
+ *    Pointer to the vendor transport layer.
+ *
+ *  h_bind
+ *     The bind handle obtained by osm_vendor_sa_api/osmv_bind_sa
+ *
+ *  mad_pool
+ *     The mad pool provided for teh vendor layer to allocate mad wrappers in
+ *
+ * p_opt
+ *    ibtrapgen options structure
+ *
+ * guid
+ *    guid for the port over which ibtrapgen is running.
+ *
+ * SEE ALSO
+ *********/
+
+/****f* Trap_Generator_App/ibtrapgen_destroy
+ * NAME
+ * ibtrapgen_destroy
+ *
+ * DESCRIPTION
+ * The ibtrapgen_destroy function destroys an ibtrapgen object, releasing
+ * all resources.
+ *
+ * SYNOPSIS
+ */
+void ibtrapgen_destroy( IN ibtrapgen_t * p_ibtrapgen );
+
+/*
+ * PARAMETERS
+ * p_ibtrapgen
+ *    [in] Pointer to a Trap_Generator_App object to destroy.
+ *
+ * RETURN VALUE
+ * This function does not return a value.
+ *
+ * NOTES
+ * Performs any necessary cleanup of the specified Trap_Generator_App object.
+ * Further operations should not be attempted on the destroyed object.
+ * This function should only be called after a call to ibtrapgen_init.
+ *
+ * SEE ALSO
+ * ibtrapgen_init
+ *********/
+
+/****f* Trap_Generator_App/ibtrapgen_init
+ * NAME
+ * ibtrapgen_init
+ *
+ * DESCRIPTION
+ * The ibtrapgen_init function initializes a Trap_Generator_App object for use.
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t ibtrapgen_init( IN ibtrapgen_t * const p_ibtrapgen,
+                              IN ibtrapgen_opt_t * const p_opt,
+                              IN const osm_log_level_t log_flags
+                              );
+
+/*
+ * PARAMETERS
+ * p_ibtrapgen
+ *    [in] Pointer to an ibtrapgen_t object to initialize.
+ *
+ * p_opt
+ *    [in] Pointer to the options structure.
+ *
+ * log_flags
+ *    [in] Log level flags to set.
+ *
+ * RETURN VALUES
+ * IB_SUCCESS if the Trap_Generator_App object was initialized successfully.
+ *
+ * NOTES
+ * Allows calling other Trap_Generator_App methods.
+ *
+ * SEE ALSO
+ * ibtrapgen object, ibtrapgen_construct, ibtrapgen_destroy
+ *********/
+
+
+/****f* Trap_Generator_App/ibtrapgen_bind
+ * NAME
+ * ibtrapgen_bind
+ *
+ * DESCRIPTION
+ * Binds ibtrapgen to a local port.
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t ibtrapgen_bind( IN ibtrapgen_t * p_ibtrapgen );
+/*
+ * PARAMETERS
+ * p_ibtrapgen
+ *    [in] Pointer to an ibtrapgen_t object.
+ *
+ * RETURN VALUES
+ * IB_SUCCESS if OK
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* Trap_Generator_App/ibtrapgen_run
+ * NAME
+ * ibtrapgen_run
+ *
+ * DESCRIPTION
+ * Runs the ibtrapgen flow: Creation of traps.
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t ibtrapgen_run( IN ibtrapgen_t * const p_ibtrapgen );
+
+/*
+ * PARAMETERS
+ * p_ibtrapgen
+ *    [in] Pointer to an ibtrapgen_t object.
+ *
+ * RETURN VALUES
+ * IB_SUCCESS on success
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+#endif /* */
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/main.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/ibtrapgen/main.c
new file mode 100644 (file)
index 0000000..f7f1de7
--- /dev/null
@@ -0,0 +1,465 @@
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+  This software program is available to you under a choice of one of two
+  licenses.  You may choose to be licensed under either the GNU General Public
+  License (GPL) Version 2, June 1991, available at
+  http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License,
+  the text of which follows:
+
+  "Recipient" has requested a license and Intel Corporation ("Intel")
+  is willing to grant a license for the software entitled
+  InfiniBand(tm) System Software (the "Software") being provided by
+  Intel Corporation.
+
+  The following definitions apply to this License:
+
+  "Licensed Patents" means patent claims licensable by Intel Corporation which
+  are necessarily infringed by the use or sale of the Software alone or when
+  combined with the operating system referred to below.
+
+  "Recipient" means the party to whom Intel delivers this Software.
+  "Licensee" means Recipient and those third parties that receive a license to
+  any operating system available under the GNU Public License version 2.0 or
+  later.
+
+  Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+
+  The license is provided to Recipient and Recipient's Licensees under the
+  following terms.
+
+  Redistribution and use in source and binary forms of the Software, with or
+  without modification, are permitted provided that the following
+  conditions are met:
+  Redistributions of source code of the Software may retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form of the Software may reproduce the above
+  copyright notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of Intel Corporation nor the names of its contributors shall
+  be used to endorse or promote products derived from this Software without
+  specific prior written permission.
+
+  Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+  royalty-free patent license under Licensed Patents to make, use, sell, offer
+  to sell, import and otherwise transfer the Software, if any, in source code
+  and object code form. This license shall include changes to the Software that
+  are error corrections or other minor changes to the Software that do not add
+  functionality or features when the Software is incorporated in any version of
+  a operating system that has been distributed under the GNU General Public
+  License 2.0 or later.  This patent license shall apply to the combination of
+  the Software and any operating system licensed under the GNU Public License
+  version 2.0 or later if, at the time Intel provides the Software to
+  Recipient, such addition of the Software to the then publicly
+  available versions of such operating system available under the GNU
+  Public License version 2.0 or later (whether in gold, beta or alpha
+  form) causes such combination to be covered by the Licensed
+  Patents. The patent license shall not apply to any other
+  combinations which include the Software. No hardware per se is
+  licensed hereunder.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS CONTRIBUTORS
+  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+  OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+  --------------------------------------------------------------------------*/
+
+
+/*
+ * Abstract:
+ *    Command line interface for ibtrapgen.
+ *    Parse and fill in the options and call the actual code.
+ *    Implemented in ibtrapgen:
+ *     Initialize the ibmgrp object (and log) 
+ *     Bind ibmgrp to the requested IB port.
+ *     Run the actual command
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.1 $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef __WIN__
+#include <getopt.h>
+#endif
+#include <complib/cl_debug.h>
+#include <errno.h>
+#include "ibtrapgen.h"
+
+#define DEFAULT_RETRY_COUNT 3
+#define DEFAULT_TRANS_TIMEOUT_MILLISEC 1000
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+ibtrapgen_is_debug()
+{
+#if defined( _DEBUG_ )
+  return TRUE;
+#else
+  return FALSE;
+#endif /* defined( _DEBUG_ ) */
+}
+
+/**********************************************************************
+ **********************************************************************/
+void show_usage(void);
+
+void
+show_usage(  )
+{
+  printf( "\n------- ibtrapgen - Usage and options ----------------------\n" );
+  printf( "Usage: one of the following optional flows:\n" );
+  printf(" ibtrapgen -t|--trap_num <TRAP_NUM> -n|--number <NUM_TRAP_CREATIONS>\n" 
+         "           -r|--rate <TRAP_RATE> -l|--lid <LIDADDR> \n"
+         "           -s|--src_port <SOURCE_PORT> -p|--port_num <PORT_NUM>\n" );
+  printf( "\nOptions:\n" );
+  printf( "-t <TRAP_NUM>\n"
+          "--trap_num <TRAP_NUM>\n"
+          "          This option specifies the number of the trap to generate.\n"
+          "          Valid values are 128-131.\n" );
+  printf( "-n <NUM_TRAP_CREATIONS>\n"
+          "--number <NUM_TRAP_CREATIONS>\n"
+          "          This option specifies the number of times to generate this trap.\n"
+          "          If not specified - default to 1.\n" );
+  printf( "-r <TRAP_RATE>\n"
+          "--rate <TRAP_RATE>\n"
+          "          This option specifies the rate of the trap generation.\n"
+          "          What is the time period between one generation and another?\n"
+          "          The value is given in miliseconds. \n"
+          "          If the number of trap creations is 1 - this value is ignored.\n" );
+  printf( "-l <LIDADDR>\n"
+          "--lid <LIDADDR>\n"
+          "          This option specifies the lid address from where the trap should\n"
+          "          be generated.\n" );
+  printf( "-s <SOURCE_PORT>\n"
+          "--src_port <SOURCE_PORT>\n"
+          "          This option specifies the port number from which the trap should\n"
+          "          be generated. If trap number is 128 - this value is ignored (since\n"
+          "          trap 128 is not sent with a specific port number)\n" );
+  printf( "-p <port num>\n"
+          "--port_num <port num>\n"
+          "          This is the port number used for communicating with\n"
+          "          the SA.\n" );
+  printf( "-h\n"
+          "--help\n" "          Display this usage info then exit.\n\n" );
+  printf( "-o\n"
+          "--out_log_file\n"
+          "          This option defines the log to be the given file.\n"
+          "          By default the log goes to stdout.\n\n");
+  printf( "-v\n"
+          "          This option increases the log verbosity level.\n"
+          "          The -v option may be specified multiple times\n"
+          "          to further increase the verbosity level.\n"
+          "          See the -vf option for more information about.\n"
+          "          log verbosity.\n\n" );
+  printf( "-V\n"
+          "          This option sets the maximum verbosity level and\n"
+          "          forces log flushing.\n"
+          "          The -V is equivalent to '-vf 0xFF -d 2'.\n"
+          "          See the -vf option for more information about.\n"
+          "          log verbosity.\n\n" );
+  printf( "-x <flags>\n"
+          "          This option sets the log verbosity level.\n"
+          "          A flags field must follow the -vf option.\n"
+          "          A bit set/clear in the flags enables/disables a\n"
+          "          specific log level as follows:\n"
+          "          BIT    LOG LEVEL ENABLED\n"
+          "          ----   -----------------\n"
+          "          0x01 - ERROR (error messages)\n"
+          "          0x02 - INFO (basic messages, low volume)\n"
+          "          0x04 - VERBOSE (interesting stuff, moderate volume)\n"
+          "          0x08 - DEBUG (diagnostic, high volume)\n"
+          "          0x10 - FUNCS (function entry/exit, very high volume)\n"
+          "          0x20 - FRAMES (dumps all SMP and GMP frames)\n"
+          "          0x40 - currently unused.\n"
+          "          0x80 - currently unused.\n"
+          "          Without -x, ibtrapgen defaults to ERROR + INFO (0x3).\n"
+          "          Specifying -x 0 disables all messages.\n"
+          "          Specifying -x 0xFF enables all messages (see -V).\n\n" );
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+  Converts a GID string of the format 0xPPPPPPPPPPPPPPPP:GGGGGGGGGGGGGGGG 
+  to a gid type
+*/
+int
+str2gid(
+  IN char *str,
+  OUT ib_gid_t *p_gid
+  );
+
+int
+str2gid( 
+  IN char *str,
+  OUT ib_gid_t *p_gid
+  ) 
+{
+  ib_gid_t temp;
+  char buf[38];
+  char *p_prefix, *p_guid;
+
+  CL_ASSERT(p_gid);
+
+  strcpy(buf, str);
+  p_prefix = buf;
+  /*p_guid = index(buf, ':');*/
+  p_guid = strchr( buf, ':' );
+
+  if (! p_guid)
+  {
+    printf("Wrong format for gid %s\n", buf);
+    return 1;
+  }
+  
+  *p_guid = '\0';
+  p_guid++;
+
+  errno = 0;
+  temp.unicast.prefix = cl_hton64(strtoull(p_prefix, NULL, 0));
+  if (errno) {
+    printf("Wrong format for gid prefix:%s (got %u)\n", 
+           p_prefix, errno);
+    return 1;
+  }
+
+  temp.unicast.interface_id = cl_hton64(strtoull(p_guid, NULL, 16));
+  if (errno) {
+    printf("Wrong format for gid guid:%s\n", p_guid);
+    return 1;
+  }
+  
+  *p_gid = temp;
+  return 0;
+}
+void OsmReportState(IN const char *p_str)
+{
+}
+/**********************************************************************
+ **********************************************************************/
+int OSM_CDECL
+main( int argc,
+      char *argv[] )
+{
+  static ibtrapgen_t ibtrapgen;
+  ibtrapgen_opt_t opt = { 0 };
+  ib_api_status_t status;
+  uint32_t log_flags = OSM_LOG_ERROR | OSM_LOG_INFO;
+  uint32_t next_option;
+  const char *const short_option = "t:n:r:s:l:p:o:vVh";
+
+  /*
+   * In the array below, the 2nd parameter specified the number
+   * of arguments as follows:
+   * 0: no arguments
+   * 1: argument
+   * 2: optional
+   */
+  const struct option long_option[] = {
+    {"trap_num",  1, NULL, 't'},
+    {"number",    1, NULL, 'n'},
+    {"rate",      1, NULL, 'r'},
+    {"lid",       1, NULL, 'l'},
+    {"src_port",  1, NULL, 's'},
+    {"port_num",  1, NULL, 'p'},
+    {"help",      0, NULL, 'h'},
+    {"verbose",   0, NULL, 'v'},
+    {"out_log_file",  1, NULL, 'o'},
+    {"vf",        1, NULL, 'x'},
+    {"V",         0, NULL, 'V'},
+
+    {NULL, 0, NULL, 0}     /* Required at end of array */
+  };
+
+
+  opt.trap_num = 0;
+  opt.number = 1; /* This is the default value */
+  opt.rate = 0;
+  opt.lid = 0;
+  opt.src_port = 0;
+  opt.port_num = 0;
+  opt.log_file = NULL;
+  opt.force_log_flush = FALSE;
+  opt.transaction_timeout = DEFAULT_TRANS_TIMEOUT_MILLISEC;
+
+  do
+  {
+    next_option = getopt_long_only( argc, argv, short_option,
+                                    long_option, NULL );
+    
+    switch ( next_option )
+    {
+    case 't':
+      /*
+       * Define the trap number
+       */
+      opt.trap_num = (uint8_t)atoi( optarg );
+      if ((opt.trap_num < 128) || (opt.trap_num > 131))
+      {
+        printf( "-E- Given trap number is illegal! \n"
+                "    Supportes generation of traps 128-131.\n" );
+        exit(1);
+      }
+      printf( "-I- Trap Number = %u\n", opt.trap_num );
+      break;
+
+    case 'n':
+      /*
+       * Define the number of occurences
+       */
+      opt.number = (uint16_t)atoi( optarg );
+
+      printf( "-I- Number Trap Occurences = %u\n", opt.number );
+      break;
+
+    case 'r':
+      /*
+       * Define the rate of the trap
+       */
+      opt.rate = (uint16_t)atoi( optarg );
+
+      printf( "-I- Trap Rate = %u miliseconds\n", opt.rate );
+      break;
+
+
+    case 'l':
+      /*
+       * Define the source lid of the trap
+       */
+        opt.lid = (uint16_t)strtoul( optarg , NULL , 16);
+
+      printf( "-I- Trap Lid = 0x%04X\n", opt.lid );
+      break;
+      
+    case 's':
+      /*
+       * Define the source port number of the trap
+       */
+      opt.src_port = (uint8_t)atoi( optarg );
+      
+      printf( "-I- Trap Port Number = %u\n", opt.src_port );
+      break;
+
+    case 'p':
+      /*
+       * Specifies port guid with which to bind.
+       */
+      opt.port_num = (uint8_t)atoi( optarg );
+      printf( "-I- Port Num:%u\n", opt.port_num );
+      break;
+    case 'o':
+      opt.log_file = optarg;
+      printf("-I- Log File:%s\n", opt.log_file );
+      break;
+
+    case 'v':
+      /*
+       * Increases log verbosity.
+       */
+      log_flags = ( log_flags << 1 ) | 1;
+      printf( "-I- Verbose option -v (log flags = 0x%X)\n", log_flags );
+      break;
+
+    case 'V':
+      /*
+       * Specifies maximum log verbosity.
+       */
+      log_flags = 0xFFFFFFFF;
+      opt.force_log_flush = TRUE;
+      printf( "-I- Enabling maximum log verbosity\n" );
+      break;
+
+    case 'h':
+      show_usage(  );
+      return 0;
+
+    case 'x':
+      log_flags = strtol( optarg, NULL, 0 );
+      printf( "-I- Verbose option -vf (log flags = 0x%X)\n",
+              log_flags );
+      break;
+
+    case -1:
+      /*      printf( "Done with args\n" ); */
+      break;
+
+    default:            /* something wrong */
+      abort(  );
+    }
+
+  }
+  while( next_option != -1 );
+
+  /* Check for mandatory options */
+  if (opt.trap_num == 0)
+  {
+    printf( "-E- Missing trap number.\n" );
+    exit(1);
+  }
+  if (opt.lid == 0)
+  {
+    printf( "-E- Missing lid.\n" );
+    exit(1);
+  }
+  if (opt.src_port == 0 && opt.trap_num >= 129 && opt.trap_num <= 131)
+  {
+    /* for trap 129-131 should be given source port number */
+    printf( "-E- source port number.\n" );
+    exit(1);
+  }
+  if (opt.port_num == 0)
+  {
+    printf( "-E- Missing port number.\n" );
+    exit(1);
+  }
+  if (opt.rate == 0 && opt.number > 1)
+  {
+    /* for number of traps greater than 1 need to give the rate for the
+       trap generation. */
+    printf( "-E- Missing rate.\n" );
+    exit(1);
+  }
+
+
+  /* init the main object and sub objects (log and osm vendor) */
+  status = ibtrapgen_init( &ibtrapgen, &opt, ( osm_log_level_t ) log_flags );
+  if( status != IB_SUCCESS )
+  {
+    printf("-E- fail to init ibtrapgen.\n");
+    goto Exit;
+  }
+  
+  /* bind to a specific port */
+  status = ibtrapgen_bind( &ibtrapgen );
+  if (status != IB_SUCCESS) exit(status);
+  
+  /* actual work */
+  status = ibtrapgen_run( &ibtrapgen );
+  if (status != IB_SUCCESS)
+  {
+    printf("IBTRAPGEN: FAIL\n");
+  }
+  else
+  {
+    printf("IBTRAPGEN: PASS\n");
+  }
+  
+  //ibtrapgen_destroy( &ibtrapgen );
+  
+ Exit:
+  exit ( status );
+}
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_byteswap.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_byteswap.h
new file mode 100644 (file)
index 0000000..60a741d
--- /dev/null
@@ -0,0 +1,547 @@
+/*
+ * Copyright (c) 2004,2005 Voltaire, Inc. All rights reserved.   
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.   
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.   
+ *  
+ * This software is available to you under the OpenIB.org BSD license  
+ * below:  
+ *  
+ *     Redistribution and use in source and binary forms, with or  
+ *     without modification, are permitted provided that the following  
+ *     conditions are met:  
+ *  
+ *      - Redistributions of source code must retain the above  
+ *        copyright notice, this list of conditions and the following  
+ *        disclaimer.  
+ *  
+ *      - Redistributions in binary form must reproduce the above  
+ *        copyright notice, this list of conditions and the following  
+ *        disclaimer in the documentation and/or other materials  
+ *        provided with the distribution.  
+ *  
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,  
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF   
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND           
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS  
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN  
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN  
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  
+ * SOFTWARE.  
+ *  
+ * $Id: cl_byteswap.h 474 2006-08-31 08:57:19Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *     provides byteswapping utilities. Basic fuctions are obtained from platform
+ *  specific implementations from ibyteswap_osd.h.
+ *
+ * Environment:
+ *     All
+ */
+
+
+#ifndef _CL_BYTESWAP_H_
+#define _CL_BYTESWAP_H_
+
+
+#include <complib/cl_memory.h>
+#include <complib/cl_byteswap_osd.h>
+
+
+/****h* Component Library/Byte Swapping
+* NAME
+*      Byte Swapping
+*
+* DESCRIPTION
+*      The byte swapping functions and macros allow swapping bytes from network
+*      byte order to host byte order.
+*
+*      All data transmitted between systems should be in network byte order.
+*      In order to utilize such data, it must be converted to host byte order
+*      before use.
+*
+* SEE ALSO
+*      Functions:
+*              cl_ntoh16, cl_hton16, cl_ntoh32, cl_hton32, cl_ntoh64, cl_hton64,
+*              cl_ntoh
+*
+*      Macros:
+*              CL_NTOH16, CL_HTON16, CL_NTOH32, CL_HTON32, CL_NTOH64, CL_HTON64
+*********/
+
+
+/*
+ * The ibyteswap_osd.h provides the following macros.
+ *             __LITTLE_ENDIAN
+ *             __BIG_ENDIAN
+ *             __BYTE_ORDER
+ *
+ * If the platform provides byte swapping functions, ibyteswap_osd.h also
+ * provides the following macros.
+ *             ntoh16, hton16
+ *             ntoh32, hton32
+ *             ntoh64, hton64
+ */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+/****d* Component Library: Byte Swapping/CL_NTOH16
+* NAME
+*      CL_NTOH16
+*
+* DESCRIPTION
+*      The CL_NTOH16 macro converts a 16-bit value from network byte order to
+*      host byte order.  The CL_NTOH16 macro will cause constant values to be
+*      swapped by the pre-processor.  For variables, CL_NTOH16 is less efficient
+*      than the cl_ntoh16 function.
+*
+* SYNOPSIS
+*      CL_NTOH16( val );
+*
+* PARAMETERS
+*      val
+*              [in] 16-bit value to swap from network byte order to host byte order.
+*
+* RESULT
+*      Value of val converted to host byte order.
+*
+* NOTES
+*      This macro is analogous to CL_HTON16.
+*
+* SEE ALSO
+*      Byte Swapping, CL_HTON16, CL_NTOH32, CL_NTOH64,
+*      cl_ntoh16, cl_ntoh32, cl_ntoh64, cl_ntoh
+*********/
+/****d* Component Library: Byte Swapping/CL_HTON16
+* NAME
+*      CL_HTON16
+*
+* DESCRIPTION
+*      The CL_HTON16 macro converts a 16-bit value from host byte order to
+*      network byte order.  The CL_HTON16 macro will cause constant values to be
+*      swapped by the pre-processor.  For variables, CL_HTON16 is less efficient
+*      than the cl_hton16 function.
+*
+* SYNOPSIS
+*      CL_HTON16( val );
+*
+* PARAMETERS
+*      val
+*              [in] 16-bit value to swap from host byte order to network byte order.
+*
+* RESULT
+*      Value of val converted to network byte order.
+*
+* NOTES
+*      This macro is analogous to CL_NTOH16.
+*
+* SEE ALSO
+*      Byte Swapping, CL_NTOH16, CL_HTON32, CL_HTON64,
+*      cl_hton16, cl_hton32, cl_hton64, cl_ntoh
+*********/
+#if CPU_LE
+       #define CL_NTOH16( x )          (uint16_t)(             \
+                       (((uint16_t)(x) & 0x00FF) << 8) |       \
+                       (((uint16_t)(x) & 0xFF00) >> 8) )
+#else
+       #define CL_NTOH16( x )          (x)
+#endif
+#define CL_HTON16                              CL_NTOH16
+
+
+/****f* Component Library: Byte Swapping/cl_ntoh16
+* NAME
+*      cl_ntoh16
+*
+* DESCRIPTION
+*      The cl_ntoh16 function converts a 16-bit value from network byte order to
+*      host byte order.
+*
+* SYNOPSIS
+*      uint16_t
+*      cl_ntoh16(
+*              IN      const uint16_t  val );
+*
+* PARAMETERS
+*      val
+*              [in] Value to swap from network byte order to host byte order.
+*
+* RETURN VALUE
+*      Value of val converted to host byte order.
+*
+* NOTES
+*      This function is analogous to cl_hton16.
+*
+* SEE ALSO
+*      Byte Swapping, cl_hton16, cl_ntoh32, cl_ntoh64, cl_ntoh
+*********/
+/****f* Component Library: Byte Swapping/cl_hton16
+* NAME
+*      cl_hton16
+*
+* DESCRIPTION
+*      The cl_hton16 function converts a 16-bit value from host byte order to
+*      network byte order.
+*
+* SYNOPSIS
+*      uint16_t
+*      cl_hton16(
+*              IN      const uint16_t  val );
+*
+* PARAMETERS
+*      val
+*              [in] Value to swap from host byte order to network byte order .
+*
+* RETURN VALUE
+*      Value of val converted to network byte order.
+*
+* NOTES
+*      This function is analogous to cl_ntoh16.
+*
+* SEE ALSO
+*      Byte Swapping, cl_ntoh16, cl_hton32, cl_hton64, cl_ntoh
+*********/
+#undef cl_ntoh16
+#undef cl_hton16
+#ifndef cl_ntoh16
+       #define cl_ntoh16       CL_NTOH16
+       #define cl_hton16       CL_HTON16
+#endif
+
+
+/****d* Component Library: Byte Swapping/CL_NTOH32
+* NAME
+*      CL_NTOH32
+*
+* DESCRIPTION
+*      The CL_NTOH32 macro converts a 32-bit value from network byte order to
+*      host byte order.  The CL_NTOH32 macro will cause constant values to be
+*      swapped by the pre-processor.  For variables, CL_NTOH32 is less efficient
+*      than the cl_ntoh32 function.
+*
+* SYNOPSIS
+*      CL_NTOH32( val );
+*
+* PARAMETERS
+*      val
+*              [in] 32-bit value to swap from network byte order to host byte order.
+*
+* RESULT
+*      Value of val converted to host byte order.
+*
+* NOTES
+*      This macro is analogous to CL_HTON32.
+*
+* SEE ALSO
+*      Byte Swapping, CL_HTON32, CL_NTOH16, CL_NTOH64,
+*      cl_ntoh16, cl_ntoh32, cl_ntoh64, cl_ntoh
+*********/
+/****d* Component Library: Byte Swapping/CL_HTON32
+* NAME
+*      CL_HTON32
+*
+* DESCRIPTION
+*      The CL_HTON32 macro converts a 32-bit value from host byte order to
+*      network byte order.  The CL_HTON32 macro will cause constant values to be
+*      swapped by the pre-processor.  For variables, CL_HTON32 is less efficient
+*      than the cl_hton32 function.
+*
+* SYNOPSIS
+*      CL_HTON32( val );
+*
+* PARAMETERS
+*      val
+*              [in] 32-bit value to swap from host byte order to network byte order.
+*
+* RESULT
+*      Value of val converted to network byte order.
+*
+* NOTES
+*      This macro is analogous to CL_NTOH32.
+*
+* SEE ALSO
+*      Byte Swapping, CL_NTOH32, CL_HTON16, CL_HTON64,
+*      cl_hton16, cl_hton32, cl_hton64, cl_ntoh
+*********/
+#if CPU_LE
+       #define CL_NTOH32( x )          (uint32_t)(                     \
+                       (((uint32_t)(x) & 0x000000FF) << 24) |  \
+                       (((uint32_t)(x) & 0x0000FF00) << 8) |   \
+                       (((uint32_t)(x) & 0x00FF0000) >> 8) |   \
+                       (((uint32_t)(x) & 0xFF000000) >> 24) )
+#else
+       #define CL_NTOH32( x )          (x)
+#endif
+#define CL_HTON32                              CL_NTOH32
+
+
+/****f* Component Library: Byte Swapping/cl_ntoh32
+* NAME
+*      cl_ntoh32
+*
+* DESCRIPTION
+*      The cl_ntoh32 function converts a 32-bit value from network byte order to
+*      host byte order.
+*
+* SYNOPSIS
+*      uint32_t
+*      cl_ntoh32(
+*              IN      const uint32_t  val );
+*
+* PARAMETERS
+*      val
+*              [in] Value to swap from network byte order to host byte order.
+*
+* RETURN VALUE
+*      Value of val converted in host byte order.
+*
+* NOTES
+*      This function is analogous to cl_hton32.
+*
+* SEE ALSO
+*      Byte Swapping, cl_hton32, cl_ntoh16, cl_ntoh64, cl_ntoh
+*********/
+/****f* Component Library: Byte Swapping/cl_hton32
+* NAME
+*      cl_hton32
+*
+* DESCRIPTION
+*      The cl_hton32 function converts a 32-bit value from host byte order to
+*      network byte order.
+*
+* SYNOPSIS
+*      uint32_t
+*      cl_hton32(
+*              IN      const uint32_t  val );
+*
+* PARAMETERS
+*      val
+*              [in] Value to swap from host byte order to network byte order .
+*
+* RETURN VALUE
+*      Value of val converted to network byte order.
+*
+* NOTES
+*      This function is analogous to cl_ntoh32.
+*
+* SEE ALSO
+*      Byte Swapping, cl_ntoh32, cl_hton16, cl_hton64, cl_ntoh
+*********/
+#undef  cl_ntoh32
+#undef  cl_hton32
+#ifndef cl_ntoh32
+       #define cl_ntoh32       CL_NTOH32
+       #define cl_hton32       CL_HTON32
+#endif
+
+
+/****d* Component Library: Byte Swapping/CL_NTOH64
+* NAME
+*      CL_NTOH64
+*
+* DESCRIPTION
+*      The CL_NTOH64 macro converts a 64-bit value from network byte order to
+*      host byte order.  The CL_NTOH64 macro will cause constant values to be
+*      swapped by the pre-processor.  For variables, CL_NTOH64 is less efficient
+*      than the cl_ntoh64 function.
+*
+* SYNOPSIS
+*      CL_NTOH64( val );
+*
+* PARAMETERS
+*      val
+*              [in] 64-bit value to swap from network byte order to host byte order.
+*
+* RESULT
+*      Value of val converted to host byte order.
+*
+* NOTES
+*      This macro is analogous to CL_HTON64.
+*
+* SEE ALSO
+*      Byte Swapping, CL_HTON64, CL_NTOH16, CL_NTOH32,
+*      cl_ntoh16, cl_ntoh32, cl_ntoh64, cl_ntoh
+*********/
+/****d* Component Library: Byte Swapping/CL_HTON64
+* NAME
+*      CL_HTON64
+*
+* DESCRIPTION
+*      The CL_HTON64 macro converts a 64-bit value from host byte order to
+*      network byte order.  The CL_HTON64 macro will cause constant values to be
+*      swapped by the pre-processor.  For variables, CL_HTON64 is less efficient
+*      than the cl_hton64 function.
+*
+* SYNOPSIS
+*      CL_HTON64( val );
+*
+* PARAMETERS
+*      val
+*              [in] 64-bit value to swap from host byte order to network byte order.
+*
+* RESULT
+*      Value of val converted to network byte order.
+*
+* NOTES
+*      This macro is analogous to CL_NTOH64.
+*
+* SEE ALSO
+*      Byte Swapping, CL_NTOH64, CL_HTON16, CL_HTON32,
+*      cl_hton16, cl_hton32, cl_hton64, cl_ntoh
+*********/
+#if CPU_LE
+       #define CL_NTOH64( x )          (uint64_t)(                                     \
+                       (((uint64_t)(x) & CL_CONST64(0x00000000000000FF)) << 56) |      \
+                       (((uint64_t)(x) & CL_CONST64(0x000000000000FF00)) << 40) |      \
+                       (((uint64_t)(x) & CL_CONST64(0x0000000000FF0000)) << 24) |      \
+                       (((uint64_t)(x) & CL_CONST64(0x00000000FF000000)) << 8 ) |      \
+                       (((uint64_t)(x) & CL_CONST64(0x000000FF00000000)) >> 8 ) |      \
+                       (((uint64_t)(x) & CL_CONST64(0x0000FF0000000000)) >> 24) |      \
+                       (((uint64_t)(x) & CL_CONST64(0x00FF000000000000)) >> 40) |      \
+                       (((uint64_t)(x) & CL_CONST64(0xFF00000000000000)) >> 56) )
+#else
+       #define CL_NTOH64( x )          (x)
+#endif
+#define CL_HTON64                              CL_NTOH64
+
+
+/****f* Component Library: Byte Swapping/cl_ntoh64
+* NAME
+*      cl_ntoh64
+*
+* DESCRIPTION
+*      The cl_ntoh64 function converts a 64-bit value from network byte order to
+*      host byte order.
+*
+* SYNOPSIS
+*      uint64_t
+*      cl_ntoh64(
+*              IN      const uint64_t  val );
+*
+* PARAMETERS
+*      val
+*              [in] Value to swap from network byte order to host byte order.
+*
+* RETURN VALUE
+*      Value of val converted in host byte order.
+*
+* NOTES
+*      This function is analogous to cl_hton64.
+*
+* SEE ALSO
+*      Byte Swapping, cl_hton64, cl_ntoh16, cl_ntoh32, cl_ntoh
+*********/
+/****f* Component Library: Byte Swapping/cl_hton64
+* NAME
+*      cl_hton64
+*
+* DESCRIPTION
+*      The cl_hton64 function converts a 64-bit value from host byte order to
+*      network byte order.
+*
+* SYNOPSIS
+*      uint64_t
+*      cl_hton64(
+*              IN      const uint64_t  val );
+*
+* PARAMETERS
+*      val
+*              [in] Value to swap from host byte order to network byte order .
+*
+* RETURN VALUE
+*      Value of val converted to network byte order.
+*
+* NOTES
+*      This function is analogous to cl_ntoh64.
+*
+* SEE ALSO
+*      Byte Swapping, cl_ntoh64, cl_hton16, cl_hton32, cl_ntoh
+*********/
+#undef cl_ntoh64
+#undef cl_hton64
+#ifndef cl_ntoh64
+       #define cl_ntoh64       CL_NTOH64
+       #define cl_hton64       CL_HTON64
+#endif
+
+
+/****f* Component Library: Byte Swapping/cl_ntoh
+* NAME
+*      cl_ntoh
+*
+* DESCRIPTION
+*      The cl_ntoh function converts a value from network byte order to
+*      host byte order.
+*
+* SYNOPSIS
+*/
+CL_INLINE void CL_API
+cl_ntoh(
+       OUT     char* const                     p_dest,
+       IN      const char* const       p_src,
+       IN      const uint8_t           size )
+{
+#if CPU_LE
+       uint8_t i;
+       char    temp;
+
+       if( p_src == p_dest )
+       {
+               /* Swap in place if source and destination are the same. */
+               for( i = 0; i < size / 2; i++ )
+               {
+                       temp = p_dest[i];
+                       p_dest[i] = p_src[size - 1 - i];
+                       p_dest[size - 1 - i] = temp;
+               }
+       }
+       else
+       {
+               for( i = 0; i < size; i++ )
+                       p_dest[i] = p_src[size - 1 - i];
+       }
+#else
+       /*
+        * If the source and destination are not the same, copy the source to
+        * the destination.
+        */
+       if( p_src != p_dest )
+               cl_memcpy( p_dest, p_src, size );
+#endif
+}
+/*
+* PARAMETERS
+*      p_dest
+*              [in] Pointer to a byte array to contain the converted value of p_src.
+*
+*      p_src
+*              [in] Pointer to a byte array to be converted from network byte
+*              ordering.
+*
+*      size
+*              [in] Number of bytes to swap.p_dest
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      cl_ntoh can perform in place swapping if both p_src and p_dest point to
+*      the same buffer.
+*
+* SEE ALSO
+*      Byte Swapping, cl_ntoh16, cl_ntoh32, cl_ntoh64
+*********/
+
+
+#ifdef __cplusplus
+}      /* extern "C" */
+#endif
+
+#endif /* _CL_BYTESWAP_H_ */
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_dispatcher.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_dispatcher.h
new file mode 100644 (file)
index 0000000..123bd09
--- /dev/null
@@ -0,0 +1,660 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of dispatcher abstraction.
+ * 
+ * Environment:
+ *     All
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _CL_DISPATCHER_H_
+#define _CL_DISPATCHER_H_
+
+#include <complib/cl_atomic.h>
+#include <complib/cl_threadpool.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_qpool.h>
+#include <complib/cl_spinlock.h>
+#include <complib/cl_ptr_vector.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* Component Library/Dispatcher
+* NAME
+*      Dispatcher
+*
+* DESCRIPTION
+*      The Dispatcher provides a facility for message routing to
+*      asynchronous worker threads.
+*
+*      The Dispatcher functions operate on a cl_dispatcher_t structure
+*      which should be treated as opaque and should be manipulated
+*      only through the provided functions.
+*
+* SEE ALSO
+*      Structures:
+*              cl_dispatcher_t
+*
+*      Initialization/Destruction:
+*              cl_disp_construct, cl_disp_init, cl_disp_shutdown, cl_disp_destroy
+*
+*      Manipulation:
+*              cl_disp_post, cl_disp_reset, cl_disp_wait_on
+*********/
+
+/****s* Component Library: Dispatcher/cl_disp_msgid_t
+* NAME
+*      cl_disp_msgid_t
+*
+* DESCRIPTION
+*      Defines the type of dispatcher messages.
+*
+* SYNOPSIS
+*/
+typedef uint32_t cl_disp_msgid_t;
+/**********/
+
+/****s* Component Library: Dispatcher/CL_DISP_MSGID_NONE
+* NAME
+*      CL_DISP_MSGID_NONE
+*
+* DESCRIPTION
+*      Defines a message value that means "no message".
+*      This value is used during registration by Dispatcher clients
+*      that do not wish to receive messages.
+*
+*      No Dispatcher message is allowed to have this value.
+*
+* SYNOPSIS
+*/
+#define CL_DISP_MSGID_NONE     0xFFFFFFFF
+/**********/
+
+/****s* Component Library: Dispatcher/CL_DISP_INVALID_HANDLE
+* NAME
+*      CL_DISP_INVALID_HANDLE
+*
+* DESCRIPTION
+*      Defines the value of an invalid Dispatcher registration handle.
+*
+* SYNOPSIS
+*/
+#define CL_DISP_INVALID_HANDLE ((cl_disp_reg_handle_t)0)
+/*********/
+
+/****f* Component Library: Dispatcher/cl_pfn_msgrcv_cb_t
+* NAME
+*      cl_pfn_msgrcv_cb_t
+*
+* DESCRIPTION
+*      This typedef defines the prototype for client functions invoked
+*      by the Dispatcher.  The Dispatcher calls the corresponding
+*      client function when delivering a message to the client.
+*
+*      The client function must be reentrant if the user creates a
+*      Dispatcher with more than one worker thread.
+*
+* SYNOPSIS
+*/
+typedef void 
+(*cl_pfn_msgrcv_cb_t)(
+       IN      void*                           context,
+       IN      void*                           p_data );
+/*
+* PARAMETERS
+*      context
+*              [in] Client specific context specified in a call to
+*              cl_disp_register
+*
+*      p_data
+*              [in] Pointer to the client specific data payload
+*              of this message.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      This typedef provides a function prototype reference for
+*      the function provided by Dispatcher clients as a parameter
+*      to the cl_disp_register function.
+*
+* SEE ALSO
+*      Dispatcher, cl_disp_register
+*********/
+
+/****f* Component Library: Dispatcher/cl_pfn_msgdone_cb_t
+* NAME
+*      cl_pfn_msgdone_cb_t
+*
+* DESCRIPTION
+*      This typedef defines the prototype for client functions invoked
+*      by the Dispatcher.  The Dispatcher calls the corresponding
+*      client function after completing delivery of a message.
+*
+*      The client function must be reentrant if the user creates a
+*      Dispatcher with more than one worker thread.
+*
+* SYNOPSIS
+*/
+typedef void 
+(*cl_pfn_msgdone_cb_t)(
+       IN      void*                           context,
+       IN      void*                           p_data );
+/*
+* PARAMETERS
+*      context
+*              [in] Client specific context specified in a call to
+*              cl_disp_post
+*
+*      p_data
+*              [in] Pointer to the client specific data payload
+*              of this message.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      This typedef provides a function prototype reference for
+*      the function provided by Dispatcher clients as a parameter
+*      to the cl_disp_post function.
+*
+* SEE ALSO
+*      Dispatcher, cl_disp_post
+*********/
+
+/****s* Component Library: Dispatcher/cl_dispatcher_t
+* NAME
+*      cl_dispatcher_t
+*
+* DESCRIPTION
+*      Dispatcher structure.
+*
+*      The Dispatcher is thread safe.
+*
+*      The cl_dispatcher_t structure should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_dispatcher
+{
+  cl_spinlock_t      lock;
+  cl_ptr_vector_t    reg_vec;
+  cl_qlist_t         reg_list;
+  cl_thread_pool_t   worker_threads;
+  cl_qlist_t         msg_fifo;
+  cl_qpool_t         msg_pool;
+  uint64_t           last_msg_queue_time_us;
+} cl_dispatcher_t;
+/*
+* FIELDS
+*      reg_vec
+*              Vector of registration info objects.  Indexed by message msg_id.
+*
+*      lock
+*              Spinlock to guard internal structures.
+*
+*      msg_fifo
+*              FIFO of messages being processed by the Dispatcher.  New
+*              messages are posted to the tail of the FIFO.  Worker threads
+*              pull messages from the front.
+*
+*      worker_threads
+*              Thread pool of worker threads to dispose of posted messages.
+*
+*      msg_pool
+*              Pool of message objects to be processed through the FIFO.
+*
+*      reg_count
+*              Count of the number of registrants.
+*
+*      state
+*              Indicates the state of the object.
+* 
+*       last_msg_queue_time_us
+*               The time that the last message spent in the Q in usec
+*      
+* SEE ALSO
+*      Dispatcher
+*********/
+
+/****s* Component Library: Dispatcher/cl_disp_reg_info_t
+* NAME
+*      cl_disp_reg_info_t
+*
+* DESCRIPTION
+*      Defines the dispatcher registration object structure.
+*
+*      The cl_disp_reg_info_t structure is for internal use by the
+*      Dispatcher only.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_disp_reg_info
+{
+       cl_list_item_t                  list_item;
+       cl_pfn_msgrcv_cb_t              pfn_rcv_callback;
+       const void                              *context;
+       atomic32_t                              ref_cnt;
+       cl_disp_msgid_t                 msg_id;
+       cl_dispatcher_t                 *p_disp;
+
+} cl_disp_reg_info_t;
+/*
+* FIELDS
+*      pfn_rcv_callback
+*              Client's message receive callback.
+*
+*      context
+*              Client's context for message receive callback.
+*
+*      rcv_thread_count
+*              Number of threads currently in the receive callback.
+*
+*      msg_done_thread_count
+*              Number of threads currently in the message done callback.
+*
+*      state
+*              State of this registration object.
+*                      DISP_REGSTATE_INIT: initialized and inactive
+*                      DISP_REGSTATE_ACTIVE: in active use
+*                      DISP_REGSTATE_UNREGPEND: unregistration is pending
+*
+*      msg_id
+*              Dispatcher message msg_id value for this registration object.
+*
+*      p_disp
+*              Pointer to parent Dispatcher.
+*
+* SEE ALSO
+*********/
+
+/****s* Component Library: Dispatcher/cl_disp_msg_t
+* NAME
+*      cl_disp_msg_t
+*
+* DESCRIPTION
+*      Defines the dispatcher message structure.
+*
+*      The cl_disp_msg_t structure is for internal use by the
+*      Dispatcher only.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_disp_msg
+{
+  cl_pool_item_t         item;
+  const void            *p_data;
+  cl_disp_reg_info_t    *p_src_reg;
+  cl_disp_reg_info_t    *p_dest_reg;
+  cl_pfn_msgdone_cb_t    pfn_xmt_callback;
+  uint64_t               in_time;
+  const void            *context;
+} cl_disp_msg_t;
+/*
+* FIELDS
+*      item
+*              List & Pool linkage.  Must be first element in the structure!!
+*
+*      msg_id
+*              The message's numberic ID value.
+*
+*      p_data
+*              Pointer to the data payload for this message.  The payload
+*              is opaque to the Dispatcher.
+*
+*      p_reg_info
+*              Pointer to the registration info of the sender.
+*
+*      pfn_xmt_callback
+*              Client's message done callback.
+*
+*       in_time 
+*               The absolute time the message was inserted into the queue
+*
+*      context
+*              Client's message done callback context.
+*              
+* SEE ALSO
+*********/
+
+/****s* Component Library: Dispatcher/cl_disp_reg_info_t
+* NAME
+*      cl_disp_reg_info_t
+*
+* DESCRIPTION
+*      Defines the Dispatcher registration handle.  This handle
+*      should be treated as opaque by the client.
+*
+* SYNOPSIS
+*/
+typedef const struct _cl_disp_reg_info *cl_disp_reg_handle_t;
+/**********/
+
+/****f* Component Library: Dispatcher/cl_disp_construct
+* NAME
+*      cl_disp_construct
+*
+* DESCRIPTION
+*      This function constructs a Dispatcher object.
+*
+* SYNOPSIS
+*/
+void
+cl_disp_construct(
+       IN      cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_disp
+*              [in] Pointer to a Dispatcher.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling cl_disp_init and cl_disp_destroy.
+*
+* SEE ALSO
+*      Dispatcher, cl_disp_init, cl_disp_destroy
+*********/
+
+/****f* Component Library: Dispatcher/cl_disp_init
+* NAME
+*      cl_disp_init
+*
+* DESCRIPTION
+*      This function initializes a Dispatcher object.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_disp_init(
+       IN      cl_dispatcher_t* const  p_disp,
+       IN      const uint32_t                  thread_count,
+    IN const char* const               name );
+/*
+* PARAMETERS
+*      p_disp
+*              [in] Pointer to a Dispatcher.
+*
+*      thread_count
+*              [in] The number of worker threads to create in this Dispatcher.
+*              A value of 0 causes the Dispatcher to create one worker thread
+*              per CPU in the system.  When the Dispatcher is created with
+*              only one thread, the Dispatcher guarantees to deliver posted
+*              messages in order.  When the Dispatcher is created with more
+*              than one thread, messages may be delivered out of order.
+*
+*      name
+*              [in] Name to associate with the threads.  The name may be up to 16
+*              characters, including a terminating null character.  All threads
+*              created in the Dispatcher have the same name.
+*
+* RETURN VALUE
+*      CL_SUCCESS if the operation is successful.
+*
+* SEE ALSO
+*      Dispatcher, cl_disp_destoy, cl_disp_register, cl_disp_unregister, 
+*      cl_disp_post
+*********/
+
+/****f* Component Library: Dispatcher/cl_disp_shutdown
+* NAME
+*      cl_disp_shutdown
+*
+* DESCRIPTION
+*      This function shutdown a Dispatcher object. So it unreg all messages and
+*  clears the fifo and waits for the threads to exit
+*
+* SYNOPSIS
+*/
+void
+cl_disp_shutdown(
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_disp
+*              [in] Pointer to a Dispatcher.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      This function does not returns until all worker threads
+*      have exited client callback functions and been successfully
+*      shutdowned.
+*
+* SEE ALSO
+*      Dispatcher, cl_disp_construct, cl_disp_init
+*********/
+
+/****f* Component Library: Dispatcher/cl_disp_destroy
+* NAME
+*      cl_disp_destroy
+*
+* DESCRIPTION
+*      This function destroys a Dispatcher object.
+*
+* SYNOPSIS
+*/
+void
+cl_disp_destroy(
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_disp
+*              [in] Pointer to a Dispatcher.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* SEE ALSO
+*      Dispatcher, cl_disp_construct, cl_disp_init
+*********/
+
+/****f* Component Library: Dispatcher/cl_disp_register
+* NAME
+*      cl_disp_register
+*
+* DESCRIPTION
+*      This function registers a client with a Dispatcher object.
+*
+* SYNOPSIS
+*/
+cl_disp_reg_handle_t
+cl_disp_register(
+       IN cl_dispatcher_t* const p_disp,
+       IN const cl_disp_msgid_t msg_id,
+       IN cl_pfn_msgrcv_cb_t pfn_callback OPTIONAL,
+       IN const void* const context );
+/*
+* PARAMETERS
+*      p_disp
+*              [in] Pointer to a Dispatcher.
+*
+*      msg_id
+*              [in] Numberic message ID for which the client is registering.
+*              If the client does not wish to receive any messages,
+*              (a send-only client) then the caller should set this value
+*              to CL_DISP_MSGID_NONE.  For efficiency, numeric message msg_id
+*              values should start with 0 and should be contiguous, or nearly so.
+*
+*      pfn_callback
+*              [in] Message receive callback.  The Dispatcher calls this
+*              function after receiving a posted message with the
+*              appropriate message msg_id value.  Send-only clients may specify
+*              NULL for this value.
+*
+*      context
+*              [in] Client context value passed to the cl_pfn_msgrcv_cb_t
+*              function.
+*
+* RETURN VALUE
+*      On success a Dispatcher registration handle.
+*      CL_CL_DISP_INVALID_HANDLE otherwise.
+*
+* SEE ALSO
+*      Dispatcher, cl_disp_unregister, cl_disp_post
+*********/
+
+/****f* Component Library: Dispatcher/cl_disp_unregister
+* NAME
+*      cl_disp_unregister
+*
+* DESCRIPTION
+*      This function unregisters a client from a Dispatcher.
+*
+* SYNOPSIS
+*/
+void
+cl_disp_unregister(
+       IN const cl_disp_reg_handle_t handle );
+/*
+* PARAMETERS
+*      handle
+*              [in] cl_disp_reg_handle_t value return by cl_disp_register.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      This function will not return until worker threads have exited
+*      the callback functions for this client.  Do not invoke this
+*      function from a callback.
+*
+* SEE ALSO
+*      Dispatcher, cl_disp_register
+*********/
+
+/****f* Component Library: Dispatcher/cl_disp_post
+* NAME
+*      cl_disp_post
+*
+* DESCRIPTION
+*      This function posts a message to a Dispatcher object.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_disp_post(
+       IN const cl_disp_reg_handle_t handle,
+       IN const cl_disp_msgid_t msg_id,
+       IN const void* const p_data,
+       IN cl_pfn_msgdone_cb_t pfn_callback OPTIONAL,
+       IN const void* const context );
+/*
+* PARAMETERS
+*      handle
+*              [in] cl_disp_reg_handle_t value return by cl_disp_register.
+*
+*      msg_id
+*              [in] Numeric message msg_id value associated with this message.
+*
+*      p_data
+*              [in] Data payload for this message.
+*
+*      pfn_callback
+*              [in] Pointer to a cl_pfn_msgdone_cb_t function.
+*              The Dispatcher calls this function after the message has been
+*              processed by the recipient.
+*              The caller may pass NULL for this value, which indicates no
+*              message done callback is necessary.
+*
+*      context
+*              [in] Client context value passed to the cl_pfn_msgdone_cb_t
+*              function.
+*      
+* RETURN VALUE
+*      CL_SUCCESS if the message was successfully queued in the Dispatcher.
+*
+* NOTES
+*      The caller must not modify the memory pointed to by p_data until
+*      the Dispatcher call the pfn_callback function.
+*
+* SEE ALSO
+*      Dispatcher
+*********/
+
+/****f* Component Library: Dispatcher/cl_disp_get_queue_status
+* NAME
+*      cl_disp_get_queue_status
+*
+* DESCRIPTION
+*      This function posts a message to a Dispatcher object.
+*
+* SYNOPSIS
+*/
+void
+cl_disp_get_queue_status(
+  IN const cl_disp_reg_handle_t handle,
+  OUT uint32_t *p_num_queued_msgs,
+  OUT uint64_t *p_last_msg_queue_time_ms);
+/*
+* PARAMETERS
+*   handle
+*     [in] cl_disp_reg_handle_t value return by cl_disp_register.
+*
+*   p_last_msg_queue_time_ms
+*     [out] pointer to a variable to hold the time the last popped up message 
+*           spent in the queue 
+*
+*   p_num_queued_msgs
+*     [out] number of messages in the queue
+*
+* RETURN VALUE
+*      Thr time the last popped up message stayed in the queue, in msec
+*
+* NOTES
+*      Extarnel Locking is not required.
+*
+* SEE ALSO
+*      Dispatcher
+*********/
+
+END_C_DECLS
+
+#endif /* !defined(_CL_DISPATCHER_H_) */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_event_wheel.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_event_wheel.h
new file mode 100644 (file)
index 0000000..129eadd
--- /dev/null
@@ -0,0 +1,493 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of event wheel abstraction.
+ * 
+ * Environment:
+ *     All
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _CL_EVENT_WHEEL_H_
+#define _CL_EVENT_WHEEL_H_
+
+#include <complib/cl_atomic.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_timer.h>
+#include <complib/cl_spinlock.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* Component Library/Event_Wheel
+* NAME
+*      Event_Wheel
+*
+* DESCRIPTION
+*      The Event_Wheel provides a facility for registering delayed events
+*      and getting called once they timeout.
+*
+*      The Event_Wheel functions operate on a cl_event_wheel_t structure
+*      which should be treated as opaque and should be manipulated
+*      only through the provided functions.
+*
+* SEE ALSO
+*      Structures:
+*              cl_event_wheel_t
+*
+*      Initialization/Destruction:
+*              cl_event_wheel_construct, cl_event_wheel_init, cl_event_wheel_destroy
+*
+*      Manipulation:
+*              cl_event_wheel_reg, cl_event_wheel_unreg
+*
+*********/
+
+/****f* Component Library: Event_Wheel/cl_pfn_event_aged_cb_t
+* NAME
+*      cl_pfn_event_aged_cb_t
+*
+* DESCRIPTION
+*      This typedef defines the prototype for client functions invoked
+*      by the Event_Wheel.  The Event_Wheel calls the corresponding
+*      client function when the specific item has aged.
+*
+* SYNOPSIS
+*/
+typedef uint64_t
+(*cl_pfn_event_aged_cb_t)(
+  IN  uint64_t       key,
+  IN  uint32_t       num_regs,
+  IN   void*                           context);
+/*
+* PARAMETERS
+*  key
+*     [in] The key used for registering the item in the call to
+*     cl_event_wheel_reg
+*
+*  num_regs
+*     [in] The number of times this event was registered (pushed in time).
+*
+*      context
+*              [in] Client specific context specified in a call to
+*              cl_event_wheel_reg
+*
+* RETURN VALUE
+*      This function returns the abosolute time the event should fire in [usec].
+*  If lower then current time means the event should be unregistered
+*  immediatly.
+*
+* NOTES
+*      This typedef provides a function prototype reference for
+*      the function provided by Event_Wheel clients as a parameter
+*      to the cl_event_wheel_reg function.
+*
+* SEE ALSO
+*      Event_Wheel, cl_event_wheel_reg
+*********/
+
+/****s* Component Library: Event_Wheel/cl_event_wheel_t
+* NAME
+*      cl_event_wheel_t
+*
+* DESCRIPTION
+*      Event_Wheel structure.
+*
+*      The Event_Wheel is thread safe.
+*
+*      The cl_event_wheel_t structure should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_event_wheel
+{
+  cl_spinlock_t                   lock;
+  cl_spinlock_t           *p_external_lock;
+    
+  cl_qmap_t                events_map;
+  boolean_t                closing;
+  cl_qlist_t               events_wheel;
+  cl_timer_t               timer;
+  osm_log_t                *p_log;
+} cl_event_wheel_t;
+/*
+* FIELDS
+*      lock
+*              Spinlock to guard internal structures.
+*
+*       p_external_lock
+*               Reference to external spinlock to guard internal structures
+*               if the event wheel is part of a larger object protected by its own lock
+*
+*      events_map
+*              A Map holding all registered event items by their key.
+*
+*  closing 
+*     A flag indicating the event wheel is closing. This means that
+*     callbacks that are called when closing == TRUE should just be ignored.
+*
+*      events_wheel
+*              A list of the events sorted by expiration time.
+*
+*      timer
+*              The timer scheduling event time propagation.
+*
+*  p_log
+*     Pointer to opensm log object.
+*
+* SEE ALSO
+*      Event_Wheel
+*********/
+
+/****s* Component Library: Event_Wheel/cl_event_wheel_reg_info_t
+* NAME
+*      cl_event_wheel_reg_info_t
+*
+* DESCRIPTION
+*      Defines the event_wheel registration object structure.
+*
+*      The cl_event_wheel_reg_info_t structure is for internal use by the
+*      Event_Wheel only.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_event_wheel_reg_info
+{
+  cl_map_item_t          map_item;
+  cl_list_item_t                        list_item;
+  uint64_t               key;
+  cl_pfn_event_aged_cb_t pfn_aged_callback;
+  uint64_t               aging_time;
+  uint32_t               num_regs;
+  void                                *context;
+  cl_event_wheel_t              *p_event_wheel;
+} cl_event_wheel_reg_info_t;
+/*
+* FIELDS
+*  map_item 
+*     The map item of this event 
+*
+*  list_item
+*     The sorted by aging time list item
+*
+*  key
+*     The key by which one can find the event
+*
+*      pfn_aged_callback
+*              The clients Event-Aged callback
+*
+*  aging_time
+*     The delta time [msec] for which the event should age.
+*
+*  num_regs
+*     The number of times the same event (key) was registered
+*
+*      context
+*              Client's context for event-aged callback.
+*
+*      p_event_wheel
+*              Pointer to this event wheel object
+*
+* SEE ALSO
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_construct
+* NAME
+*      cl_event_wheel_construct
+*
+* DESCRIPTION
+*      This function constructs a Event_Wheel object.
+*
+* SYNOPSIS
+*/
+void
+cl_event_wheel_construct(
+       IN      cl_event_wheel_t* const p_event_wheel );
+/*
+* PARAMETERS
+*      p_event_wheel
+*              [in] Pointer to a Event_Wheel.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling cl_event_wheel_init and cl_event_wheel_destroy.
+*
+* SEE ALSO
+*      Event_Wheel, cl_event_wheel_init, cl_event_wheel_destroy
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_init
+* NAME
+*      cl_event_wheel_init
+*
+* DESCRIPTION
+*      This function initializes a Event_Wheel object.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_event_wheel_init(
+  IN   cl_event_wheel_t* const p_event_wheel,
+  IN    osm_log_t               *p_log);
+
+/*
+* PARAMETERS
+*      p_event_wheel
+*              [in] Pointer to a Event_Wheel.
+*
+*  p_log
+*     [in] Pointer to opensm log object to be used for logging
+*
+* RETURN VALUE
+*      CL_SUCCESS if the operation is successful.
+*
+* SEE ALSO
+*      Event_Wheel, cl_event_wheel_destoy, cl_event_wheel_reg, cl_event_wheel_unreg
+*      
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_init
+* NAME
+*      cl_event_wheel_init
+*
+* DESCRIPTION
+*      This function initializes a Event_Wheel object.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_event_wheel_init_ex(
+  IN   cl_event_wheel_t* const p_event_wheel,
+  IN    osm_log_t               *p_log,
+  IN    cl_spinlock_t           *p_external_lock);
+
+/*
+* PARAMETERS
+*  p_event_wheel
+*     [in] Pointer to a Event_Wheel.
+*
+*  p_log
+*     [in] Pointer to opensm log object to be used for logging
+*
+*  p_external_lock
+*     [in] Reference to external spinlock to guard internal structures
+*          if the event wheel is part of a larger object protected by its own lock
+*
+* RETURN VALUE
+*      CL_SUCCESS if the operation is successful.
+*
+* SEE ALSO
+*      Event_Wheel, cl_event_wheel_destoy, cl_event_wheel_reg, cl_event_wheel_unreg
+*      
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_destroy
+* NAME
+*      cl_event_wheel_destroy
+*
+* DESCRIPTION
+*      This function destroys a Event_Wheel object.
+*
+* SYNOPSIS
+*/
+void
+cl_event_wheel_destroy(
+       IN cl_event_wheel_t* const p_event_wheel );
+/*
+* PARAMETERS
+*      p_event_wheel
+*              [in] Pointer to a Event_Wheel.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      This function does not returns until all client callback functions
+*  been successfully finished.
+*
+* SEE ALSO
+*      Event_Wheel, cl_event_wheel_construct, cl_event_wheel_init
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_dump
+* NAME
+*      cl_event_wheel_dump
+*
+* DESCRIPTION
+*      This function dumps the details of an Event_Whell object.
+*
+* SYNOPSIS
+*/
+void
+cl_event_wheel_dump(
+       IN cl_event_wheel_t* const p_event_wheel );
+/*
+* PARAMETERS
+*      p_event_wheel
+*              [in] Pointer to a Event_Wheel.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Note that this function should be called inside a lock of the event wheel!
+*  It doesn't aquire the lock by itself. 
+*
+* SEE ALSO
+*      Event_Wheel, cl_event_wheel_construct, cl_event_wheel_init
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_reg
+* NAME
+*      cl_event_wheel_reg
+*
+* DESCRIPTION
+*      This function registers a client with a Event_Wheel object.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_event_wheel_reg(
+       IN cl_event_wheel_t* const p_event_wheel,
+       IN const uint64_t          key,
+       IN const uint64_t          aging_time_usec,
+       IN cl_pfn_event_aged_cb_t  pfn_callback,
+       IN void* const context );
+/*
+* PARAMETERS
+*      p_event_wheel
+*              [in] Pointer to a Event_Wheel.
+*
+*      key
+*              [in] The specifc Key by which events are registered.
+*
+*  aging_time_usec
+*     [in] The absolute time this event should age in usec
+*
+*      pfn_callback
+*              [in] Event Aging callback.  The Event_Wheel calls this
+*              function after the time the event has registed for has come.
+*
+*      context
+*              [in] Client context value passed to the cl_pfn_event_aged_cb_t
+*              function.
+*
+* RETURN VALUE
+*      On success a Event_Wheel CL_SUCCESS or CL_ERROR otherwise.
+*
+* SEE ALSO
+*      Event_Wheel, cl_event_wheel_unreg
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_unreg
+* NAME
+*      cl_event_wheel_unreg
+*
+* DESCRIPTION
+*      This function unregisters a client event from a Event_Wheel.
+*
+* SYNOPSIS
+*/
+void
+cl_event_wheel_unreg(
+  IN cl_event_wheel_t* const p_event_wheel,
+  IN uint64_t key );
+/*
+* PARAMETERS
+*      p_event_wheel
+*              [in] Pointer to a Event_Wheel.
+*
+*      key
+*              [in] The key used for registering the event
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*  After the event has aged it is automatically removed from 
+*  the event wheel. So it should only be invoked when the need arises
+*  to remove existing events before they age.
+*
+* SEE ALSO
+*      Event_Wheel, cl_event_wheel_reg
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_num_regs
+* NAME
+*      cl_event_wheel_num_regs
+*
+* DESCRIPTION
+*      This function returns the number of times an event was registered.
+*
+* SYNOPSIS
+*/
+uint32_t 
+cl_event_wheel_num_regs(
+  IN cl_event_wheel_t* const p_event_wheel,
+  IN uint64_t key );
+/*
+* PARAMETERS
+*      p_event_wheel
+*              [in] Pointer to a Event_Wheel.
+*
+*      key
+*              [in] The key used for registering the event
+*
+* RETURN VALUE
+*      The number of times the event was registered.
+*  0 if never registered or eventually aged.
+*
+* SEE ALSO
+*      Event_Wheel, cl_event_wheel_reg, cl_event_wheel_unreg
+*********/
+
+END_C_DECLS
+
+#endif /* !defined(_CL_EVENT_WHEEL_H_) */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_signal_osd.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/complib/cl_signal_osd.h
new file mode 100644 (file)
index 0000000..01c1f90
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2005 Mellanox Technologies.  All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: cl_signal_osd.h 474 2006-08-31 08:57:19Z sleybo $
+ */
+
+/*
+ * Abstract:
+ *     Declaration of Signal Handler Registration
+ *
+ * Environment:
+ *     All
+ *
+ * $Revision: 1.3 $
+ */
+
+
+#ifndef _CL_SIG_HDL_H_
+#define _CL_SIG_HDL_H_
+
+#include <signal.h>
+
+/****h* Component Library/Signal Handler
+* NAME
+*   Signal Handler Registration
+*
+* DESCRIPTION
+*      The Signal Handler Registration allows to register a callback on the case of incoming signal
+*
+* SEE ALSO
+*********/
+/* TODO : Required when calling signal function in windows*/
+typedef void (__cdecl *cl_sig_hdl)(
+   IN int sig);
+/* Prototypes */
+
+/****f* Component Library: Signal Handler/cl_reg_sig_hdl
+* NAME
+*      cl_reg_sig_hdl
+*
+* DESCRIPTION
+*      Register the handler for the given signal
+*
+* SYNOPSIS
+*/
+
+static inline void 
+cl_reg_sig_hdl(int sig, cl_sig_hdl pfn_sig_hdl);
+
+
+
+/****f* Component Library: Signal Handler/cl_mask_sigint
+* NAME
+*      cl_sig_mask_sigint
+*
+* DESCRIPTION
+*      Mask the kill signal
+*
+* SYNOPSIS
+*/
+
+static inline void 
+cl_sig_mask_sigint(void);
+
+
+
+
+/****f* Component Library: Signal Handler/cl_reg_sig_hdl
+* NAME
+*      cl_reg_sig_hdl
+*
+* DESCRIPTION
+*      Register the handler for the given signal
+*
+* SYNOPSIS
+*/
+static inline void 
+cl_reg_sig_hdl(int sig, cl_sig_hdl pfn_sig_hdl) {
+       signal(sig,pfn_sig_hdl);
+ }
+/*
+*********/
+
+/****f* Component Library: Signal Handler/cl_mask_sigint
+* NAME
+*      cl_sig_mask_sigint
+*
+* DESCRIPTION
+*      Mask the kill signal
+*
+* SYNOPSIS
+*/
+static inline void 
+cl_sig_mask_sigint(void)
+{
+}
+/*
+*********/
+
+#endif /* _CL_SIG_HDL_H_ */
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/iba/ib_types.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/iba/ib_types.h
new file mode 100644 (file)
index 0000000..2111366
--- /dev/null
@@ -0,0 +1,10684 @@
+/*\r
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.\r
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.\r
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.\r
+ * Portions Copyright (c) 2008 Microsoft Corporation.  All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: ib_types.h 1925 2009-02-04 15:11:30Z tzachid $\r
+ */\r
+\r
+\r
+\r
+#if !defined(__IB_TYPES_H__)\r
+#define __IB_TYPES_H__\r
+\r
+#include <string.h>\r
+#include <complib/cl_types.h>\r
+#include <complib/cl_byteswap.h>\r
+\r
+#ifdef __cplusplus\r
+#  define BEGIN_C_DECLS extern "C" {\r
+#  define END_C_DECLS   }\r
+#else /* !__cplusplus */\r
+#  define BEGIN_C_DECLS\r
+#  define END_C_DECLS\r
+#endif /* __cplusplus */\r
+\r
+BEGIN_C_DECLS\r
+\r
+#if defined( WIN32 ) || defined( _WIN64 )\r
+    #if defined( EXPORT_AL_SYMBOLS )\r
+         #define OSM_EXPORT    __declspec(dllexport)\r
+    #else\r
+         #define OSM_EXPORT    __declspec(dllimport)\r
+    #endif\r
+    #define OSM_API __stdcall\r
+    #define OSM_CDECL __cdecl\r
+#else\r
+    #define OSM_EXPORT extern\r
+    #define OSM_API\r
+    #define OSM_CDECL\r
+    #define __ptr64\r
+#endif\r
+\r
+\r
+#define IB_CONCAT(str1, str2) str1##str2\r
+\r
+#define TO_LONG_PTR(type,member_name) \\r
+    union { type member_name;  uint64_t IB_CONCAT(member_name,_padding) ; }\r
+\r
+\r
+\r
+/****h* IBA Base/Constants\r
+* NAME\r
+*      Constants\r
+*\r
+* DESCRIPTION\r
+*      The following constants are used throughout the IBA code base.\r
+*\r
+*      Definitions are from the InfiniBand Architecture Specification v1.2\r
+*\r
+*********/\r
+\r
+/****d* IBA Base: Constants/MAD_BLOCK_SIZE\r
+* NAME\r
+*      MAD_BLOCK_SIZE\r
+*\r
+* DESCRIPTION\r
+*      Size of a non-RMPP MAD datagram.\r
+*\r
+* SOURCE\r
+*/\r
+#define MAD_BLOCK_SIZE                                         256\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/MAD_RMPP_HDR_SIZE\r
+* NAME\r
+*      MAD_RMPP_HDR_SIZE\r
+*\r
+* DESCRIPTION\r
+*      Size of an RMPP header, including the common MAD header.\r
+*\r
+* SOURCE\r
+*/\r
+#define MAD_RMPP_HDR_SIZE                                      36\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/MAD_RMPP_DATA_SIZE\r
+* NAME\r
+*      MAD_RMPP_DATA_SIZE\r
+*\r
+* DESCRIPTION\r
+*      Size of an RMPP transaction data section.\r
+*\r
+* SOURCE\r
+*/\r
+#define MAD_RMPP_DATA_SIZE             (MAD_BLOCK_SIZE - MAD_RMPP_HDR_SIZE)\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/MAD_BLOCK_GRH_SIZE\r
+* NAME\r
+*      MAD_BLOCK_GRH_SIZE\r
+*\r
+* DESCRIPTION\r
+*      Size of a MAD datagram, including the GRH.\r
+*\r
+* SOURCE\r
+*/\r
+#define MAD_BLOCK_GRH_SIZE                                     296\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_LID_PERMISSIVE\r
+* NAME\r
+*      IB_LID_PERMISSIVE\r
+*\r
+* DESCRIPTION\r
+*      Permissive LID\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_LID_PERMISSIVE                                      0xFFFF\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_DEFAULT_PKEY\r
+* NAME\r
+*      IB_DEFAULT_PKEY\r
+*\r
+* DESCRIPTION\r
+*      P_Key value for the default partition.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_DEFAULT_PKEY                                                0xFFFF\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_QP1_WELL_KNOWN_Q_KEY\r
+* NAME\r
+*      IB_QP1_WELL_KNOWN_Q_KEY\r
+*\r
+* DESCRIPTION\r
+*      Well-known Q_Key for QP1 privileged mode access (15.4.2).\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_QP1_WELL_KNOWN_Q_KEY                                CL_NTOH32(0x80010000)\r
+/*********/\r
+\r
+#define IB_QP0                                                         0\r
+#define IB_QP1                                                         CL_NTOH32(1)\r
+\r
+#define IB_QP_PRIVILEGED_Q_KEY                         CL_NTOH32(0x80000000)\r
+\r
+/****d* IBA Base: Constants/IB_LID_UCAST_START\r
+* NAME\r
+*      IB_LID_UCAST_START\r
+*\r
+* DESCRIPTION\r
+*      Lowest valid unicast LID value.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_LID_UCAST_START_HO                          0x0001\r
+#define IB_LID_UCAST_START                                     (CL_HTON16(IB_LID_UCAST_START_HO))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_LID_UCAST_END\r
+* NAME\r
+*      IB_LID_UCAST_END\r
+*\r
+* DESCRIPTION\r
+*      Highest valid unicast LID value.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_LID_UCAST_END_HO                                    0xBFFF\r
+#define IB_LID_UCAST_END                                       (CL_HTON16(IB_LID_UCAST_END_HO))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_LID_MCAST_START\r
+* NAME\r
+*      IB_LID_MCAST_START\r
+*\r
+* DESCRIPTION\r
+*      Lowest valid multicast LID value.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_LID_MCAST_START_HO                          0xC000\r
+#define IB_LID_MCAST_START                                     (CL_HTON16(IB_LID_MCAST_START_HO))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_LID_MCAST_END\r
+* NAME\r
+*      IB_LID_MCAST_END\r
+*\r
+* DESCRIPTION\r
+*      Highest valid multicast LID value.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_LID_MCAST_END_HO                                    0xFFFE\r
+#define IB_LID_MCAST_END                                       (CL_HTON16(IB_LID_MCAST_END_HO))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_DEFAULT_SUBNET_PREFIX\r
+* NAME\r
+*      IB_DEFAULT_SUBNET_PREFIX\r
+*\r
+* DESCRIPTION\r
+*      Default subnet GID prefix.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_DEFAULT_SUBNET_PREFIX                       (CL_HTON64(0xFE80000000000000ULL))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_NODE_NUM_PORTS_MAX\r
+* NAME\r
+*      IB_NODE_NUM_PORTS_MAX\r
+*\r
+* DESCRIPTION\r
+*      Maximum number of ports in a single node (14.2.5.7).\r
+* SOURCE\r
+*/\r
+#define IB_NODE_NUM_PORTS_MAX                          0xFE\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_INVALID_PORT_NUM\r
+* NAME\r
+*      IB_INVALID_PORT_NUM\r
+*\r
+* DESCRIPTION\r
+*      Value used to indicate an invalid port number (14.2.5.10).\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_INVALID_PORT_NUM                                    0xFF\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_SUBNET_PATH_HOPS_MAX\r
+* NAME\r
+*      IB_SUBNET_PATH_HOPS_MAX\r
+*\r
+* DESCRIPTION\r
+*      Maximum number of directed route switch hops in a subnet (14.2.1.2).\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SUBNET_PATH_HOPS_MAX                                64\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_PKEY_MAX_BLOCKS\r
+* NAME\r
+*      IB_PKEY_MAX_BLOCKS\r
+*\r
+* DESCRIPTION\r
+*      Maximum number of PKEY blocks (14.2.5.7).\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_PKEY_MAX_BLOCKS                                     2048\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_MCAST_MAX_BLOCK_ID\r
+* NAME\r
+*      IB_MCAST_MAX_BLOCK_ID\r
+*\r
+* DESCRIPTION\r
+*      Maximum number of Multicast port mask blocks\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCAST_MAX_BLOCK_ID                          511\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_MCAST_BLOCK_ID_MASK_HO\r
+* NAME\r
+*      IB_MCAST_BLOCK_ID_MASK_HO\r
+*\r
+* DESCRIPTION\r
+*      Mask (host order) to recover the Multicast block ID.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCAST_BLOCK_ID_MASK_HO                      0x000001FF\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_MCAST_BLOCK_SIZE\r
+* NAME\r
+*      IB_MCAST_BLOCK_SIZE\r
+*\r
+* DESCRIPTION\r
+*      Number of port mask entries in a multicast forwarding table block.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCAST_BLOCK_SIZE                                    32\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_MCAST_MASK_SIZE\r
+* NAME\r
+*      IB_MCAST_MASK_SIZE\r
+*\r
+* DESCRIPTION\r
+*      Number of port mask bits in each entry in the multicast forwarding table.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCAST_MASK_SIZE                                     16\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_MCAST_POSITION_MASK_HO\r
+* NAME\r
+*      IB_MCAST_POSITION_MASK_HO\r
+*\r
+* DESCRIPTION\r
+*      Mask (host order) to recover the multicast block position.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCAST_POSITION_MASK_HO                              0xF0000000\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_MCAST_POSITION_MAX\r
+* NAME\r
+*      IB_MCAST_POSITION_MAX\r
+*\r
+* DESCRIPTION\r
+*      Maximum value for the multicast block position.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCAST_POSITION_MAX                          0xF\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_MCAST_POSITION_SHIFT\r
+* NAME\r
+*      IB_MCAST_POSITION_SHIFT\r
+*\r
+* DESCRIPTION\r
+*      Shift value to normalize the multicast block position value.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCAST_POSITION_SHIFT                                28\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_PKEY_ENTRIES_MAX\r
+* NAME\r
+*      IB_PKEY_ENTRIES_MAX\r
+*\r
+* DESCRIPTION\r
+*      Maximum number of PKEY entries per port (14.2.5.7).\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_PKEY_ENTRIES_MAX (IB_PKEY_MAX_BLOCKS * IB_NUM_PKEY_ELEMENTS_IN_BLOCK)\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_PKEY_BASE_MASK\r
+* NAME\r
+*      IB_PKEY_BASE_MASK\r
+*\r
+* DESCRIPTION\r
+*      Masks for the base P_Key value given a P_Key Entry.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_PKEY_BASE_MASK                                      (CL_HTON16(0x7FFF))\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_PKEY_TYPE_MASK\r
+* NAME\r
+*      IB_PKEY_TYPE_MASK\r
+*\r
+* DESCRIPTION\r
+*      Masks for the P_Key membership type given a P_Key Entry.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_PKEY_TYPE_MASK                                      (CL_NTOH16(0x8000))\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_DEFAULT_PARTIAL_PKEY\r
+* NAME\r
+*      IB_DEFAULT_PARTIAL_PKEY \r
+*\r
+* DESCRIPTION\r
+*      0x7FFF in network order\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_DEFAULT_PARTIAL_PKEY                                       (CL_HTON16(0x7FFF))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_SUBN_LID\r
+* NAME\r
+*      IB_MCLASS_SUBN_LID\r
+*\r
+* DESCRIPTION\r
+*      Subnet Management Class, Subnet Manager LID routed (13.4.4)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_SUBN_LID                                     0x01\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_SUBN_DIR\r
+* NAME\r
+*      IB_MCLASS_SUBN_DIR\r
+*\r
+* DESCRIPTION\r
+*      Subnet Management Class, Subnet Manager directed route (13.4.4)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_SUBN_DIR                                     0x81\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_SUBN_ADM\r
+* NAME\r
+*      IB_MCLASS_SUBN_ADM\r
+*\r
+* DESCRIPTION\r
+*      Subnet Management Class, Subnet Administration (13.4.4)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_SUBN_ADM                                     0x03\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_PERF\r
+* NAME\r
+*      IB_MCLASS_PERF\r
+*\r
+* DESCRIPTION\r
+*      Subnet Management Class, Performance Manager (13.4.4)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_PERF                                         0x04\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_BM\r
+* NAME\r
+*      IB_MCLASS_BM\r
+*\r
+* DESCRIPTION\r
+*      Subnet Management Class, Baseboard Manager (13.4.4)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_BM                                           0x05\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_DEV_MGMT\r
+* NAME\r
+*      IB_MCLASS_DEV_MGMT\r
+*\r
+* DESCRIPTION\r
+*      Subnet Management Class, Device Management (13.4.4)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_DEV_MGMT                                     0x06\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_COMM_MGMT\r
+* NAME\r
+*      IB_MCLASS_COMM_MGMT\r
+*\r
+* DESCRIPTION\r
+*      Subnet Management Class, Communication Management (13.4.4)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_COMM_MGMT                                    0x07\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_SNMP\r
+* NAME\r
+*      IB_MCLASS_SNMP\r
+*\r
+* DESCRIPTION\r
+*      Subnet Management Class, SNMP Tunneling (13.4.4)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_SNMP                                         0x08\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_VENDOR_LOW_RANGE_MIN\r
+* NAME\r
+*      IB_MCLASS_VENDOR_LOW_RANGE_MIN\r
+*\r
+* DESCRIPTION\r
+*      Subnet Management Class, Vendor Specific Low Range Start\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_VENDOR_LOW_RANGE_MIN 0x09\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_VENDOR_LOW_RANGE_MAX\r
+* NAME\r
+*      IB_MCLASS_VENDOR_LOW_RANGE_MAX\r
+*\r
+* DESCRIPTION\r
+*      Subnet Management Class, Vendor Specific Low Range End\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_VENDOR_LOW_RANGE_MAX 0x0f\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_DEV_ADM\r
+* NAME\r
+*      IB_MCLASS_DEV_ADM\r
+*\r
+* DESCRIPTION\r
+*      Subnet Management Class, Device Administration\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_DEV_ADM 0x10\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_BIS\r
+* NAME\r
+*      IB_MCLASS_BIS\r
+*\r
+* DESCRIPTION\r
+*      Subnet Management Class, BIS\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_BIS 0x12\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_VENDOR_HIGH_RANGE_MIN\r
+* NAME\r
+*      IB_MCLASS_VENDOR_HIGH_RANGE_MIN\r
+*\r
+* DESCRIPTION\r
+*      Subnet Management Class, Vendor Specific High Range Start\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_VENDOR_HIGH_RANGE_MIN 0x30\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_VENDOR_HIGH_RANGE_MAX\r
+* NAME\r
+*      IB_MCLASS_VENDOR_HIGH_RANGE_MAX\r
+*\r
+* DESCRIPTION\r
+*      Subnet Management Class, Vendor Specific High Range End\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_VENDOR_HIGH_RANGE_MAX 0x4f\r
+/**********/\r
+\r
+/****f* IBA Base: Types/ib_class_is_vendor_specific_low\r
+* NAME\r
+*      ib_class_is_vendor_specific_low\r
+*\r
+* DESCRIPTION\r
+*      Indicates if the Class Code if a vendor specific class from \r
+*  the low range\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t        OSM_API\r
+ib_class_is_vendor_specific_low(\r
+       IN              const   uint8_t class_code )\r
+{\r
+       return( (class_code >= IB_MCLASS_VENDOR_LOW_RANGE_MIN) &&\r
+           (class_code <= IB_MCLASS_VENDOR_LOW_RANGE_MAX) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      class_code\r
+*              [in] The Management Datagram Class Code\r
+*\r
+* RETURN VALUE\r
+*      TRUE if the class is in the Low range of Vendor Specific MADs \r
+*      FALSE otherwise.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* IB_MCLASS_VENDOR_LOW_RANGE_MIN, IB_MCLASS_VENDOR_LOW_RANGE_MAX\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_class_is_vendor_specific_high\r
+* NAME\r
+*      ib_class_is_vendor_specific_high\r
+*\r
+* DESCRIPTION\r
+*      Indicates if the Class Code if a vendor specific class from \r
+*  the high range\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t        OSM_API\r
+ib_class_is_vendor_specific_high(\r
+       IN              const   uint8_t class_code )\r
+{\r
+       return( (class_code >= IB_MCLASS_VENDOR_HIGH_RANGE_MIN) &&\r
+           (class_code <= IB_MCLASS_VENDOR_HIGH_RANGE_MAX) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      class_code\r
+*              [in] The Management Datagram Class Code\r
+*\r
+* RETURN VALUE\r
+*      TRUE if the class is in the High range of Vendor Specific MADs \r
+*      FALSE otherwise.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* IB_MCLASS_VENDOR_HIGH_RANGE_MIN, IB_MCLASS_VENDOR_HIGH_RANGE_MAX\r
+*********/\r
+\r
+\r
+/****f* IBA Base: Types/ib_class_is_vendor_specific\r
+* NAME\r
+*      ib_class_is_vendor_specific\r
+*\r
+* DESCRIPTION\r
+*      Indicates if the Class Code if a vendor specific class\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t        OSM_API\r
+ib_class_is_vendor_specific(\r
+       IN              const   uint8_t class_code )\r
+{\r
+  return( ib_class_is_vendor_specific_low(class_code) ||\r
+                        ib_class_is_vendor_specific_high(class_code) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      class_code\r
+*              [in] The Management Datagram Class Code\r
+*\r
+* RETURN VALUE\r
+*      TRUE if the class is a Vendor Specific MAD\r
+*      FALSE otherwise.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*  ib_class_is_vendor_specific_low, ib_class_is_vendor_specific_high\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_class_is_rmpp\r
+* NAME\r
+*      ib_class_is_rmpp\r
+*\r
+* DESCRIPTION\r
+*      Indicates if the Class Code supports RMPP\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t        OSM_API\r
+ib_class_is_rmpp(\r
+        IN              const   uint8_t class_code )\r
+{\r
+       return( (class_code == IB_MCLASS_SUBN_ADM) ||\r
+               (class_code == IB_MCLASS_DEV_MGMT) ||\r
+               (class_code == IB_MCLASS_DEV_ADM) ||\r
+               (class_code == IB_MCLASS_BIS) ||\r
+               ib_class_is_vendor_specific_high( class_code ) ); \r
+}\r
+/*\r
+* PARAMETERS\r
+*      class_code\r
+*              [in] The Management Datagram Class Code\r
+*\r
+* RETURN VALUE\r
+*      TRUE if the class supports RMPP\r
+*      FALSE otherwise.\r
+*\r
+* NOTES\r
+*\r
+*********/\r
+\r
+/*\r
+ *     MAD methods\r
+ */\r
+\r
+/****d* IBA Base: Constants/IB_MAX_METHOD\r
+* NAME\r
+*      IB_MAX_METHOD\r
+*\r
+* DESCRIPTION\r
+*      Total number of methods available to a class, not including the R-bit.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAX_METHODS                                         128\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_METHOD_RESP_MASK\r
+* NAME\r
+*      IB_MAD_METHOD_RESP_MASK\r
+*\r
+* DESCRIPTION\r
+*      Response mask to extract 'R' bit from the method field. (13.4.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_METHOD_RESP_MASK                                0x80\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_METHOD_GET\r
+* NAME\r
+*      IB_MAD_METHOD_GET\r
+*\r
+* DESCRIPTION\r
+*      Get() Method (13.4.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_METHOD_GET                                      0x01\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_METHOD_SET\r
+* NAME\r
+*      IB_MAD_METHOD_SET\r
+*\r
+* DESCRIPTION\r
+*      Set() Method (13.4.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_METHOD_SET                                      0x02\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_METHOD_GET_RESP\r
+* NAME\r
+*      IB_MAD_METHOD_GET_RESP\r
+*\r
+* DESCRIPTION\r
+*      GetResp() Method (13.4.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_METHOD_GET_RESP                         0x81\r
+/**********/\r
+\r
+#define IB_MAD_METHOD_DELETE                           0x15\r
+\r
+/****d* IBA Base: Constants/IB_MAD_METHOD_GETTABLE\r
+* NAME\r
+*      IB_MAD_METHOD_GETTABLE\r
+*\r
+* DESCRIPTION\r
+*      SubnAdmGetTable() Method (15.2.2)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_METHOD_GETTABLE                         0x12\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_METHOD_GETTABLE_RESP\r
+* NAME\r
+*      IB_MAD_METHOD_GETTABLE_RESP\r
+*\r
+* DESCRIPTION\r
+*      SubnAdmGetTableResp() Method (15.2.2)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_METHOD_GETTABLE_RESP                    0x92\r
+\r
+/**********/\r
+\r
+#define IB_MAD_METHOD_GETTRACETABLE                    0x13\r
+#define IB_MAD_METHOD_GETMULTI                         0x14\r
+#define IB_MAD_METHOD_GETMULTI_RESP                    0x94\r
+\r
+\r
+/****d* IBA Base: Constants/IB_MAD_METHOD_SEND\r
+* NAME\r
+*      IB_MAD_METHOD_SEND\r
+*\r
+* DESCRIPTION\r
+*      Send() Method (13.4.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_METHOD_SEND                                     0x03\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_METHOD_TRAP\r
+* NAME\r
+*      IB_MAD_METHOD_TRAP\r
+*\r
+* DESCRIPTION\r
+*      Trap() Method (13.4.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_METHOD_TRAP                                     0x05\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_METHOD_REPORT\r
+* NAME\r
+*      IB_MAD_METHOD_REPORT\r
+*\r
+* DESCRIPTION\r
+*      Report() Method (13.4.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_METHOD_REPORT                           0x06\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_METHOD_REPORT_RESP\r
+* NAME\r
+*      IB_MAD_METHOD_REPORT_RESP\r
+*\r
+* DESCRIPTION\r
+*      ReportResp() Method (13.4.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_METHOD_REPORT_RESP                      0x86\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_METHOD_TRAP_REPRESS\r
+* NAME\r
+*      IB_MAD_METHOD_TRAP_REPRESS\r
+*\r
+* DESCRIPTION\r
+*      TrapRepress() Method (13.4.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_METHOD_TRAP_REPRESS                     0x07\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_STATUS_BUSY\r
+* NAME\r
+*      IB_MAD_STATUS_BUSY\r
+*\r
+* DESCRIPTION\r
+*      Temporarily busy, MAD discarded (13.4.7)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_STATUS_BUSY                             (CL_HTON16(0x0001))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_STATUS_REDIRECT\r
+* NAME\r
+*      IB_MAD_STATUS_REDIRECT\r
+*\r
+* DESCRIPTION\r
+*      QP Redirection required (13.4.7)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_STATUS_REDIRECT                         (CL_HTON16(0x0002))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_STATUS_UNSUP_CLASS_VER\r
+* NAME\r
+*      IB_MAD_STATUS_UNSUP_CLASS_VER\r
+*\r
+* DESCRIPTION\r
+*      Unsupported class version (13.4.7)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_STATUS_UNSUP_CLASS_VER                  (CL_HTON16(0x0004))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_STATUS_UNSUP_METHOD\r
+* NAME\r
+*      IB_MAD_STATUS_UNSUP_METHOD\r
+*\r
+* DESCRIPTION\r
+*      Unsupported method (13.4.7)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_STATUS_UNSUP_METHOD                     (CL_HTON16(0x0008))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_STATUS_UNSUP_METHOD_ATTR\r
+* NAME\r
+*      IB_MAD_STATUS_UNSUP_METHOD_ATTR\r
+*\r
+* DESCRIPTION\r
+*      Unsupported method/attribute combination (13.4.7)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_STATUS_UNSUP_METHOD_ATTR                        (CL_HTON16(0x000C))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_STATUS_INVALID_FIELD\r
+* NAME\r
+*      IB_MAD_STATUS_INVALID_FIELD\r
+*\r
+* DESCRIPTION\r
+*      Attribute contains one or more invalid fields (13.4.7)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_STATUS_INVALID_FIELD                    (CL_HTON16(0x001C))\r
+/**********/\r
+\r
+#define IB_MAD_STATUS_CLASS_MASK                       (CL_HTON16(0xFF00))\r
+\r
+#define IB_SA_MAD_STATUS_SUCCESS                       (CL_HTON16(0x0000))\r
+#define IB_SA_MAD_STATUS_NO_RESOURCES                  (CL_HTON16(0x0100))\r
+#define IB_SA_MAD_STATUS_REQ_INVALID                   (CL_HTON16(0x0200))\r
+#define IB_SA_MAD_STATUS_NO_RECORDS                    (CL_HTON16(0x0300))\r
+#define IB_SA_MAD_STATUS_TOO_MANY_RECORDS              (CL_HTON16(0x0400))\r
+#define IB_SA_MAD_STATUS_INVALID_GID                   (CL_HTON16(0x0500))\r
+#define IB_SA_MAD_STATUS_INSUF_COMPS                   (CL_HTON16(0x0600))\r
+\r
+#define IB_DM_MAD_STATUS_NO_IOC_RESP                   (CL_HTON16(0x0100))\r
+#define IB_DM_MAD_STATUS_NO_SVC_ENTRIES                        (CL_HTON16(0x0200))\r
+#define IB_DM_MAD_STATUS_IOC_FAILURE                   (CL_HTON16(0x8000))\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_CLASS_PORT_INFO\r
+* NAME\r
+*      IB_MAD_ATTR_CLASS_PORT_INFO\r
+*\r
+* DESCRIPTION\r
+*      ClassPortInfo attribute (13.4.8)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_CLASS_PORT_INFO                    (CL_NTOH16(0x0001))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_NOTICE\r
+* NAME\r
+*      IB_MAD_ATTR_NOTICE\r
+*\r
+* DESCRIPTION\r
+*      Notice attribute (13.4.8)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_NOTICE                                     (CL_NTOH16(0x0002))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_INFORM_INFO\r
+* NAME\r
+*      IB_MAD_ATTR_INFORM_INFO\r
+*\r
+* DESCRIPTION\r
+*      InformInfo attribute (13.4.8)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_INFORM_INFO                                (CL_NTOH16(0x0003))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_NODE_DESC\r
+* NAME\r
+*      IB_MAD_ATTR_NODE_DESC\r
+*\r
+* DESCRIPTION\r
+*      NodeDescription attribute (14.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_NODE_DESC                          (CL_NTOH16(0x0010))\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORT_SMPL_CTRL\r
+* NAME\r
+*      IB_MAD_ATTR_PORT_SMPL_CTRL\r
+*\r
+* DESCRIPTION\r
+*      NodeDescription attribute (16.1.2)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_PORT_SMPL_CTRL                     (CL_NTOH16(0x0010))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_NODE_INFO\r
+* NAME\r
+*      IB_MAD_ATTR_NODE_INFO\r
+*\r
+* DESCRIPTION\r
+*      NodeInfo attribute (14.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_NODE_INFO                          (CL_NTOH16(0x0011))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORT_SMPL_RSLT\r
+* NAME\r
+*      IB_MAD_ATTR_PORT_SMPL_RSLT\r
+*\r
+* DESCRIPTION\r
+*      NodeInfo attribute (16.1.2)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_PORT_SMPL_RSLT                     (CL_NTOH16(0x0011))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_SWITCH_INFO\r
+* NAME\r
+*      IB_MAD_ATTR_SWITCH_INFO\r
+*\r
+* DESCRIPTION\r
+*      SwitchInfo attribute (14.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_SWITCH_INFO                                (CL_NTOH16(0x0012))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORT_CNTRS\r
+* NAME\r
+*      IB_MAD_ATTR_PORT_CNTRS\r
+*\r
+* DESCRIPTION\r
+*      SwitchInfo attribute (16.1.2)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_PORT_CNTRS                         (CL_NTOH16(0x0012))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_GUID_INFO\r
+* NAME\r
+*      IB_MAD_ATTR_GUID_INFO\r
+*\r
+* DESCRIPTION\r
+*      GUIDInfo attribute (14.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_GUID_INFO                          (CL_NTOH16(0x0014))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORT_INFO\r
+* NAME\r
+*      IB_MAD_ATTR_PORT_INFO\r
+*\r
+* DESCRIPTION\r
+*      PortInfo attribute (14.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_PORT_INFO                          (CL_NTOH16(0x0015))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_P_KEY_TABLE\r
+* NAME\r
+*      IB_MAD_ATTR_P_KEY_TABLE\r
+*\r
+* DESCRIPTION\r
+*      PartitionTable attribute (14.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_P_KEY_TABLE                                (CL_NTOH16(0x0016))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_SLVL_TABLE\r
+* NAME\r
+*      IB_MAD_ATTR_SLVL_TABLE\r
+*\r
+* DESCRIPTION\r
+*      SL VL Mapping Table attribute (14.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_SLVL_TABLE                         (CL_NTOH16(0x0017))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_VL_ARBITRATION\r
+* NAME\r
+*      IB_MAD_ATTR_VL_ARBITRATION\r
+*\r
+* DESCRIPTION\r
+*      VL Arbitration Table attribute (14.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_VL_ARBITRATION                     (CL_NTOH16(0x0018))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_LIN_FWD_TBL\r
+* NAME\r
+*      IB_MAD_ATTR_LIN_FWD_TBL\r
+*\r
+* DESCRIPTION\r
+*      Switch linear forwarding table\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_LIN_FWD_TBL                                (CL_NTOH16(0x0019))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_RND_FWD_TBL\r
+* NAME\r
+*      IB_MAD_ATTR_RND_FWD_TBL\r
+*\r
+* DESCRIPTION\r
+*      Switch random forwarding table\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_RND_FWD_TBL                                (CL_NTOH16(0x001A))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_MCAST_FWD_TBL\r
+* NAME\r
+*      IB_MAD_ATTR_MCAST_FWD_TBL\r
+*\r
+* DESCRIPTION\r
+*      Switch multicast forwarding table\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_MCAST_FWD_TBL                      (CL_NTOH16(0x001B))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_NODE_RECORD\r
+* NAME\r
+*      IB_MAD_ATTR_NODE_RECORD\r
+*\r
+* DESCRIPTION\r
+*      NodeRecord attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_NODE_RECORD                                (CL_NTOH16(0x0011))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORTINFO_RECORD\r
+* NAME\r
+*      IB_MAD_ATTR_PORTINFO_RECORD\r
+*\r
+* DESCRIPTION\r
+*      PortInfoRecord attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_PORTINFO_RECORD                    (CL_NTOH16(0x0012))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_SWITCH_INFO_RECORD\r
+* NAME\r
+*       IB_MAD_ATTR_SWITCH_INFO_RECORD\r
+*\r
+* DESCRIPTION\r
+*       SwitchInfoRecord attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_SWITCH_INFO_RECORD                 (CL_NTOH16(0x0014))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_LINK_RECORD\r
+* NAME\r
+*      IB_MAD_ATTR_LINK_RECORD\r
+*\r
+* DESCRIPTION\r
+*      LinkRecord attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_LINK_RECORD                                (CL_NTOH16(0x0020))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_SM_INFO\r
+* NAME\r
+*      IB_MAD_ATTR_SM_INFO\r
+*\r
+* DESCRIPTION\r
+*      SMInfo attribute (14.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_SM_INFO                            (CL_NTOH16(0x0020))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_SMINFO_RECORD\r
+* NAME\r
+*      IB_MAD_ATTR_SMINFO_RECORD\r
+*\r
+* DESCRIPTION\r
+*      SMInfoRecord attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_SMINFO_RECORD                      (CL_NTOH16(0x0018))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_GUIDINFO_RECORD\r
+* NAME\r
+*       IB_MAD_ATTR_GUIDINFO_RECORD\r
+*\r
+* DESCRIPTION\r
+*       GuidInfoRecord attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_GUIDINFO_RECORD                    (CL_NTOH16(0x0030))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_VENDOR_DIAG\r
+* NAME\r
+*      IB_MAD_ATTR_VENDOR_DIAG\r
+*\r
+* DESCRIPTION\r
+*      VendorDiag attribute (14.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_VENDOR_DIAG                                (CL_NTOH16(0x0030))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_LED_INFO\r
+* NAME\r
+*      IB_MAD_ATTR_LED_INFO\r
+*\r
+* DESCRIPTION\r
+*      LedInfo attribute (14.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_LED_INFO                           (CL_NTOH16(0x0031))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_SERVICE_RECORD\r
+* NAME\r
+*      IB_MAD_ATTR_SERVICE_RECORD\r
+*\r
+* DESCRIPTION\r
+*      ServiceRecord attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_SERVICE_RECORD                     (CL_NTOH16(0x0031))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_LFT_RECORD\r
+* NAME\r
+*      IB_MAD_ATTR_LFT_RECORD\r
+*\r
+* DESCRIPTION\r
+*      LinearForwardingTableRecord attribute (15.2.5.6)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_LFT_RECORD                         (CL_NTOH16(0x0015))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_MFT_RECORD\r
+* NAME\r
+*       IB_MAD_ATTR_MFT_RECORD\r
+*\r
+* DESCRIPTION\r
+*       MulticastForwardingTableRecord attribute (15.2.5.8)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_MFT_RECORD                         (CL_NTOH16(0x0017))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_PKEYTBL_RECORD\r
+* NAME\r
+*      IB_MAD_ATTR_PKEYTBL_RECORD\r
+*\r
+* DESCRIPTION\r
+*      PKEY Table Record attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_PKEY_TBL_RECORD                    (CL_NTOH16(0x0033))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_PATH_RECORD\r
+* NAME\r
+*      IB_MAD_ATTR_PATH_RECORD\r
+*\r
+* DESCRIPTION\r
+*      PathRecord attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_PATH_RECORD                                (CL_NTOH16(0x0035))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_VLARB_RECORD\r
+* NAME\r
+*      IB_MAD_ATTR_VLARB_RECORD\r
+*\r
+* DESCRIPTION\r
+*      VL Arbitration Table Record attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_VLARB_RECORD                       (CL_NTOH16(0x0036))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_SLVL_RECORD\r
+* NAME\r
+*      IB_MAD_ATTR_SLVL_RECORD\r
+*\r
+* DESCRIPTION\r
+*      SLtoVL Mapping Table Record attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_SLVL_RECORD                                (CL_NTOH16(0x0013))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_MCMEMBER_RECORD\r
+* NAME\r
+*      IB_MAD_ATTR_MCMEMBER_RECORD\r
+*\r
+* DESCRIPTION\r
+*      MCMemberRecord attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_MCMEMBER_RECORD                    (CL_NTOH16(0x0038))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_TRACE_RECORD\r
+* NAME\r
+*      IB_MAD_ATTR_TRACE_RECORD\r
+*\r
+* DESCRIPTION\r
+*      TraceRecord attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_TRACE_RECORD                       (CL_NTOH16(0x0039))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_MULTIPATH_RECORD\r
+* NAME\r
+*      IB_MAD_ATTR_MULTIPATH_RECORD\r
+*\r
+* DESCRIPTION\r
+*      MultiPathRecord attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_MULTIPATH_RECORD                   (CL_NTOH16(0x003A))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_SVC_ASSOCIATION_RECORD\r
+* NAME\r
+*      IB_MAD_ATTR_SVC_ASSOCIATION_RECORD\r
+*\r
+* DESCRIPTION\r
+*      Service Association Record attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_SVC_ASSOCIATION_RECORD             (CL_NTOH16(0x003B))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_INFORM_INFO_RECORD\r
+* NAME\r
+*      IB_MAD_ATTR_INFORM_INFO_RECORD\r
+*\r
+* DESCRIPTION\r
+*      InformInfo Record attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_INFORM_INFO_RECORD                 (CL_NTOH16(0x00F3))\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_IO_UNIT_INFO\r
+* NAME\r
+*      IB_MAD_ATTR_IO_UNIT_INFO\r
+*\r
+* DESCRIPTION\r
+*      IOUnitInfo attribute (16.3.3)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_IO_UNIT_INFO                       (CL_NTOH16(0x0010))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_IO_CONTROLLER_PROFILE\r
+* NAME\r
+*      IB_MAD_ATTR_IO_CONTROLLER_PROFILE\r
+*\r
+* DESCRIPTION\r
+*      IOControllerProfile attribute (16.3.3)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_IO_CONTROLLER_PROFILE      (CL_NTOH16(0x0011))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_SERVICE_ENTRIES\r
+* NAME\r
+*      IB_MAD_ATTR_SERVICE_ENTRIES\r
+*\r
+* DESCRIPTION\r
+*      ServiceEntries attribute (16.3.3)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_SERVICE_ENTRIES                    (CL_NTOH16(0x0012))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_DIAGNOSTIC_TIMEOUT\r
+* NAME\r
+*      IB_MAD_ATTR_DIAGNOSTIC_TIMEOUT\r
+*\r
+* DESCRIPTION\r
+*      DiagnosticTimeout attribute (16.3.3)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_DIAGNOSTIC_TIMEOUT         (CL_NTOH16(0x0020))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_PREPARE_TO_TEST\r
+* NAME\r
+*      IB_MAD_ATTR_PREPARE_TO_TEST\r
+*\r
+* DESCRIPTION\r
+*      PrepareToTest attribute (16.3.3)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_PREPARE_TO_TEST                    (CL_NTOH16(0x0021))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_TEST_DEVICE_ONCE\r
+* NAME\r
+*      IB_MAD_ATTR_TEST_DEVICE_ONCE\r
+*\r
+* DESCRIPTION\r
+*      TestDeviceOnce attribute (16.3.3)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_TEST_DEVICE_ONCE           (CL_NTOH16(0x0022))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_TEST_DEVICE_LOOP\r
+* NAME\r
+*      IB_MAD_ATTR_TEST_DEVICE_LOOP\r
+*\r
+* DESCRIPTION\r
+*      TestDeviceLoop attribute (16.3.3)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_TEST_DEVICE_LOOP           (CL_NTOH16(0x0023))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_DIAG_CODE\r
+* NAME\r
+*      IB_MAD_ATTR_DIAG_CODE\r
+*\r
+* DESCRIPTION\r
+*      DiagCode attribute (16.3.3)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_DIAG_CODE                          (CL_NTOH16(0x0024))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_SVC_ASSOCIATION_RECORD\r
+* NAME\r
+*      IB_MAD_ATTR_SVC_ASSOCIATION_RECORD\r
+*\r
+* DESCRIPTION\r
+*      Service Association Record attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_SVC_ASSOCIATION_RECORD     (CL_NTOH16(0x003B))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_NODE_TYPE_CA\r
+* NAME\r
+*      IB_NODE_TYPE_CA\r
+*\r
+* DESCRIPTION\r
+*      Encoded generic node type used in MAD attributes (13.4.8.2)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_NODE_TYPE_CA                                                0x01\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_NODE_TYPE_SWITCH\r
+* NAME\r
+*      IB_NODE_TYPE_SWITCH\r
+*\r
+* DESCRIPTION\r
+*      Encoded generic node type used in MAD attributes (13.4.8.2)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_NODE_TYPE_SWITCH                                    0x02\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_NODE_TYPE_ROUTER\r
+* NAME\r
+*      IB_NODE_TYPE_ROUTER\r
+*\r
+* DESCRIPTION\r
+*      Encoded generic node type used in MAD attributes (13.4.8.2)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_NODE_TYPE_ROUTER                                    0x03\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_NOTICE_NODE_TYPE_CA\r
+* NAME\r
+*      IB_NOTICE_NODE_TYPE_CA\r
+*\r
+* DESCRIPTION\r
+*      Encoded generic node type used in MAD attributes (13.4.8.2)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_NOTICE_NODE_TYPE_CA                         (CL_NTOH32(0x000001))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_NOTICE_NODE_TYPE_SWITCH\r
+* NAME\r
+*      IB_NOTICE_NODE_TYPE_SWITCH\r
+*\r
+* DESCRIPTION\r
+*      Encoded generic node type used in MAD attributes (13.4.8.2)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_NOTICE_NODE_TYPE_SWITCH                     (CL_NTOH32(0x000002))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_NOTICE_NODE_TYPE_ROUTER\r
+* NAME\r
+*      IB_NOTICE_NODE_TYPE_ROUTER\r
+*\r
+* DESCRIPTION\r
+*      Encoded generic node type used in MAD attributes (13.4.8.2)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_NOTICE_NODE_TYPE_ROUTER                     (CL_NTOH32(0x000003))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_NOTICE_NODE_TYPE_SUBN_MGMT\r
+* NAME\r
+*      IB_NOTICE_NODE_TYPE_SUBN_MGMT\r
+*\r
+* DESCRIPTION\r
+*      Encoded generic node type used in MAD attributes (13.4.8.2).\r
+*      Note that this value is not defined for the NodeType field\r
+*      of the NodeInfo attribute (14.2.5.3).\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_NOTICE_NODE_TYPE_SUBN_MGMT          (CL_NTOH32(0x000004))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MTU_LEN_TYPE\r
+* NAME\r
+*      IB_MTU_LEN_TYPE\r
+*\r
+* DESCRIPTION\r
+*      Encoded path MTU.\r
+*              1: 256\r
+*              2: 512\r
+*              3: 1024\r
+*              4: 2048\r
+*              5: 4096\r
+*              others: reserved\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MTU_LEN_256                                                 1\r
+#define IB_MTU_LEN_512                                                 2\r
+#define IB_MTU_LEN_1024                                                        3\r
+#define IB_MTU_LEN_2048                                                        4\r
+#define IB_MTU_LEN_4096                                                        5\r
+\r
+#define IB_MIN_MTU    IB_MTU_LEN_256\r
+#define IB_MAX_MTU    IB_MTU_LEN_4096\r
+\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_PATH_SELECTOR_TYPE\r
+* NAME\r
+*      IB_PATH_SELECTOR_TYPE\r
+*\r
+* DESCRIPTION\r
+*      Path selector.\r
+*              0: greater than specified\r
+*              1: less than specified\r
+*              2: exactly the specified\r
+*              3: largest available\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_PATH_SELECTOR_GREATER_THAN          0\r
+#define IB_PATH_SELECTOR_LESS_THAN             1\r
+#define IB_PATH_SELECTOR_EXACTLY               2\r
+#define IB_PATH_SELECTOR_LARGEST               3\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_STATE_NOTACTIVE\r
+* NAME\r
+*      IB_SMINFO_STATE_NOTACTIVE\r
+*\r
+* DESCRIPTION\r
+*      Encoded state value used in the SMInfo attribute.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_STATE_NOTACTIVE                      0\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_STATE_DISCOVERING\r
+* NAME\r
+*      IB_SMINFO_STATE_DISCOVERING\r
+*\r
+* DESCRIPTION\r
+*      Encoded state value used in the SMInfo attribute.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_STATE_DISCOVERING                    1\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_STATE_STANDBY\r
+* NAME\r
+*      IB_SMINFO_STATE_STANDBY\r
+*\r
+* DESCRIPTION\r
+*      Encoded state value used in the SMInfo attribute.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_STATE_STANDBY                                2\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_STATE_MASTER\r
+* NAME\r
+*      IB_SMINFO_STATE_MASTER\r
+*\r
+* DESCRIPTION\r
+*      Encoded state value used in the SMInfo attribute.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_STATE_MASTER                         3\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_PATH_REC_SL_MASK\r
+* NAME\r
+*      IB_PATH_REC_SL_MASK\r
+*\r
+* DESCRIPTION\r
+*      Mask for the sl field for path record\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_PATH_REC_SL_MASK                            0x000F\r
+\r
+/****d* IBA Base: Constants/IB_MULTIPATH_REC_SL_MASK\r
+* NAME\r
+*      IB_MILTIPATH_REC_SL_MASK\r
+*\r
+* DESCRIPTION\r
+*      Mask for the sl field for MultiPath record\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MULTIPATH_REC_SL_MASK                       0x000F\r
+\r
+/****d* IBA Base: Constants/IB_PATH_REC_QOS_CLASS_MASK\r
+* NAME\r
+*      IB_PATH_REC_QOS_CLASS_MASK\r
+*\r
+* DESCRIPTION\r
+*      Mask for the QoS class field for path record\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_PATH_REC_QOS_CLASS_MASK                     0xFFF0\r
+\r
+/****d* IBA Base: Constants/IB_MULTIPATH_REC_QOS_CLASS_MASK\r
+* NAME\r
+*      IB_MULTIPATH_REC_QOS_CLASS_MASK\r
+*\r
+* DESCRIPTION\r
+*      Mask for the QoS class field for MultiPath record\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MULTIPATH_REC_QOS_CLASS_MASK                        0xFFF0\r
+\r
+/****d* IBA Base: Constants/IB_PATH_REC_SELECTOR_MASK\r
+* NAME\r
+*      IB_PATH_REC_SELECTOR_MASK\r
+*\r
+* DESCRIPTION\r
+*      Mask for the selector field for path record MTU, rate,\r
+*      and packet lifetime.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_PATH_REC_SELECTOR_MASK                      0xC0\r
+\r
+/****d* IBA Base: Constants/IB_MULTIPATH_REC_SELECTOR_MASK\r
+* NAME\r
+*       IB_MULTIPATH_REC_SELECTOR_MASK\r
+*\r
+* DESCRIPTION\r
+*       Mask for the selector field for multipath record MTU, rate,\r
+*       and packet lifetime.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MULTIPATH_REC_SELECTOR_MASK                       0xC0\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_PATH_REC_BASE_MASK\r
+* NAME\r
+*      IB_PATH_REC_BASE_MASK\r
+*\r
+* DESCRIPTION\r
+*      Mask for the base value field for path record MTU, rate,\r
+*      and packet lifetime.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_PATH_REC_BASE_MASK                          0x3F\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MULTIPATH_REC_BASE_MASK\r
+* NAME\r
+*       IB_MULTIPATH_REC_BASE_MASK\r
+*\r
+* DESCRIPTION\r
+*       Mask for the base value field for multipath record MTU, rate,\r
+*       and packet lifetime.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MULTIPATH_REC_BASE_MASK                      0x3F\r
+/**********/\r
+\r
+/****h* IBA Base/Type Definitions\r
+* NAME\r
+*      Type Definitions\r
+*\r
+* DESCRIPTION\r
+*      Definitions are from the InfiniBand Architecture Specification v1.2\r
+*\r
+*********/\r
+\r
+/****d* IBA Base: Types/ib_net16_t\r
+* NAME\r
+*      ib_net16_t\r
+*\r
+* DESCRIPTION\r
+*      Defines the network ordered type for 16-bit values.\r
+*\r
+* SOURCE\r
+*/\r
+typedef uint16_t       ib_net16_t;\r
+/**********/\r
+\r
+/****d* IBA Base: Types/ib_net32_t\r
+* NAME\r
+*      ib_net32_t\r
+*\r
+* DESCRIPTION\r
+*      Defines the network ordered type for 32-bit values.\r
+*\r
+* SOURCE\r
+*/\r
+typedef uint32_t       ib_net32_t;\r
+/**********/\r
+\r
+/****d* IBA Base: Types/ib_net64_t\r
+* NAME\r
+*      ib_net64_t\r
+*\r
+* DESCRIPTION\r
+*      Defines the network ordered type for 64-bit values.\r
+*\r
+* SOURCE\r
+*/\r
+typedef uint64_t       ib_net64_t;\r
+/**********/\r
+\r
+/****d* IBA Base: Types/ib_gid_prefix_t\r
+* NAME\r
+*      ib_gid_prefix_t\r
+*\r
+* DESCRIPTION\r
+*\r
+* SOURCE\r
+*/\r
+typedef ib_net64_t             ib_gid_prefix_t;\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/ib_link_states_t\r
+* NAME\r
+*      ib_link_states_t\r
+*\r
+* DESCRIPTION\r
+*      Defines the link states of a port.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_LINK_NO_CHANGE 0\r
+#define IB_LINK_DOWN      1\r
+#define IB_LINK_INIT     2\r
+#define IB_LINK_ARMED     3\r
+#define IB_LINK_ACTIVE    4\r
+#define IB_LINK_ACT_DEFER 5\r
+/**********/\r
+\r
+static const char* const __ib_node_type_str[] =\r
+{\r
+       "UNKNOWN",\r
+       "Channel Adapter",\r
+       "Switch",\r
+       "Router",\r
+       "Subnet Management"\r
+};\r
+\r
+/****f* IBA Base: Types/ib_get_node_type_str\r
+* NAME\r
+*      ib_get_node_type_str\r
+*\r
+* DESCRIPTION\r
+*      Returns a string for the specified node type.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline const char*      OSM_API\r
+ib_get_node_type_str(\r
+       IN uint32_t node_type )\r
+{\r
+       if( node_type >= IB_NOTICE_NODE_TYPE_ROUTER )\r
+               node_type = 0;\r
+       return( __ib_node_type_str[node_type] );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      node_type\r
+*              [in] Encoded node type as returned in the NodeInfo attribute.\r
+\r
+* RETURN VALUES\r
+*      Pointer to the node type string.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_node_info_t\r
+*********/\r
+\r
+static const char* const __ib_port_state_str[] =\r
+{\r
+       "No State Change (NOP)",\r
+       "DOWN",\r
+       "INIT",\r
+       "ARMED",\r
+       "ACTIVE",\r
+       "ACTDEFER",\r
+       "UNKNOWN"\r
+};\r
+\r
+/****f* IBA Base: Types/ib_get_port_state_str\r
+* NAME\r
+*      ib_get_port_state_str\r
+*\r
+* DESCRIPTION\r
+*      Returns a string for the specified port state.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline const char*      OSM_API\r
+ib_get_port_state_str(\r
+       IN                              uint8_t                                         port_state )\r
+{\r
+       if( port_state > IB_LINK_ACTIVE )\r
+               port_state = IB_LINK_ACTIVE + 1;\r
+       return( __ib_port_state_str[port_state] );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      node_type\r
+*              [in] Encoded port state as returned in the PortInfo attribute.\r
+\r
+* RETURN VALUES\r
+*      Pointer to the port state string.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_port_info_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_get_port_state_from_str\r
+* NAME\r
+*      ib_get_port_state_from_str\r
+*\r
+* DESCRIPTION\r
+*      Returns a string for the specified port state.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_get_port_state_from_str(\r
+       IN                              char*                                           p_port_state_str )\r
+{\r
+       if( !strncmp(p_port_state_str,"No State Change (NOP)", 12) )\r
+               return(0);\r
+       else if( !strncmp(p_port_state_str, "DOWN", 4) )\r
+               return(1);\r
+       else if( !strncmp(p_port_state_str, "INIT", 4) )\r
+               return(2);\r
+       else if( !strncmp(p_port_state_str, "ARMED" , 5) )\r
+               return(3);\r
+       else if( !strncmp(p_port_state_str, "ACTIVE", 6) )\r
+               return(4);\r
+       else if( !strncmp(p_port_state_str, "ACTDEFER", 8) )\r
+               return(5);\r
+       return(6);\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_port_state_str\r
+*              [in] A string matching one returned by ib_get_port_state_str\r
+*\r
+* RETURN VALUES\r
+*      The appropriate code.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_port_info_t\r
+*********/\r
+\r
+/****d* IBA Base: Constants/Join States\r
+* NAME\r
+*      Join States\r
+*\r
+* DESCRIPTION\r
+*      Defines the join state flags for multicast group management.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_JOIN_STATE_FULL             1\r
+#define IB_JOIN_STATE_NON              2\r
+#define IB_JOIN_STATE_SEND_ONLY                4\r
+/**********/\r
+\r
+/****f* IBA Base: Types/ib_pkey_get_base\r
+* NAME\r
+*      ib_pkey_get_base\r
+*\r
+* DESCRIPTION\r
+*      Returns the base P_Key value with the membership bit stripped.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net16_t       OSM_API\r
+ib_pkey_get_base(\r
+       IN      const   ib_net16_t              pkey )\r
+{\r
+       return( (ib_net16_t)(pkey & IB_PKEY_BASE_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      pkey\r
+*              [in] P_Key value\r
+*\r
+* RETURN VALUE\r
+*      Returns the base P_Key value with the membership bit stripped.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_pkey_is_full_member\r
+* NAME\r
+*      ib_pkey_is_full_member\r
+*\r
+* DESCRIPTION\r
+*      Indicates if the port is a full member of the parition.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t        OSM_API\r
+ib_pkey_is_full_member(\r
+       IN      const   ib_net16_t              pkey )\r
+{\r
+       return( (pkey & IB_PKEY_TYPE_MASK) == IB_PKEY_TYPE_MASK );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      pkey\r
+*              [in] P_Key value\r
+*\r
+* RETURN VALUE\r
+*      TRUE if the port is a full member of the partition.\r
+*      FALSE otherwise.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_pkey_get_base, ib_net16_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_pkey_is_invalid\r
+* NAME\r
+*      ib_pkey_is_invalid\r
+*\r
+* DESCRIPTION\r
+*      Returns TRUE if the given P_Key is an invalid P_Key\r
+*  C10-116: the CI shall regard a P_Key as invalid if its low-order\r
+*           15 bits are all zero...\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t        OSM_API\r
+ib_pkey_is_invalid(\r
+       IN      const   ib_net16_t              pkey )\r
+{\r
+  if (ib_pkey_get_base(pkey) == 0x0000)\r
+    return TRUE;\r
+\r
+  return FALSE;\r
+}\r
+/*\r
+* PARAMETERS\r
+*      pkey\r
+*              [in] P_Key value\r
+*\r
+* RETURN VALUE\r
+*      Returns the base P_Key value with the membership bit stripped.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****d* IBA Base: Types/ib_gid_t\r
+* NAME\r
+*      ib_gid_t\r
+*\r
+* DESCRIPTION\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef union _ib_gid\r
+{\r
+       uint8_t                         raw[16];\r
+       struct _ib_gid_unicast\r
+       {\r
+               ib_gid_prefix_t         prefix;\r
+               ib_net64_t              interface_id;\r
+\r
+       } PACK_SUFFIX unicast;\r
+\r
+       struct _ib_gid_multicast\r
+       {\r
+               uint8_t                 header[2];\r
+               uint8_t                 raw_group_id[14];\r
+\r
+       } PACK_SUFFIX multicast;\r
+\r
+}      PACK_SUFFIX ib_gid_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+*      raw\r
+*              GID represented as an unformated byte array.\r
+*\r
+*      unicast\r
+*              Typical unicast representation with subnet prefix and\r
+*              port GUID.\r
+*\r
+*      multicast\r
+*              Representation for multicast use.\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_gid_is_multicast\r
+* NAME\r
+*      ib_gid_is_multicast\r
+*\r
+* DESCRIPTION\r
+*       Returns a boolean indicating whether a GID is a multicast GID.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t        OSM_API\r
+ib_gid_is_multicast(\r
+       IN      const   ib_gid_t*               p_gid )\r
+{\r
+       return( p_gid->raw[0] == 0xFF );\r
+}\r
+\r
+/****f* IBA Base: Types/ib_gid_get_scope\r
+* NAME\r
+*      ib_gid_get_scope\r
+*\r
+* DESCRIPTION\r
+*      Returns scope of (assumed) multicast GID.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_mgid_get_scope(\r
+       IN      const   ib_gid_t*               p_gid )\r
+{\r
+       return( p_gid->raw[1] & 0x0F );\r
+}\r
+\r
+/****f* IBA Base: Types/ib_gid_set_scope\r
+* NAME\r
+*      ib_gid_set_scope\r
+*\r
+* DESCRIPTION\r
+*      Sets scope of (assumed) multicast GID.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_mgid_set_scope(\r
+        IN             ib_gid_t* const         p_gid,\r
+       IN      const   uint8_t                 scope )\r
+{\r
+       p_gid->raw[1] &= 0xF0;\r
+       p_gid->raw[1] |= scope & 0x0F;\r
+}\r
+\r
+/****f* IBA Base: Types/ib_gid_set_default\r
+* NAME\r
+*      ib_gid_set_default\r
+*\r
+* DESCRIPTION\r
+*      Sets a GID to the default value.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_gid_set_default(\r
+       IN              ib_gid_t* const         p_gid,\r
+       IN      const   ib_net64_t              interface_id )\r
+{\r
+       p_gid->unicast.prefix = IB_DEFAULT_SUBNET_PREFIX;\r
+       p_gid->unicast.interface_id = interface_id;\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_gid\r
+*              [in] Pointer to the GID object.\r
+*\r
+*      interface_id\r
+*              [in] Manufacturer assigned EUI64 value of a port.\r
+*\r
+* RETURN VALUES\r
+*      None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_gid_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_gid_get_subnet_prefix\r
+* NAME\r
+*      ib_gid_get_subnet_prefix\r
+*\r
+* DESCRIPTION\r
+*      Gets the subnet prefix from a GID.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net64_t       OSM_API\r
+ib_gid_get_subnet_prefix(\r
+       IN      const   ib_gid_t* const         p_gid )\r
+{\r
+       return( p_gid->unicast.prefix );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_gid\r
+*              [in] Pointer to the GID object.\r
+*\r
+* RETURN VALUES\r
+*      64-bit subnet prefix value.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_gid_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_gid_is_link_local\r
+* NAME\r
+*      ib_gid_is_link_local\r
+*\r
+* DESCRIPTION\r
+*      Returns TRUE if the unicast GID scoping indicates link local,\r
+*      FALSE otherwise.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t        OSM_API\r
+ib_gid_is_link_local(\r
+       IN      const   ib_gid_t* const         p_gid )\r
+{\r
+       return( ( ib_gid_get_subnet_prefix( p_gid ) &\r
+               CL_HTON64( 0xFFC0000000000000ULL ) ) == IB_DEFAULT_SUBNET_PREFIX );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_gid\r
+*              [in] Pointer to the GID object.\r
+*\r
+* RETURN VALUES\r
+*      Returns TRUE if the unicast GID scoping indicates link local,\r
+*      FALSE otherwise.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_gid_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_gid_is_site_local\r
+* NAME\r
+*      ib_gid_is_site_local\r
+*\r
+* DESCRIPTION\r
+*      Returns TRUE if the unicast GID scoping indicates site local,\r
+*      FALSE otherwise.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t        OSM_API\r
+ib_gid_is_site_local(\r
+       IN      const   ib_gid_t* const         p_gid )\r
+{\r
+       return( ( ib_gid_get_subnet_prefix( p_gid ) &\r
+               CL_HTON64( 0xFFFFFFFFFFFF0000ULL ) ) == CL_HTON64( 0xFEC0000000000000ULL ) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_gid\r
+*              [in] Pointer to the GID object.\r
+*\r
+* RETURN VALUES\r
+*      Returns TRUE if the unicast GID scoping indicates site local,\r
+*      FALSE otherwise.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_gid_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_gid_get_guid\r
+* NAME\r
+*      ib_gid_get_guid\r
+*\r
+* DESCRIPTION\r
+*      Gets the guid from a GID.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net64_t       OSM_API\r
+ib_gid_get_guid(\r
+       IN      const   ib_gid_t* const         p_gid )\r
+{\r
+       return( p_gid->unicast.interface_id );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_gid\r
+*              [in] Pointer to the GID object.\r
+*\r
+* RETURN VALUES\r
+*      64-bit GUID value.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_gid_t\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_path_rec_t\r
+* NAME\r
+*      ib_path_rec_t\r
+*\r
+* DESCRIPTION\r
+*      Path records encapsulate the properties of a given\r
+*      route between two end-points on a subnet.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_path_rec\r
+{\r
+       ib_net64_t                              service_id;\r
+       ib_gid_t                                dgid;\r
+       ib_gid_t                                sgid;\r
+       ib_net16_t                              dlid;\r
+       ib_net16_t                              slid;\r
+       ib_net32_t                              hop_flow_raw;\r
+       uint8_t                                 tclass;\r
+       uint8_t                                 num_path; \r
+       ib_net16_t                              pkey;\r
+       ib_net16_t                              qos_class_sl;\r
+       uint8_t                                 mtu;\r
+       uint8_t                                 rate;\r
+       uint8_t                                 pkt_life;\r
+       uint8_t                                 preference;\r
+       uint8_t                                 resv2[6];\r
+\r
+}      PACK_SUFFIX ib_path_rec_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+*      resv0\r
+*              Reserved bytes.\r
+*\r
+*      dgid\r
+*              GID of destination port.\r
+*\r
+*      sgid\r
+*              GID of source port.\r
+*\r
+*      dlid\r
+*              LID of destination port.\r
+*\r
+*      slid\r
+*              LID of source port.\r
+*\r
+*      hop_flow_raw\r
+*              Global routing parameters: hop count, flow label and raw bit.\r
+*\r
+*      tclass\r
+*              Another global routing parameter.\r
+*\r
+*      num_path\r
+*     Reversible path - 1 bit to say if path is reversible.\r
+*              num_path [6:0] In queries, maximum number of paths to return.\r
+*              In responses, undefined.\r
+*\r
+*      pkey\r
+*              Partition key (P_Key) to use on this path.\r
+*\r
+*      resv1\r
+*              Reserved byte.\r
+*\r
+*      sl\r
+*              Service level to use on this path.\r
+*\r
+*      mtu\r
+*              MTU and MTU selector fields to use on this path\r
+*\r
+*      rate\r
+*              Rate and rate selector fields to use on this path.\r
+*\r
+*      pkt_life\r
+*              Packet lifetime\r
+*\r
+*      preference\r
+*              Indicates the relative merit of this path versus other path\r
+*              records returned from the SA.  Lower numbers are better.\r
+*\r
+*      resv2\r
+*              Reserved bytes.\r
+* SEE ALSO\r
+*********/\r
+\r
+/* Path Record Component Masks */\r
+#define  IB_PR_COMPMASK_DGID              (CL_HTON64(((uint64_t)1)<<2))\r
+#define  IB_PR_COMPMASK_SGID              (CL_HTON64(((uint64_t)1)<<3))\r
+#define  IB_PR_COMPMASK_DLID              (CL_HTON64(((uint64_t)1)<<4))\r
+#define  IB_PR_COMPMASK_SLID              (CL_HTON64(((uint64_t)1)<<5))\r
+#define  IB_PR_COMPMASK_RAWTRAFFIC        (CL_HTON64(((uint64_t)1)<<6))\r
+#define  IB_PR_COMPMASK_RESV0             (CL_HTON64(((uint64_t)1)<<7))\r
+#define  IB_PR_COMPMASK_FLOWLABEL         (CL_HTON64(((uint64_t)1)<<8))\r
+#define  IB_PR_COMPMASK_HOPLIMIT          (CL_HTON64(((uint64_t)1)<<9))\r
+#define  IB_PR_COMPMASK_TCLASS            (CL_HTON64(((uint64_t)1)<<10))\r
+#define  IB_PR_COMPMASK_REVERSIBLE        (CL_HTON64(((uint64_t)1)<<11))\r
+#define  IB_PR_COMPMASK_NUMBPATH          (CL_HTON64(((uint64_t)1)<<12))\r
+#define  IB_PR_COMPMASK_PKEY              (CL_HTON64(((uint64_t)1)<<13))\r
+#define  IB_PR_COMPMASK_RESV1             (CL_HTON64(((uint64_t)1)<<14))\r
+#define  IB_PR_COMPMASK_SL                (CL_HTON64(((uint64_t)1)<<15))\r
+#define  IB_PR_COMPMASK_MTUSELEC          (CL_HTON64(((uint64_t)1)<<16))\r
+#define  IB_PR_COMPMASK_MTU               (CL_HTON64(((uint64_t)1)<<17))\r
+#define  IB_PR_COMPMASK_RATESELEC         (CL_HTON64(((uint64_t)1)<<18))\r
+#define  IB_PR_COMPMASK_RATE              (CL_HTON64(((uint64_t)1)<<19))\r
+#define  IB_PR_COMPMASK_PKTLIFETIMESELEC  (CL_HTON64(((uint64_t)1)<<20))\r
+#define  IB_PR_COMPMASK_PKTLIFETIME       (CL_HTON64(((uint64_t)1)<<21))\r
+\r
+/* Link Record Component Masks */\r
+#define IB_LR_COMPMASK_FROM_LID           (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_LR_COMPMASK_FROM_PORT          (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_LR_COMPMASK_TO_PORT            (CL_HTON64(((uint64_t)1)<<2))\r
+#define IB_LR_COMPMASK_TO_LID             (CL_HTON64(((uint64_t)1)<<3))\r
+\r
+/* VL Arbitration Record Masks */\r
+#define IB_VLA_COMPMASK_LID               (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_VLA_COMPMASK_OUT_PORT          (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_VLA_COMPMASK_BLOCK             (CL_HTON64(((uint64_t)1)<<2))\r
+\r
+/* SLtoVL Mapping Record Masks */\r
+#define IB_SLVL_COMPMASK_LID              (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_SLVL_COMPMASK_IN_PORT          (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_SLVL_COMPMASK_OUT_PORT         (CL_HTON64(((uint64_t)1)<<2))\r
+\r
+/* P_Key Table Record Masks */\r
+#define IB_PKEY_COMPMASK_LID              (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_PKEY_COMPMASK_BLOCK            (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_PKEY_COMPMASK_PORT             (CL_HTON64(((uint64_t)1)<<2))\r
+\r
+/* Switch Info Record Masks */\r
+#define IB_SWIR_COMPMASK_LID             (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_SWIR_COMPMASK_RESERVED1       (CL_HTON64(((uint64_t)1)<<1))\r
+\r
+/* LFT Record Masks */\r
+#define IB_LFTR_COMPMASK_LID              (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_LFTR_COMPMASK_BLOCK            (CL_HTON64(((uint64_t)1)<<1))\r
+\r
+/* MFT Record Masks */\r
+#define IB_MFTR_COMPMASK_LID             (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_MFTR_COMPMASK_POSITION        (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_MFTR_COMPMASK_RESERVED1       (CL_HTON64(((uint64_t)1)<<2))\r
+#define IB_MFTR_COMPMASK_BLOCK           (CL_HTON64(((uint64_t)1)<<3))\r
+#define IB_MFTR_COMPMASK_RESERVED2       (CL_HTON64(((uint64_t)1)<<4))\r
+\r
+/* NodeInfo Record Masks */\r
+#define IB_NR_COMPMASK_LID                (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_NR_COMPMASK_RESERVED1          (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_NR_COMPMASK_BASEVERSION        (CL_HTON64(((uint64_t)1)<<2))\r
+#define IB_NR_COMPMASK_CLASSVERSION       (CL_HTON64(((uint64_t)1)<<3))\r
+#define IB_NR_COMPMASK_NODETYPE           (CL_HTON64(((uint64_t)1)<<4))\r
+#define IB_NR_COMPMASK_NUMPORTS           (CL_HTON64(((uint64_t)1)<<5))\r
+#define IB_NR_COMPMASK_SYSIMAGEGUID       (CL_HTON64(((uint64_t)1)<<6))\r
+#define IB_NR_COMPMASK_NODEGUID           (CL_HTON64(((uint64_t)1)<<7))\r
+#define IB_NR_COMPMASK_PORTGUID           (CL_HTON64(((uint64_t)1)<<8))\r
+#define IB_NR_COMPMASK_PARTCAP            (CL_HTON64(((uint64_t)1)<<9))\r
+#define IB_NR_COMPMASK_DEVID              (CL_HTON64(((uint64_t)1)<<10))\r
+#define IB_NR_COMPMASK_REV                (CL_HTON64(((uint64_t)1)<<11))\r
+#define IB_NR_COMPMASK_PORTNUM            (CL_HTON64(((uint64_t)1)<<12))\r
+#define IB_NR_COMPMASK_VENDID             (CL_HTON64(((uint64_t)1)<<13))\r
+#define IB_NR_COMPMASK_NODEDESC           (CL_HTON64(((uint64_t)1)<<14))\r
+\r
+/* Service Record Component Masks Sec 15.2.5.14 Ver 1.1*/\r
+#define IB_SR_COMPMASK_SID                (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_SR_COMPMASK_SGID               (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_SR_COMPMASK_SPKEY              (CL_HTON64(((uint64_t)1)<<2))\r
+#define IB_SR_COMPMASK_RES1               (CL_HTON64(((uint64_t)1)<<3))\r
+#define IB_SR_COMPMASK_SLEASE             (CL_HTON64(((uint64_t)1)<<4))\r
+#define IB_SR_COMPMASK_SKEY               (CL_HTON64(((uint64_t)1)<<5))\r
+#define IB_SR_COMPMASK_SNAME              (CL_HTON64(((uint64_t)1)<<6))\r
+#define IB_SR_COMPMASK_SDATA8_0           (CL_HTON64(((uint64_t)1)<<7))\r
+#define IB_SR_COMPMASK_SDATA8_1           (CL_HTON64(((uint64_t)1)<<8))\r
+#define IB_SR_COMPMASK_SDATA8_2           (CL_HTON64(((uint64_t)1)<<9))\r
+#define IB_SR_COMPMASK_SDATA8_3           (CL_HTON64(((uint64_t)1)<<10))\r
+#define IB_SR_COMPMASK_SDATA8_4           (CL_HTON64(((uint64_t)1)<<11))\r
+#define IB_SR_COMPMASK_SDATA8_5           (CL_HTON64(((uint64_t)1)<<12))\r
+#define IB_SR_COMPMASK_SDATA8_6           (CL_HTON64(((uint64_t)1)<<13))\r
+#define IB_SR_COMPMASK_SDATA8_7           (CL_HTON64(((uint64_t)1)<<14))\r
+#define IB_SR_COMPMASK_SDATA8_8           (CL_HTON64(((uint64_t)1)<<15))\r
+#define IB_SR_COMPMASK_SDATA8_9           (CL_HTON64(((uint64_t)1)<<16))\r
+#define IB_SR_COMPMASK_SDATA8_10       (CL_HTON64(((uint64_t)1)<<17))\r
+#define IB_SR_COMPMASK_SDATA8_11       (CL_HTON64(((uint64_t)1)<<18))\r
+#define IB_SR_COMPMASK_SDATA8_12       (CL_HTON64(((uint64_t)1)<<19))\r
+#define IB_SR_COMPMASK_SDATA8_13       (CL_HTON64(((uint64_t)1)<<20))\r
+#define IB_SR_COMPMASK_SDATA8_14       (CL_HTON64(((uint64_t)1)<<21))\r
+#define IB_SR_COMPMASK_SDATA8_15       (CL_HTON64(((uint64_t)1)<<22))\r
+#define IB_SR_COMPMASK_SDATA16_0       (CL_HTON64(((uint64_t)1)<<23))\r
+#define IB_SR_COMPMASK_SDATA16_1       (CL_HTON64(((uint64_t)1)<<24))\r
+#define IB_SR_COMPMASK_SDATA16_2       (CL_HTON64(((uint64_t)1)<<25))\r
+#define IB_SR_COMPMASK_SDATA16_3       (CL_HTON64(((uint64_t)1)<<26))\r
+#define IB_SR_COMPMASK_SDATA16_4       (CL_HTON64(((uint64_t)1)<<27))\r
+#define IB_SR_COMPMASK_SDATA16_5       (CL_HTON64(((uint64_t)1)<<28))\r
+#define IB_SR_COMPMASK_SDATA16_6       (CL_HTON64(((uint64_t)1)<<29))\r
+#define IB_SR_COMPMASK_SDATA16_7       (CL_HTON64(((uint64_t)1)<<30))\r
+#define IB_SR_COMPMASK_SDATA32_0       (CL_HTON64(((uint64_t)1)<<31))\r
+#define IB_SR_COMPMASK_SDATA32_1       (CL_HTON64(((uint64_t)1)<<32))\r
+#define IB_SR_COMPMASK_SDATA32_2       (CL_HTON64(((uint64_t)1)<<33))\r
+#define IB_SR_COMPMASK_SDATA32_3       (CL_HTON64(((uint64_t)1)<<34))\r
+#define IB_SR_COMPMASK_SDATA64_0       (CL_HTON64(((uint64_t)1)<<35))\r
+#define IB_SR_COMPMASK_SDATA64_1       (CL_HTON64(((uint64_t)1)<<36))\r
+\r
+/* Port Info Record Component Masks */\r
+#define IB_PIR_COMPMASK_LID              (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_PIR_COMPMASK_PORTNUM          (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_PIR_COMPMASK_RESV1            (CL_HTON64(((uint64_t)1)<<2))\r
+#define IB_PIR_COMPMASK_MKEY             (CL_HTON64(((uint64_t)1)<<3))\r
+#define IB_PIR_COMPMASK_GIDPRE           (CL_HTON64(((uint64_t)1)<<4))\r
+#define IB_PIR_COMPMASK_BASELID          (CL_HTON64(((uint64_t)1)<<5))\r
+#define IB_PIR_COMPMASK_SMLID            (CL_HTON64(((uint64_t)1)<<6))\r
+#define IB_PIR_COMPMASK_CAPMASK          (CL_HTON64(((uint64_t)1)<<7))\r
+#define IB_PIR_COMPMASK_DIAGCODE         (CL_HTON64(((uint64_t)1)<<8))\r
+#define IB_PIR_COMPMASK_MKEYLEASEPRD     (CL_HTON64(((uint64_t)1)<<9))\r
+#define IB_PIR_COMPMASK_LOCALPORTNUM     (CL_HTON64(((uint64_t)1)<<10))\r
+#define IB_PIR_COMPMASK_LINKWIDTHENABLED (CL_HTON64(((uint64_t)1)<<11))\r
+#define IB_PIR_COMPMASK_LNKWIDTHSUPPORT  (CL_HTON64(((uint64_t)1)<<12))\r
+#define IB_PIR_COMPMASK_LNKWIDTHACTIVE   (CL_HTON64(((uint64_t)1)<<13))\r
+#define IB_PIR_COMPMASK_LNKSPEEDSUPPORT  (CL_HTON64(((uint64_t)1)<<14))\r
+#define IB_PIR_COMPMASK_PORTSTATE        (CL_HTON64(((uint64_t)1)<<15))\r
+#define IB_PIR_COMPMASK_PORTPHYSTATE     (CL_HTON64(((uint64_t)1)<<16))\r
+#define IB_PIR_COMPMASK_LINKDWNDFLTSTATE (CL_HTON64(((uint64_t)1)<<17))\r
+#define IB_PIR_COMPMASK_MKEYPROTBITS     (CL_HTON64(((uint64_t)1)<<18))\r
+#define IB_PIR_COMPMASK_RESV2            (CL_HTON64(((uint64_t)1)<<19))\r
+#define IB_PIR_COMPMASK_LMC              (CL_HTON64(((uint64_t)1)<<20))\r
+#define IB_PIR_COMPMASK_LINKSPEEDACTIVE  (CL_HTON64(((uint64_t)1)<<21))\r
+#define IB_PIR_COMPMASK_LINKSPEEDENABLE  (CL_HTON64(((uint64_t)1)<<22))\r
+#define IB_PIR_COMPMASK_NEIGHBORMTU      (CL_HTON64(((uint64_t)1)<<23))\r
+#define IB_PIR_COMPMASK_MASTERSMSL       (CL_HTON64(((uint64_t)1)<<24))\r
+#define IB_PIR_COMPMASK_VLCAP            (CL_HTON64(((uint64_t)1)<<25))\r
+#define IB_PIR_COMPMASK_INITTYPE         (CL_HTON64(((uint64_t)1)<<26))\r
+#define IB_PIR_COMPMASK_VLHIGHLIMIT      (CL_HTON64(((uint64_t)1)<<27))\r
+#define IB_PIR_COMPMASK_VLARBHIGHCAP     (CL_HTON64(((uint64_t)1)<<28))\r
+#define IB_PIR_COMPMASK_VLARBLOWCAP      (CL_HTON64(((uint64_t)1)<<29))\r
+#define IB_PIR_COMPMASK_INITTYPEREPLY    (CL_HTON64(((uint64_t)1)<<30))\r
+#define IB_PIR_COMPMASK_MTUCAP           (CL_HTON64(((uint64_t)1)<<31))\r
+#define IB_PIR_COMPMASK_VLSTALLCNT       (CL_HTON64(((uint64_t)1)<<32))\r
+#define IB_PIR_COMPMASK_HOQLIFE          (CL_HTON64(((uint64_t)1)<<33))\r
+#define IB_PIR_COMPMASK_OPVLS            (CL_HTON64(((uint64_t)1)<<34))\r
+#define IB_PIR_COMPMASK_PARENFIN         (CL_HTON64(((uint64_t)1)<<35))\r
+#define IB_PIR_COMPMASK_PARENFOUT        (CL_HTON64(((uint64_t)1)<<36))\r
+#define IB_PIR_COMPMASK_FILTERRAWIN      (CL_HTON64(((uint64_t)1)<<37))\r
+#define IB_PIR_COMPMASK_FILTERRAWOUT     (CL_HTON64(((uint64_t)1)<<38))\r
+#define IB_PIR_COMPMASK_MKEYVIO          (CL_HTON64(((uint64_t)1)<<39))\r
+#define IB_PIR_COMPMASK_PKEYVIO          (CL_HTON64(((uint64_t)1)<<40))\r
+#define IB_PIR_COMPMASK_QKEYVIO          (CL_HTON64(((uint64_t)1)<<41))\r
+#define IB_PIR_COMPMASK_GUIDCAP          (CL_HTON64(((uint64_t)1)<<42))\r
+#define IB_PIR_COMPMASK_RESV3            (CL_HTON64(((uint64_t)1)<<43))\r
+#define IB_PIR_COMPMASK_SUBNTO           (CL_HTON64(((uint64_t)1)<<44))\r
+#define IB_PIR_COMPMASK_RESV4            (CL_HTON64(((uint64_t)1)<<45))\r
+#define IB_PIR_COMPMASK_RESPTIME         (CL_HTON64(((uint64_t)1)<<46))\r
+#define IB_PIR_COMPMASK_LOCALPHYERR      (CL_HTON64(((uint64_t)1)<<47))\r
+#define IB_PIR_COMPMASK_OVERRUNERR       (CL_HTON64(((uint64_t)1)<<48))\r
+\r
+/* Multicast Member Record Component Masks */\r
+#define IB_MCR_COMPMASK_GID         (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_MCR_COMPMASK_MGID        (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_MCR_COMPMASK_PORT_GID    (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_MCR_COMPMASK_QKEY        (CL_HTON64(((uint64_t)1)<<2))\r
+#define IB_MCR_COMPMASK_MLID        (CL_HTON64(((uint64_t)1)<<3))\r
+#define IB_MCR_COMPMASK_MTU_SEL     (CL_HTON64(((uint64_t)1)<<4))\r
+#define IB_MCR_COMPMASK_MTU         (CL_HTON64(((uint64_t)1)<<5))\r
+#define IB_MCR_COMPMASK_TCLASS      (CL_HTON64(((uint64_t)1)<<6))\r
+#define IB_MCR_COMPMASK_PKEY        (CL_HTON64(((uint64_t)1)<<7))\r
+#define IB_MCR_COMPMASK_RATE_SEL    (CL_HTON64(((uint64_t)1)<<8))\r
+#define IB_MCR_COMPMASK_RATE        (CL_HTON64(((uint64_t)1)<<9))\r
+#define IB_MCR_COMPMASK_LIFE_SEL    (CL_HTON64(((uint64_t)1)<<10))\r
+#define IB_MCR_COMPMASK_LIFE        (CL_HTON64(((uint64_t)1)<<11))\r
+#define IB_MCR_COMPMASK_SL          (CL_HTON64(((uint64_t)1)<<12))\r
+#define IB_MCR_COMPMASK_FLOW        (CL_HTON64(((uint64_t)1)<<13))\r
+#define IB_MCR_COMPMASK_HOP         (CL_HTON64(((uint64_t)1)<<14))\r
+#define IB_MCR_COMPMASK_SCOPE       (CL_HTON64(((uint64_t)1)<<15))\r
+#define IB_MCR_COMPMASK_JOIN_STATE  (CL_HTON64(((uint64_t)1)<<16))\r
+#define IB_MCR_COMPMASK_PROXY       (CL_HTON64(((uint64_t)1)<<17))\r
+\r
+/* GUID Info Record Component Masks */\r
+#define IB_GIR_COMPMASK_LID            (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_GIR_COMPMASK_BLOCKNUM       (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_GIR_COMPMASK_RESV1          (CL_HTON64(((uint64_t)1)<<2))\r
+#define IB_GIR_COMPMASK_RESV2          (CL_HTON64(((uint64_t)1)<<3))\r
+#define IB_GIR_COMPMASK_GID0           (CL_HTON64(((uint64_t)1)<<4))\r
+#define IB_GIR_COMPMASK_GID1           (CL_HTON64(((uint64_t)1)<<5))\r
+#define IB_GIR_COMPMASK_GID2           (CL_HTON64(((uint64_t)1)<<6))\r
+#define IB_GIR_COMPMASK_GID3           (CL_HTON64(((uint64_t)1)<<7))\r
+#define IB_GIR_COMPMASK_GID4           (CL_HTON64(((uint64_t)1)<<8))\r
+#define IB_GIR_COMPMASK_GID5           (CL_HTON64(((uint64_t)1)<<9))\r
+#define IB_GIR_COMPMASK_GID6           (CL_HTON64(((uint64_t)1)<<10))\r
+#define IB_GIR_COMPMASK_GID7           (CL_HTON64(((uint64_t)1)<<11))\r
+\r
+/* MultiPath Record Component Masks */\r
+#define IB_MPR_COMPMASK_RAWTRAFFIC     (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_MPR_COMPMASK_RESV0          (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_MPR_COMPMASK_FLOWLABEL      (CL_HTON64(((uint64_t)1)<<2))\r
+#define IB_MPR_COMPMASK_HOPLIMIT       (CL_HTON64(((uint64_t)1)<<3))\r
+#define IB_MPR_COMPMASK_TCLASS         (CL_HTON64(((uint64_t)1)<<4))\r
+#define IB_MPR_COMPMASK_REVERSIBLE     (CL_HTON64(((uint64_t)1)<<5))\r
+#define IB_MPR_COMPMASK_NUMBPATH       (CL_HTON64(((uint64_t)1)<<6))\r
+#define IB_MPR_COMPMASK_PKEY           (CL_HTON64(((uint64_t)1)<<7))\r
+#define IB_MPR_COMPMASK_RESV1          (CL_HTON64(((uint64_t)1)<<8))\r
+#define IB_MPR_COMPMASK_SL             (CL_HTON64(((uint64_t)1)<<9))\r
+#define IB_MPR_COMPMASK_MTUSELEC       (CL_HTON64(((uint64_t)1)<<10))\r
+#define IB_MPR_COMPMASK_MTU            (CL_HTON64(((uint64_t)1)<<11))\r
+#define IB_MPR_COMPMASK_RATESELEC      (CL_HTON64(((uint64_t)1)<<12))\r
+#define IB_MPR_COMPMASK_RATE           (CL_HTON64(((uint64_t)1)<<13))\r
+#define IB_MPR_COMPMASK_PKTLIFETIMESELEC (CL_HTON64(((uint64_t)1)<<14))\r
+#define IB_MPR_COMPMASK_PKTLIFETIME    (CL_HTON64(((uint64_t)1)<<15))\r
+#define IB_MPR_COMPMASK_RESV2          (CL_HTON64(((uint64_t)1)<<16))\r
+#define IB_MPR_COMPMASK_INDEPSELEC     (CL_HTON64(((uint64_t)1)<<17))\r
+#define IB_MPR_COMPMASK_RESV3          (CL_HTON64(((uint64_t)1)<<18))\r
+#define IB_MPR_COMPMASK_SGIDCOUNT      (CL_HTON64(((uint64_t)1)<<19))\r
+#define IB_MPR_COMPMASK_DGIDCOUNT      (CL_HTON64(((uint64_t)1)<<20))\r
+#define IB_MPR_COMPMASK_RESV4          (CL_HTON64(((uint64_t)1)<<21))\r
+\r
+/* SMInfo Record Component Masks */\r
+#define IB_SMIR_COMPMASK_LID           (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_SMIR_COMPMASK_RESV0         (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_SMIR_COMPMASK_GUID          (CL_HTON64(((uint64_t)1)<<2))\r
+#define IB_SMIR_COMPMASK_SMKEY         (CL_HTON64(((uint64_t)1)<<3))\r
+#define IB_SMIR_COMPMASK_ACTCOUNT      (CL_HTON64(((uint64_t)1)<<4))\r
+#define IB_SMIR_COMPMASK_PRIORITY      (CL_HTON64(((uint64_t)1)<<5))\r
+#define IB_SMIR_COMPMASK_SMSTATE       (CL_HTON64(((uint64_t)1)<<6))\r
+\r
+/* InformInfo Record Component Masks */\r
+#define IB_IIR_COMPMASK_SUBSCRIBERGID  (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_IIR_COMPMASK_ENUM           (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_IIR_COMPMASK_RESV0          (CL_HTON64(((uint64_t)1)<<2))\r
+#define IB_IIR_COMPMASK_GID            (CL_HTON64(((uint64_t)1)<<3))\r
+#define IB_IIR_COMPMASK_LIDRANGEBEGIN  (CL_HTON64(((uint64_t)1)<<4))\r
+#define IB_IIR_COMPMASK_LIDRANGEEND    (CL_HTON64(((uint64_t)1)<<5))\r
+#define IB_IIR_COMPMASK_RESV1          (CL_HTON64(((uint64_t)1)<<6))\r
+#define IB_IIR_COMPMASK_ISGENERIC      (CL_HTON64(((uint64_t)1)<<7))\r
+#define IB_IIR_COMPMASK_SUBSCRIBE      (CL_HTON64(((uint64_t)1)<<8))\r
+#define IB_IIR_COMPMASK_TYPE           (CL_HTON64(((uint64_t)1)<<9))\r
+#define IB_IIR_COMPMASK_TRAPNUMB       (CL_HTON64(((uint64_t)1)<<10))\r
+#define IB_IIR_COMPMASK_DEVICEID       (CL_HTON64(((uint64_t)1)<<10))\r
+#define IB_IIR_COMPMASK_QPN            (CL_HTON64(((uint64_t)1)<<11))\r
+#define IB_IIR_COMPMASK_RESV2          (CL_HTON64(((uint64_t)1)<<12))\r
+#define IB_IIR_COMPMASK_RESPTIME       (CL_HTON64(((uint64_t)1)<<13))\r
+#define IB_IIR_COMPMASK_RESV3          (CL_HTON64(((uint64_t)1)<<14))\r
+#define IB_IIR_COMPMASK_PRODTYPE       (CL_HTON64(((uint64_t)1)<<15))\r
+#define IB_IIR_COMPMASK_VENDID         (CL_HTON64(((uint64_t)1)<<15))\r
+\r
+/****f* IBA Base: Types/ib_path_rec_init_local\r
+* NAME\r
+*      ib_path_rec_init_local\r
+*\r
+* DESCRIPTION\r
+*      Initializes a subnet local path record.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_path_rec_init_local(\r
+       IN      ib_path_rec_t* const    p_rec,\r
+       IN      ib_gid_t* const         p_dgid,\r
+       IN      ib_gid_t* const         p_sgid,\r
+       IN      ib_net16_t              dlid,\r
+       IN      ib_net16_t              slid,\r
+       IN      uint8_t                 num_path,\r
+       IN      ib_net16_t              pkey,\r
+       IN      uint8_t                 sl,\r
+       IN      uint8_t                 mtu_selector,\r
+       IN      uint8_t                 mtu,\r
+       IN      uint8_t                 rate_selector,\r
+       IN      uint8_t                 rate,\r
+       IN      uint8_t                 pkt_life_selector,\r
+       IN      uint8_t                 pkt_life,\r
+       IN      uint8_t                 preference )\r
+{\r
+       p_rec->dgid = *p_dgid;\r
+       p_rec->sgid = *p_sgid;\r
+       p_rec->dlid = dlid;\r
+       p_rec->slid = slid;\r
+       p_rec->num_path = num_path;\r
+       p_rec->pkey = pkey;\r
+       /* Lower 4 bits of path rec's SL are reserved. */\r
+       p_rec->qos_class_sl = cl_ntoh16( sl );\r
+       p_rec->mtu = (uint8_t)((mtu & IB_PATH_REC_BASE_MASK) |\r
+                       (uint8_t)(mtu_selector << 6));\r
+       p_rec->rate = (uint8_t)((rate & IB_PATH_REC_BASE_MASK) |\r
+                       (uint8_t)(rate_selector << 6));\r
+       p_rec->pkt_life = (uint8_t)((pkt_life & IB_PATH_REC_BASE_MASK) |\r
+                       (uint8_t)(pkt_life_selector << 6));\r
+       p_rec->preference = preference;\r
+\r
+       /* Clear global routing fields for local path records */\r
+       p_rec->hop_flow_raw = 0;\r
+       p_rec->tclass = 0;\r
+\r
+       *((uint64_t*)p_rec->service_id) = 0;\r
+       *((uint32_t*)p_rec->resv2) = 0;\r
+       *((uint16_t*)p_rec->resv2 + 2) = 0;\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_rec\r
+*              [in] Pointer to the path record object.\r
+*\r
+*      dgid\r
+*              [in] GID of destination port.\r
+*\r
+*      sgid\r
+*              [in] GID of source port.\r
+*\r
+*      dlid\r
+*              [in] LID of destination port.\r
+*\r
+*      slid\r
+*              [in] LID of source port.\r
+*\r
+*      num_path\r
+*     [in] Reversible path - 1 bit to say if path is reversible.\r
+*              num_path [6:0] In queries, maximum number of paths to return.\r
+*              In responses, undefined.\r
+*\r
+*      pkey\r
+*              [in] Partition key (P_Key) to use on this path.\r
+*\r
+*      sl\r
+*              [in] Service level to use on this path.  Lower 4-bits are valid.\r
+*\r
+*      mtu_selector\r
+*              [in] Encoded MTU selector value to use on this path\r
+*\r
+*      mtu\r
+*              [in] Encoded MTU to use on this path\r
+*\r
+*      rate_selector\r
+*              [in] Encoded rate selector value to use on this path.\r
+*\r
+*      rate\r
+*              [in] Encoded rate to use on this path.\r
+*\r
+*      pkt_life_selector\r
+*              [in] Encoded Packet selector value lifetime for this path.\r
+*\r
+*      pkt_life\r
+*              [in] Encoded Packet lifetime for this path.\r
+*\r
+*      preference\r
+*              [in] Indicates the relative merit of this path versus other path\r
+*              records returned from the SA.  Lower numbers are better.\r
+*\r
+* RETURN VALUES\r
+*      None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_gid_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_rec_num_path\r
+* NAME\r
+*      ib_path_rec_num_path\r
+*\r
+* DESCRIPTION\r
+*      Get max number of paths to return.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_path_rec_num_path(\r
+       IN      const   ib_path_rec_t* const    p_rec )\r
+{\r
+       return( p_rec->num_path &0x7F );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_rec\r
+*              [in] Pointer to the path record object.\r
+*\r
+* RETURN VALUES\r
+*      Maximum number of paths to return for each unique SGID_DGID combination.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_path_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_rec_sl\r
+* NAME\r
+*      ib_path_rec_sl\r
+*\r
+* DESCRIPTION\r
+*      Get path service level.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_path_rec_sl(\r
+       IN      const   ib_path_rec_t* const    p_rec )\r
+{\r
+       return( (uint8_t)((cl_ntoh16( p_rec->qos_class_sl )) & 0xF) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_rec\r
+*              [in] Pointer to the path record object.\r
+*\r
+* RETURN VALUES\r
+*      SL.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_path_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_rec_set_qos_class\r
+* NAME\r
+*      ib_path_rec_set_qos_class\r
+*\r
+* DESCRIPTION\r
+*      Set path QoS class.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_path_rec_set_qos_class(IN ib_path_rec_t * const p_rec,\r
+                         IN const uint16_t qos_class)\r
+{\r
+       p_rec->qos_class_sl =\r
+           (p_rec->qos_class_sl & CL_HTON16(IB_PATH_REC_SL_MASK)) |\r
+           cl_hton16(qos_class << 4);\r
+}\r
+\r
+/*\r
+* PARAMETERS\r
+*      p_rec\r
+*              [in] Pointer to the path record object.\r
+*\r
+*      qos_class\r
+*              [in] QoS class to set.\r
+*\r
+* RETURN VALUES\r
+*      None\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_path_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_rec_qos_class\r
+* NAME\r
+*      ib_path_rec_qos_class\r
+*\r
+* DESCRIPTION\r
+*      Get QoS class.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint16_t OSM_API\r
+ib_path_rec_qos_class(IN const ib_path_rec_t * const p_rec)\r
+{\r
+       return (cl_ntoh16(p_rec->qos_class_sl) >> 4);\r
+}\r
+\r
+/*\r
+* PARAMETERS\r
+*      p_rec\r
+*              [in] Pointer to the path record object.\r
+*\r
+* RETURN VALUES\r
+*      QoS class of the path record.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_path_rec_t\r
+*********/\r
+\r
+\r
+/****f* IBA Base: Types/ib_path_rec_mtu\r
+* NAME\r
+*      ib_path_rec_mtu\r
+*\r
+* DESCRIPTION\r
+*      Get encoded path MTU.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_path_rec_mtu(\r
+       IN      const   ib_path_rec_t* const    p_rec )\r
+{\r
+       return( (uint8_t)(p_rec->mtu & IB_PATH_REC_BASE_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_rec\r
+*              [in] Pointer to the path record object.\r
+*\r
+* RETURN VALUES\r
+*      Encoded path MTU.\r
+*              1: 256\r
+*              2: 512\r
+*              3: 1024\r
+*              4: 2048\r
+*              5: 4096\r
+*              others: reserved\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_path_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_rec_mtu_sel\r
+* NAME\r
+*      ib_path_rec_mtu_sel\r
+*\r
+* DESCRIPTION\r
+*      Get encoded path MTU selector.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_path_rec_mtu_sel(\r
+       IN      const   ib_path_rec_t* const    p_rec )\r
+{\r
+       return( (uint8_t)((p_rec->mtu & IB_PATH_REC_SELECTOR_MASK) >> 6) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_rec\r
+*              [in] Pointer to the path record object.\r
+*\r
+* RETURN VALUES\r
+*      Encoded path MTU selector value (for queries).\r
+*              0: greater than MTU specified\r
+*              1: less than MTU specified\r
+*              2: exactly the MTU specified\r
+*              3: largest MTU available\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_path_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_rec_rate\r
+* NAME\r
+*      ib_path_rec_rate\r
+*\r
+* DESCRIPTION\r
+*      Get encoded path rate.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_path_rec_rate(\r
+       IN      const   ib_path_rec_t* const    p_rec )\r
+{\r
+       return( (uint8_t)(p_rec->rate & IB_PATH_REC_BASE_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_rec\r
+*              [in] Pointer to the path record object.\r
+*\r
+* RETURN VALUES\r
+*      Encoded path rate.\r
+*              2: 2.5 Gb/sec.\r
+*              3: 10 Gb/sec.\r
+*              4: 30 Gb/sec.\r
+*              5: 5 Gb/sec.\r
+*              6: 20 Gb/sec.\r
+*              7: 40 Gb/sec.\r
+*              8: 60 Gb/sec.\r
+*              9: 80 Gb/sec.\r
+*              10: 120 Gb/sec.\r
+*              others: reserved\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_path_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_rec_rate_sel\r
+* NAME\r
+*      ib_path_rec_rate_sel\r
+*\r
+* DESCRIPTION\r
+*      Get encoded path rate selector.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_path_rec_rate_sel(\r
+       IN      const   ib_path_rec_t* const    p_rec )\r
+{\r
+       return( (uint8_t)((p_rec->rate & IB_PATH_REC_SELECTOR_MASK) >> 6) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_rec\r
+*              [in] Pointer to the path record object.\r
+*\r
+* RETURN VALUES\r
+*      Encoded path rate selector value (for queries).\r
+*              0: greater than rate specified\r
+*              1: less than rate specified\r
+*              2: exactly the rate specified\r
+*              3: largest rate available\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_path_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_rec_pkt_life\r
+* NAME\r
+*      ib_path_rec_pkt_life\r
+*\r
+* DESCRIPTION\r
+*      Get encoded path pkt_life.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_path_rec_pkt_life(\r
+       IN      const   ib_path_rec_t* const    p_rec )\r
+{\r
+       return( (uint8_t)(p_rec->pkt_life & IB_PATH_REC_BASE_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_rec\r
+*              [in] Pointer to the path record object.\r
+*\r
+* RETURN VALUES\r
+*      Encoded path pkt_life = 4.096 Âµsec * 2 ** PacketLifeTime.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_path_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_rec_pkt_life_sel\r
+* NAME\r
+*      ib_path_rec_pkt_life_sel\r
+*\r
+* DESCRIPTION\r
+*      Get encoded path pkt_lifetime selector.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_path_rec_pkt_life_sel(\r
+       IN      const   ib_path_rec_t* const    p_rec )\r
+{\r
+       return( (uint8_t)((p_rec->pkt_life & IB_PATH_REC_SELECTOR_MASK) >> 6 ));\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_rec\r
+*              [in] Pointer to the path record object.\r
+*\r
+* RETURN VALUES\r
+*      Encoded path pkt_lifetime selector value (for queries).\r
+*              0: greater than rate specified\r
+*              1: less than rate specified\r
+*              2: exactly the rate specified\r
+*              3: smallest packet lifetime available\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_path_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_rec_flow_lbl\r
+* NAME\r
+*      ib_path_rec_flow_lbl\r
+*\r
+* DESCRIPTION\r
+*      Get flow label.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint32_t OSM_API\r
+ib_path_rec_flow_lbl(\r
+       IN      const   ib_path_rec_t* const    p_rec )\r
+{\r
+       return( ((cl_ntoh32(p_rec->hop_flow_raw) >> 8) & 0x000FFFFF) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_rec\r
+*              [in] Pointer to the path record object.\r
+*\r
+* RETURN VALUES\r
+*      Flow label of the path record.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_path_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_rec_hop_limit\r
+* NAME\r
+*      ib_path_rec_hop_limit\r
+*\r
+* DESCRIPTION\r
+*      Get hop limit.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_path_rec_hop_limit(\r
+       IN      const   ib_path_rec_t* const    p_rec )\r
+{\r
+       return( (uint8_t)(p_rec->hop_flow_raw & 0x000000FF ) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_rec\r
+*              [in] Pointer to the path record object.\r
+*\r
+* RETURN VALUES\r
+*      Hop limit of the path record.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_path_rec_t\r
+*********/\r
+\r
+/****s* IBA Base: Constants/IB_CLASS_CAP_TRAP\r
+* NAME\r
+*      IB_CLASS_CAP_TRAP\r
+*\r
+* DESCRIPTION\r
+*      ClassPortInfo CapabilityMask bits.  This bit will be set\r
+*      if the class supports Trap() MADs (13.4.8.1).\r
+*\r
+* SEE ALSO\r
+*      ib_class_port_info_t, IB_CLASS_CAP_GETSET\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_CLASS_CAP_TRAP                                      0x0001\r
+/*********/\r
+\r
+/****s* IBA Base: Constants/IB_CLASS_CAP_GETSET\r
+* NAME\r
+*      IB_CLASS_CAP_GETSET\r
+*\r
+* DESCRIPTION\r
+*      ClassPortInfo CapabilityMask bits.  This bit will be set\r
+*      if the class supports Get(Notice) and Set(Notice) MADs (13.4.8.1).\r
+*\r
+* SEE ALSO\r
+*      ib_class_port_info_t, IB_CLASS_CAP_TRAP\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_CLASS_CAP_GETSET                                    0x0002\r
+/*********/\r
+\r
+/****s* IBA Base: Constants/IB_CLASS_RESP_TIME_MASK\r
+* NAME\r
+*      IB_CLASS_RESP_TIME_MASK\r
+*\r
+* DESCRIPTION\r
+*      Mask bits to extract the reponse time value from the\r
+*      resp_time_val field of ib_class_port_info_t.\r
+*\r
+* SEE ALSO\r
+*      ib_class_port_info_t\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_CLASS_RESP_TIME_MASK                                0x1F\r
+/*********/\r
+/****s* IBA Base: Types/ib_class_port_info_t\r
+* NAME\r
+*      ib_class_port_info_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined ClassPortInfo attribute (13.4.8.1)\r
+*      route between two end-points on a subnet.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_class_port_info\r
+{\r
+       uint8_t                                 base_ver;\r
+       uint8_t                                 class_ver;\r
+       ib_net16_t                              cap_mask;\r
+       ib_net32_t                              cap_mask2_resp_time;\r
+       ib_gid_t                                redir_gid;\r
+       ib_net32_t                              redir_tc_sl_fl;\r
+       ib_net16_t                              redir_lid;\r
+       ib_net16_t                              redir_pkey;\r
+       ib_net32_t                              redir_qp;\r
+       ib_net32_t                              redir_qkey;\r
+       ib_gid_t                                trap_gid;\r
+       ib_net32_t                              trap_tc_sl_fl;\r
+       ib_net16_t                              trap_lid;\r
+       ib_net16_t                              trap_pkey;\r
+       ib_net32_t                              trap_hop_qp;\r
+       ib_net32_t                              trap_qkey;\r
+\r
+}      PACK_SUFFIX ib_class_port_info_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+*      base_ver\r
+*              Maximum supported MAD Base Version.\r
+*\r
+*      class_ver\r
+*              Maximum supported management class version.\r
+*\r
+*      cap_mask\r
+*              Supported capabilities of this management class.\r
+*\r
+*      cap_mask2_resp_time\r
+*              Maximum expected response time and additional\r
+*              supported capabilities of this management class.\r
+*\r
+*      redr_gid\r
+*              GID to use for redirection, or zero\r
+*\r
+*      recdir_tc_sl_fl\r
+*              Traffic class, service level and flow label the requester\r
+*              should use if the service is redirected.\r
+*\r
+*      redir_lid\r
+*              LID used for redirection, or zero\r
+*\r
+*      redir_pkey\r
+*              P_Key used for redirection\r
+*\r
+*      redir_qp\r
+*              QP number used for redirection\r
+*\r
+*      redir_qkey\r
+*              Q_Key associated with the redirected QP.  This shall be the\r
+*              well known Q_Key value.\r
+*\r
+*      trap_gid\r
+*              GID value used for trap messages from this service.\r
+*\r
+*      trap_tc_sl_fl\r
+*              Traffic class, service level and flow label used for\r
+*              trap messages originated by this service.\r
+*\r
+*      trap_lid\r
+*              LID used for trap messages, or zero\r
+*\r
+*      trap_pkey\r
+*              P_Key used for trap messages\r
+*\r
+*      trap_hop_qp\r
+*              Hop limit (upper 8 bits) and QP number used for trap messages\r
+*\r
+*      trap_qkey\r
+*              Q_Key associated with the trap messages QP.\r
+*\r
+* SEE ALSO\r
+*      IB_CLASS_CAP_GETSET, IB_CLASS_CAP_TRAP\r
+*\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_class_set_resp_time_val\r
+* NAME\r
+*      ib_class_set_resp_time_val\r
+*\r
+* DESCRIPTION\r
+*      Set maximum expected response time.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_class_set_resp_time_val(IN ib_class_port_info_t * const p_cpi,\r
+                          IN const uint8_t val)\r
+{\r
+       p_cpi->cap_mask2_resp_time =\r
+           (p_cpi->cap_mask2_resp_time & CL_HTON32(~IB_CLASS_RESP_TIME_MASK)) |\r
+           cl_hton32(val & IB_CLASS_RESP_TIME_MASK);\r
+}\r
+\r
+/*\r
+* PARAMETERS\r
+*      p_cpi\r
+*              [in] Pointer to the class port info object.\r
+*\r
+*      val\r
+*              [in] Response time value to set.\r
+*\r
+* RETURN VALUES\r
+*      None\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_class_port_info_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_class_resp_time_val\r
+* NAME\r
+*      ib_class_resp_time_val\r
+*\r
+* DESCRIPTION\r
+*      Get response time value.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_class_resp_time_val(IN ib_class_port_info_t * const p_cpi)\r
+{\r
+       return (uint8_t)(cl_ntoh32(p_cpi->cap_mask2_resp_time) &\r
+                        IB_CLASS_RESP_TIME_MASK);\r
+}\r
+\r
+/*\r
+* PARAMETERS\r
+*      p_cpi\r
+*              [in] Pointer to the class port info object.\r
+*\r
+* RETURN VALUES\r
+*      Response time value.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_class_port_info_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_class_set_cap_mask2\r
+* NAME\r
+*      ib_class_set_cap_mask2\r
+*\r
+* DESCRIPTION\r
+*      Set ClassPortInfo:CapabilityMask2.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_class_set_cap_mask2(IN ib_class_port_info_t * const p_cpi,\r
+                      IN const uint32_t cap_mask2)\r
+{\r
+       p_cpi->cap_mask2_resp_time = (p_cpi->cap_mask2_resp_time &\r
+               CL_HTON32(IB_CLASS_RESP_TIME_MASK)) |\r
+               cl_hton32(cap_mask2 << 5);\r
+}\r
+\r
+/*\r
+* PARAMETERS\r
+*      p_cpi\r
+*              [in] Pointer to the class port info object.\r
+*\r
+*      cap_mask2\r
+*              [in] CapabilityMask2 value to set.\r
+*\r
+* RETURN VALUES\r
+*      None\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_class_port_info_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_class_cap_mask2\r
+* NAME\r
+*      ib_class_cap_mask2\r
+*\r
+* DESCRIPTION\r
+*      Get ClassPortInfo:CapabilityMask2.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint32_t OSM_API\r
+ib_class_cap_mask2(IN const ib_class_port_info_t * const p_cpi)\r
+{\r
+       return (cl_ntoh32(p_cpi->cap_mask2_resp_time) >> 5);\r
+}\r
+\r
+/*\r
+* PARAMETERS\r
+*      p_cpi\r
+*              [in] Pointer to the class port info object.\r
+*\r
+* RETURN VALUES\r
+*      CapabilityMask2 of the ClassPortInfo.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_class_port_info_t\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_sm_info_t\r
+* NAME\r
+*      ib_sm_info_t\r
+*\r
+* DESCRIPTION\r
+*      SMInfo structure (14.2.5.13).\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_sm_info\r
+{\r
+       ib_net64_t                      guid;\r
+       ib_net64_t                      sm_key;\r
+       ib_net32_t                      act_count;\r
+       uint8_t                         pri_state;\r
+\r
+}      PACK_SUFFIX ib_sm_info_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+*      guid\r
+*              Port GUID for this SM.\r
+*\r
+*      sm_key\r
+*              SM_Key of this SM.\r
+*\r
+*      act_count\r
+*              Activity counter used as a heartbeat.\r
+*\r
+*      pri_state\r
+*              Priority and State information\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_sminfo_get_priority\r
+* NAME\r
+*      ib_sminfo_get_priority\r
+*\r
+* DESCRIPTION\r
+*      Returns the priority value.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_sminfo_get_priority(\r
+       IN      const   ib_sm_info_t* const             p_smi )\r
+{\r
+       return( (uint8_t)((p_smi->pri_state & 0xF0)>>4) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_smi\r
+*              [in] Pointer to the SMInfo Attribute.\r
+*\r
+* RETURN VALUES\r
+*      Returns the priority value.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_sminfo_get_state\r
+* NAME\r
+*      ib_sminfo_get_state\r
+*\r
+* DESCRIPTION\r
+*      Returns the state value.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_sminfo_get_state(\r
+       IN      const   ib_sm_info_t* const             p_smi )\r
+{\r
+       return( (uint8_t)(p_smi->pri_state & 0x0F) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_smi\r
+*              [in] Pointer to the SMInfo Attribute.\r
+*\r
+* RETURN VALUES\r
+*      Returns the state value.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_mad_t\r
+* NAME\r
+*      ib_mad_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined MAD header (13.4.3)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_mad\r
+{\r
+       uint8_t                                 base_ver;\r
+       uint8_t                                 mgmt_class;\r
+       uint8_t                                 class_ver;\r
+       uint8_t                                 method;\r
+       ib_net16_t                              status;\r
+       ib_net16_t                              class_spec;\r
+       ib_net64_t                              trans_id;\r
+       ib_net16_t                              attr_id;\r
+       ib_net16_t                              resv;\r
+       ib_net32_t                              attr_mod;\r
+}      PACK_SUFFIX ib_mad_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+*      base_ver\r
+*              MAD base format.\r
+*\r
+*      mgmt_class\r
+*              Class of operation.\r
+*\r
+*      class_ver\r
+*              Version of MAD class-specific format.\r
+*\r
+*      method\r
+*              Method to perform, including 'R' bit.\r
+*\r
+*      status\r
+*              Status of operation.\r
+*\r
+*      class_spec\r
+*              Reserved for subnet management.\r
+*\r
+*      trans_id\r
+*              Transaction ID.\r
+*\r
+*      attr_id\r
+*              Attribute ID.\r
+*\r
+*      resv\r
+*              Reserved field.\r
+*\r
+*      attr_mod\r
+*              Attribute modifier.\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+\r
+/****s* IBA Base: Types/ib_rmpp_mad_t\r
+* NAME\r
+*      ib_rmpp_mad_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined MAD RMPP header (13.6.2.1)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_rmpp_mad\r
+{\r
+       ib_mad_t                                common_hdr;\r
+\r
+       uint8_t                                 rmpp_version;\r
+       uint8_t                                 rmpp_type;\r
+       uint8_t                                 rmpp_flags;\r
+       uint8_t                                 rmpp_status;\r
+\r
+       ib_net32_t                              seg_num;\r
+       ib_net32_t                              paylen_newwin;\r
+\r
+}      PACK_SUFFIX ib_rmpp_mad_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* SEE ALSO\r
+*      ib_mad_t\r
+*********/\r
+\r
+\r
+/****f* IBA Base: Types/ib_mad_init_new\r
+* NAME\r
+*      ib_mad_init_new\r
+*\r
+* DESCRIPTION\r
+*      Initializes a MAD common header.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_mad_init_new(\r
+       IN              ib_mad_t* const         p_mad,\r
+       IN              const   uint8_t         mgmt_class,\r
+       IN              const   uint8_t         class_ver,\r
+       IN              const   uint8_t         method,\r
+       IN              const   ib_net64_t      trans_id,\r
+       IN              const   ib_net16_t      attr_id,\r
+       IN              const   ib_net32_t      attr_mod )\r
+{\r
+       CL_ASSERT( p_mad );\r
+       p_mad->base_ver = 1;\r
+       p_mad->mgmt_class = mgmt_class;\r
+       p_mad->class_ver = class_ver;\r
+       p_mad->method = method;\r
+       p_mad->status = 0;\r
+       p_mad->class_spec = 0;\r
+       p_mad->trans_id = trans_id;\r
+       p_mad->attr_id = attr_id;\r
+       p_mad->resv = 0;\r
+       p_mad->attr_mod = attr_mod;\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_mad\r
+*              [in] Pointer to the MAD common header.\r
+*\r
+*      mgmt_class\r
+*              [in] Class of operation.\r
+*\r
+*      class_ver\r
+*              [in] Version of MAD class-specific format.\r
+*\r
+*      method\r
+*              [in] Method to perform, including 'R' bit.\r
+*\r
+*      trans_Id\r
+*              [in] Transaction ID.\r
+*\r
+*      attr_id\r
+*              [in] Attribute ID.\r
+*\r
+*      attr_mod\r
+*              [in] Attribute modifier.\r
+*\r
+* RETURN VALUES\r
+*      None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_mad_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_mad_init_response\r
+* NAME\r
+*      ib_mad_init_response\r
+*\r
+* DESCRIPTION\r
+*      Initializes a MAD common header as a response.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_mad_init_response(\r
+       IN      const   ib_mad_t* const         p_req_mad,\r
+       IN              ib_mad_t* const         p_mad,\r
+       IN      const   ib_net16_t              status )\r
+{\r
+       CL_ASSERT( p_req_mad );\r
+       CL_ASSERT( p_mad );\r
+       *p_mad = *p_req_mad;\r
+       p_mad->status = status;\r
+       if( p_mad->method == IB_MAD_METHOD_SET )\r
+               p_mad->method = IB_MAD_METHOD_GET;\r
+       p_mad->method |= IB_MAD_METHOD_RESP_MASK;\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_req_mad\r
+*              [in] Pointer to the MAD common header in the original request MAD.\r
+*\r
+*      p_mad\r
+*              [in] Pointer to the MAD common header to initialize.\r
+*\r
+*      status\r
+*              [in] MAD Status value to return;\r
+*\r
+* RETURN VALUES\r
+*      None.\r
+*\r
+* NOTES\r
+*      p_req_mad and p_mad may point to the same MAD.\r
+*\r
+* SEE ALSO\r
+*      ib_mad_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_mad_is_response\r
+* NAME\r
+*      ib_mad_is_response\r
+*\r
+* DESCRIPTION\r
+*      Returns TRUE if the MAD is a response ('R' bit set),\r
+*      FALSE otherwise.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t        OSM_API\r
+ib_mad_is_response(\r
+       IN      const   ib_mad_t* const         p_mad )\r
+{\r
+       CL_ASSERT( p_mad );\r
+       return( (p_mad->method & IB_MAD_METHOD_RESP_MASK) ==\r
+                       IB_MAD_METHOD_RESP_MASK );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_mad\r
+*              [in] Pointer to the MAD.\r
+*\r
+* RETURN VALUES\r
+*      Returns TRUE if the MAD is a response ('R' bit set),\r
+*      FALSE otherwise.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_mad_t\r
+*********/\r
+\r
+#define IB_RMPP_TYPE_DATA              1\r
+#define IB_RMPP_TYPE_ACK               2\r
+#define IB_RMPP_TYPE_STOP              3\r
+#define IB_RMPP_TYPE_ABORT             4\r
+\r
+#define IB_RMPP_NO_RESP_TIME           0x1F\r
+#define IB_RMPP_FLAG_ACTIVE            0x01\r
+#define IB_RMPP_FLAG_FIRST             0x02\r
+#define IB_RMPP_FLAG_LAST              0x04\r
+\r
+#define IB_RMPP_STATUS_SUCCESS         0\r
+#define IB_RMPP_STATUS_RESX            1               /* resources exhausted */\r
+#define IB_RMPP_STATUS_T2L             118             /* time too long */\r
+#define IB_RMPP_STATUS_BAD_LEN         119             /* incon. last and payload len */\r
+#define IB_RMPP_STATUS_BAD_SEG         120             /* incon. first and segment no */\r
+#define IB_RMPP_STATUS_BADT            121             /* bad rmpp type */\r
+#define IB_RMPP_STATUS_W2S             122             /* newwindowlast too small */\r
+#define IB_RMPP_STATUS_S2B             123             /* segment no too big */\r
+#define IB_RMPP_STATUS_BAD_STATUS      124             /* illegal status */\r
+#define IB_RMPP_STATUS_UNV             125             /* unsupported version */\r
+#define IB_RMPP_STATUS_TMR             126             /* too many retries */\r
+#define IB_RMPP_STATUS_UNSPEC          127             /* unspecified */\r
+\r
+/****f* IBA Base: Types/ib_rmpp_is_flag_set\r
+* NAME\r
+*      ib_rmpp_is_flag_set\r
+*\r
+* DESCRIPTION\r
+*      Returns TRUE if the MAD has the given RMPP flag set.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t        OSM_API\r
+ib_rmpp_is_flag_set(\r
+       IN      const   ib_rmpp_mad_t* const    p_rmpp_mad,\r
+       IN      const   uint8_t                 flag )\r
+{\r
+       CL_ASSERT( p_rmpp_mad );\r
+       return( (p_rmpp_mad->rmpp_flags & flag) == flag );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      ib_rmpp_mad_t\r
+*              [in] Pointer to a MAD with an RMPP header.\r
+*\r
+*      flag\r
+*              [in] The RMPP flag being examined.\r
+*\r
+* RETURN VALUES\r
+*      Returns TRUE if the MAD has the given RMPP flag set.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_mad_t, ib_rmpp_mad_t\r
+*********/\r
+\r
+static inline void     OSM_API\r
+ib_rmpp_set_resp_time(\r
+       IN              ib_rmpp_mad_t* const    p_rmpp_mad,\r
+       IN      const   uint8_t                 resp_time )\r
+{\r
+       CL_ASSERT( p_rmpp_mad );\r
+       p_rmpp_mad->rmpp_flags |= (resp_time << 3);\r
+}\r
+\r
+\r
+static inline uint8_t  OSM_API\r
+ib_rmpp_get_resp_time(\r
+       IN      const   ib_rmpp_mad_t* const    p_rmpp_mad )\r
+{\r
+       CL_ASSERT( p_rmpp_mad );\r
+       return( (uint8_t)(p_rmpp_mad->rmpp_flags >> 3) );\r
+}\r
+\r
+/****d* IBA Base: Constants/IB_SMP_DIRECTION\r
+* NAME\r
+*      IB_SMP_DIRECTION\r
+*\r
+* DESCRIPTION\r
+*      The Direction bit for directed route SMPs.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMP_DIRECTION_HO            0x8000\r
+#define IB_SMP_DIRECTION               (CL_HTON16(IB_SMP_DIRECTION_HO))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMP_STATUS_MASK\r
+* NAME\r
+*      IB_SMP_STATUS_MASK\r
+*\r
+* DESCRIPTION\r
+*      Mask value for extracting status from a directed route SMP.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMP_STATUS_MASK_HO          0x7FFF\r
+#define IB_SMP_STATUS_MASK             (CL_HTON16(IB_SMP_STATUS_MASK_HO))\r
+/**********/\r
+\r
+/****s* IBA Base: Types/ib_smp_t\r
+* NAME\r
+*      ib_smp_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined SMP. (14.2.1.2)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define IB_SMP_DATA_SIZE 64\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_smp\r
+{\r
+       uint8_t                                 base_ver;\r
+       uint8_t                                 mgmt_class;\r
+       uint8_t                                 class_ver;\r
+       uint8_t                                 method;\r
+       ib_net16_t                              status;\r
+       uint8_t                                 hop_ptr;\r
+       uint8_t                                 hop_count;\r
+       ib_net64_t                              trans_id;\r
+       ib_net16_t                              attr_id;\r
+       ib_net16_t                              resv;\r
+       ib_net32_t                              attr_mod;\r
+       ib_net64_t                              m_key;\r
+       ib_net16_t                              dr_slid;\r
+       ib_net16_t                              dr_dlid;\r
+       uint32_t                                resv1[7];\r
+       uint8_t                                 data[IB_SMP_DATA_SIZE];\r
+       uint8_t                                 initial_path[IB_SUBNET_PATH_HOPS_MAX];\r
+       uint8_t                                 return_path[IB_SUBNET_PATH_HOPS_MAX];\r
+\r
+}      PACK_SUFFIX ib_smp_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+*      base_ver\r
+*              MAD base format.\r
+*\r
+*      mgmt_class\r
+*              Class of operation.\r
+*\r
+*      class_ver\r
+*              Version of MAD class-specific format.\r
+*\r
+*      method\r
+*              Method to perform, including 'R' bit.\r
+*\r
+*      status\r
+*              Status of operation.\r
+*\r
+*      hop_ptr\r
+*              Hop pointer for directed route MADs.\r
+*\r
+*      hop_count\r
+*              Hop count for directed route MADs.\r
+*\r
+*      trans_Id\r
+*              Transaction ID.\r
+*\r
+*      attr_id\r
+*              Attribute ID.\r
+*\r
+*      resv\r
+*              Reserved field.\r
+*\r
+*      attr_mod\r
+*              Attribute modifier.\r
+*\r
+*      m_key\r
+*              Management key value.\r
+*\r
+*      dr_slid\r
+*              Directed route source LID.\r
+*\r
+*      dr_dlid\r
+*              Directed route destination LID.\r
+*\r
+*      resv0\r
+*              Reserved for 64 byte alignment.\r
+*\r
+*      data\r
+*              MAD data payload.\r
+*\r
+*      initial_path\r
+*              Outbound port list.\r
+*\r
+*      return_path\r
+*              Inbound port list.\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_smp_get_status\r
+* NAME\r
+*      ib_smp_get_status\r
+*\r
+* DESCRIPTION\r
+*      Returns the SMP status value in network order.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net16_t       OSM_API\r
+ib_smp_get_status(\r
+       IN      const   ib_smp_t* const         p_smp )\r
+{\r
+       return( (ib_net16_t)(p_smp->status & IB_SMP_STATUS_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_smp\r
+*              [in] Pointer to the SMP packet.\r
+*\r
+* RETURN VALUES\r
+*      Returns the SMP status value in network order.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_smp_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_smp_is_response\r
+* NAME\r
+*      ib_smp_is_response\r
+*\r
+* DESCRIPTION\r
+*      Returns TRUE if the SMP is a response MAD, FALSE otherwise.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t        OSM_API\r
+ib_smp_is_response(\r
+       IN      const   ib_smp_t* const         p_smp )\r
+{\r
+       return( ib_mad_is_response( (const ib_mad_t*)p_smp ) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_smp\r
+*              [in] Pointer to the SMP packet.\r
+*\r
+* RETURN VALUES\r
+*      Returns TRUE if the SMP is a response MAD, FALSE otherwise.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_smp_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_smp_is_d\r
+* NAME\r
+*      ib_smp_is_d\r
+*\r
+* DESCRIPTION\r
+*      Returns TRUE if the SMP 'D' (direction) bit is set.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t        OSM_API\r
+ib_smp_is_d(\r
+       IN      const   ib_smp_t* const         p_smp )\r
+{\r
+       return( (p_smp->status & IB_SMP_DIRECTION) == IB_SMP_DIRECTION );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_smp\r
+*              [in] Pointer to the SMP packet.\r
+*\r
+* RETURN VALUES\r
+*      Returns TRUE if the SMP 'D' (direction) bit is set.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_smp_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_smp_init_new\r
+* NAME\r
+*      ib_smp_init_new\r
+*\r
+* DESCRIPTION\r
+*      Initializes a MAD common header.\r
+*\r
+* TODO\r
+*      This is too big for inlining, but leave it here for now\r
+*      since there is not yet another convient spot.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_smp_init_new(\r
+       IN              ib_smp_t* const         p_smp,\r
+       IN      const   uint8_t                 method,\r
+       IN      const   ib_net64_t              trans_id,\r
+       IN      const   ib_net16_t              attr_id,\r
+       IN      const   ib_net32_t              attr_mod,\r
+       IN      const   uint8_t                 hop_count,\r
+       IN      const   ib_net64_t              m_key,\r
+       IN      const   uint8_t*                path_out,\r
+       IN      const   ib_net16_t              dr_slid,\r
+       IN      const   ib_net16_t              dr_dlid )\r
+{\r
+       CL_ASSERT( p_smp );\r
+       CL_ASSERT( hop_count < IB_SUBNET_PATH_HOPS_MAX );\r
+       p_smp->base_ver = 1;\r
+       p_smp->mgmt_class = IB_MCLASS_SUBN_DIR;\r
+       p_smp->class_ver = 1;\r
+       p_smp->method = method;\r
+       p_smp->status = 0;\r
+       p_smp->hop_ptr = 0;\r
+       p_smp->hop_count = hop_count;\r
+       p_smp->trans_id = trans_id;\r
+       p_smp->attr_id = attr_id;\r
+       p_smp->resv = 0;\r
+       p_smp->attr_mod = attr_mod;\r
+       p_smp->m_key = m_key;\r
+       p_smp->dr_slid = dr_slid;\r
+       p_smp->dr_dlid = dr_dlid;\r
+\r
+       memset( p_smp->resv1, 0,\r
+               sizeof(p_smp->resv1) +\r
+               sizeof(p_smp->data) +\r
+               sizeof(p_smp->initial_path) +\r
+               sizeof(p_smp->return_path) );\r
+\r
+       /* copy the path */\r
+       memcpy( &p_smp->initial_path, path_out,\r
+               sizeof( p_smp->initial_path ) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_smp\r
+*              [in] Pointer to the SMP packet.\r
+*\r
+*      method\r
+*              [in] Method to perform, including 'R' bit.\r
+*\r
+*      trans_Id\r
+*              [in] Transaction ID.\r
+*\r
+*      attr_id\r
+*              [in] Attribute ID.\r
+*\r
+*      attr_mod\r
+*              [in] Attribute modifier.\r
+*\r
+*      hop_count\r
+*              [in] Number of hops in the path.\r
+*\r
+*      m_key\r
+*              [in] Management key for this SMP.\r
+*\r
+*      path_out\r
+*              [in] Port array for outbound path.\r
+*\r
+*\r
+* RETURN VALUES\r
+*      None.\r
+*\r
+* NOTES\r
+*      Payload area is initialized to zero.\r
+*\r
+*\r
+* SEE ALSO\r
+*      ib_mad_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_smp_get_payload_ptr\r
+* NAME\r
+*      ib_smp_get_payload_ptr\r
+*\r
+* DESCRIPTION\r
+*      Gets a pointer to the SMP payload area.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void*    OSM_API\r
+ib_smp_get_payload_ptr(\r
+       IN      const   ib_smp_t* const         p_smp )\r
+{\r
+       return( (void*)p_smp->data );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_smp\r
+*              [in] Pointer to the SMP packet.\r
+*\r
+* RETURN VALUES\r
+*      Pointer to SMP payload area.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_mad_t\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_node_info_t\r
+* NAME\r
+*      ib_node_info_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined NodeInfo. (14.2.5.3)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_node_info\r
+{\r
+       uint8_t                         base_version;\r
+       uint8_t                         class_version;\r
+       uint8_t                         node_type;\r
+       uint8_t                         num_ports;\r
+       ib_net64_t                      sys_guid;\r
+       ib_net64_t                      node_guid;\r
+       ib_net64_t                      port_guid;\r
+       ib_net16_t                      partition_cap;\r
+       ib_net16_t                      device_id;\r
+       ib_net32_t                      revision;\r
+       ib_net32_t                      port_num_vendor_id;\r
+\r
+}      PACK_SUFFIX ib_node_info_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+/****s* IBA Base: Types/ib_sa_mad_t\r
+* NAME\r
+*      ib_sa_mad_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined SA MAD format. (15.2.1)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define IB_SA_DATA_SIZE 200\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_sa_mad\r
+{\r
+       uint8_t                                 base_ver;\r
+       uint8_t                                 mgmt_class;\r
+       uint8_t                                 class_ver;\r
+       uint8_t                                 method;\r
+       ib_net16_t                              status;\r
+       ib_net16_t                              resv;\r
+       ib_net64_t                              trans_id;\r
+       ib_net16_t                              attr_id;\r
+       ib_net16_t                              resv1;\r
+       ib_net32_t                              attr_mod;\r
+\r
+       uint8_t                                 rmpp_version;\r
+       uint8_t                                 rmpp_type;\r
+       uint8_t                                 rmpp_flags;\r
+       uint8_t                                 rmpp_status;\r
+\r
+       ib_net32_t                              seg_num;\r
+       ib_net32_t                              paylen_newwin;\r
+\r
+       ib_net64_t                              sm_key;\r
+\r
+       ib_net16_t                              attr_offset;\r
+       ib_net16_t                              resv3;\r
+\r
+       ib_net64_t                              comp_mask;\r
+\r
+       uint8_t                                 data[IB_SA_DATA_SIZE];\r
+}      PACK_SUFFIX ib_sa_mad_t;\r
+#include <complib/cl_packoff.h>\r
+/**********/\r
+#define IB_SA_MAD_HDR_SIZE (sizeof(ib_sa_mad_t) - IB_SA_DATA_SIZE)\r
+\r
+static inline uint32_t OSM_API\r
+ib_get_attr_size(\r
+       IN      const   ib_net16_t                              attr_offset )\r
+{\r
+       return( ((uint32_t)cl_ntoh16( attr_offset )) << 3 );\r
+}\r
+\r
+static inline ib_net16_t       OSM_API\r
+ib_get_attr_offset(\r
+       IN      const   uint32_t                                attr_size )\r
+{\r
+       return( cl_hton16( (uint16_t)(attr_size >> 3) ) );\r
+}\r
+\r
+/****f* IBA Base: Types/ib_sa_mad_get_payload_ptr\r
+* NAME\r
+*      ib_sa_mad_get_payload_ptr\r
+*\r
+* DESCRIPTION\r
+*      Gets a pointer to the SA MAD's payload area.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void*    OSM_API\r
+ib_sa_mad_get_payload_ptr(\r
+       IN      const   ib_sa_mad_t* const              p_sa_mad )\r
+{\r
+       return( (void*)p_sa_mad->data );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_smp\r
+*              [in] Pointer to the SA MAD packet.\r
+*\r
+* RETURN VALUES\r
+*      Pointer to SA MAD payload area.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_mad_t\r
+*********/\r
+\r
+#define IB_NODE_INFO_PORT_NUM_MASK             (CL_NTOH32(0xFF000000))\r
+#define IB_NODE_INFO_VEND_ID_MASK              (CL_NTOH32(0x00FFFFFF))\r
+#if CPU_LE\r
+       #define IB_NODE_INFO_PORT_NUM_SHIFT 0\r
+#else\r
+       #define IB_NODE_INFO_PORT_NUM_SHIFT 24\r
+#endif\r
+\r
+/****f* IBA Base: Types/ib_node_info_get_local_port_num\r
+* NAME\r
+*      ib_node_info_get_local_port_num\r
+*\r
+* DESCRIPTION\r
+*      Gets a the local port number from the NodeInfo attribute.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_node_info_get_local_port_num(\r
+       IN      const   ib_node_info_t* const   p_ni )\r
+{\r
+       return( (uint8_t)(( p_ni->port_num_vendor_id &\r
+                       IB_NODE_INFO_PORT_NUM_MASK )\r
+                       >> IB_NODE_INFO_PORT_NUM_SHIFT ));\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_ni\r
+*              [in] Pointer to a NodeInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      Local port number that returned the attribute.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_node_info_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_node_info_get_vendor_id\r
+* NAME\r
+*      ib_node_info_get_vendor_id\r
+*\r
+* DESCRIPTION\r
+*      Gets the VendorID from the NodeInfo attribute.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net32_t       OSM_API\r
+ib_node_info_get_vendor_id(\r
+       IN      const   ib_node_info_t* const   p_ni )\r
+{\r
+       return( (ib_net32_t)( p_ni->port_num_vendor_id &\r
+                       IB_NODE_INFO_VEND_ID_MASK ) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_ni\r
+*              [in] Pointer to a NodeInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      VendorID that returned the attribute.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_node_info_t\r
+*********/\r
+\r
+#define IB_NODE_DESCRIPTION_SIZE 64\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_node_desc\r
+{\r
+       // Node String is an array of UTF-8 character that\r
+       // describes the node in text format\r
+       // Note that this string is NOT NULL TERMINATED!\r
+       uint8_t         description[IB_NODE_DESCRIPTION_SIZE];\r
+\r
+}      PACK_SUFFIX ib_node_desc_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_node_record_t\r
+{\r
+       ib_net16_t              lid;\r
+       ib_net16_t              resv;\r
+       ib_node_info_t  node_info;\r
+       ib_node_desc_t  node_desc;\r
+       uint8_t                 pad[4];\r
+\r
+}      PACK_SUFFIX ib_node_record_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+/****s* IBA Base: Types/ib_port_info_t\r
+* NAME\r
+*      ib_port_info_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined PortInfo. (14.2.5.6)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_port_info\r
+{\r
+       ib_net64_t                      m_key;\r
+       ib_net64_t                      subnet_prefix;\r
+       ib_net16_t                      base_lid;\r
+       ib_net16_t                      master_sm_base_lid;\r
+       ib_net32_t                      capability_mask;\r
+       ib_net16_t                      diag_code;\r
+       ib_net16_t                      m_key_lease_period;\r
+       uint8_t                         local_port_num;\r
+       uint8_t                         link_width_enabled;\r
+       uint8_t                         link_width_supported;\r
+       uint8_t                         link_width_active;\r
+       uint8_t                         state_info1; /* LinkSpeedSupported and PortState */\r
+       uint8_t                         state_info2; /* PortPhysState and LinkDownDefaultState */\r
+       uint8_t                         mkey_lmc;\r
+       uint8_t                         link_speed;      /* LinkSpeedEnabled and LinkSpeedActive */\r
+       uint8_t                         mtu_smsl;\r
+       uint8_t                         vl_cap;          /* VLCap and InitType */\r
+       uint8_t                         vl_high_limit;\r
+       uint8_t                         vl_arb_high_cap;\r
+       uint8_t                         vl_arb_low_cap;\r
+       uint8_t                         mtu_cap;\r
+       uint8_t                         vl_stall_life;\r
+       uint8_t                         vl_enforce;\r
+       ib_net16_t                      m_key_violations;\r
+       ib_net16_t                      p_key_violations;\r
+       ib_net16_t                      q_key_violations;\r
+       uint8_t                         guid_cap;\r
+       uint8_t                         subnet_timeout; /* cli_rereg(1b), resrv(\r
+2b), timeout(5b) */\r
+       uint8_t                         resp_time_value;\r
+       uint8_t                         error_threshold;\r
+\r
+}      PACK_SUFFIX ib_port_info_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+#define IB_PORT_STATE_MASK                     0x0F\r
+#define IB_PORT_LMC_MASK                       0x07\r
+#define IB_PORT_LMC_MAX                                0x07\r
+#define IB_PORT_MPB_MASK                       0xC0\r
+#define IB_PORT_MPB_SHIFT                      6\r
+#define IB_PORT_LINK_SPEED_SHIFT               4\r
+#define IB_PORT_LINK_SPEED_SUPPORTED_MASK      0xF0\r
+#define IB_PORT_LINK_SPEED_ACTIVE_MASK         0xF0\r
+#define IB_PORT_LINK_SPEED_ENABLED_MASK                0x0F\r
+#define IB_PORT_PHYS_STATE_MASK                        0xF0\r
+#define IB_PORT_PHYS_STATE_SHIFT               4\r
+#define IB_PORT_LNKDWNDFTSTATE_MASK            0x0F\r
+\r
+#define IB_PORT_CAP_RESV0         (CL_NTOH32(0x00000001))\r
+#define IB_PORT_CAP_IS_SM         (CL_NTOH32(0x00000002))\r
+#define IB_PORT_CAP_HAS_NOTICE    (CL_NTOH32(0x00000004))\r
+#define IB_PORT_CAP_HAS_TRAP      (CL_NTOH32(0x00000008))\r
+#define IB_PORT_CAP_HAS_IPD       (CL_NTOH32(0x00000010))\r
+#define IB_PORT_CAP_HAS_AUTO_MIG  (CL_NTOH32(0x00000020))\r
+#define IB_PORT_CAP_HAS_SL_MAP    (CL_NTOH32(0x00000040))\r
+#define IB_PORT_CAP_HAS_NV_MKEY   (CL_NTOH32(0x00000080))\r
+#define IB_PORT_CAP_HAS_NV_PKEY   (CL_NTOH32(0x00000100))\r
+#define IB_PORT_CAP_HAS_LED_INFO  (CL_NTOH32(0x00000200))\r
+#define IB_PORT_CAP_SM_DISAB      (CL_NTOH32(0x00000400))\r
+#define IB_PORT_CAP_HAS_SYS_IMG_GUID  (CL_NTOH32(0x00000800))\r
+#define IB_PORT_CAP_HAS_PKEY_SW_EXT_PORT_TRAP (CL_NTOH32(0x00001000))\r
+#define IB_PORT_CAP_RESV13        (CL_NTOH32(0x00002000))\r
+#define IB_PORT_CAP_RESV14        (CL_NTOH32(0x00004000))\r
+#define IB_PORT_CAP_RESV15        (CL_NTOH32(0x00008000))\r
+#define IB_PORT_CAP_HAS_COM_MGT   (CL_NTOH32(0x00010000))\r
+#define IB_PORT_CAP_HAS_SNMP      (CL_NTOH32(0x00020000))\r
+#define IB_PORT_CAP_REINIT        (CL_NTOH32(0x00040000))\r
+#define IB_PORT_CAP_HAS_DEV_MGT   (CL_NTOH32(0x00080000))\r
+#define IB_PORT_CAP_HAS_VEND_CLS  (CL_NTOH32(0x00100000))\r
+#define IB_PORT_CAP_HAS_DR_NTC    (CL_NTOH32(0x00200000))\r
+#define IB_PORT_CAP_HAS_CAP_NTC   (CL_NTOH32(0x00400000))\r
+#define IB_PORT_CAP_HAS_BM        (CL_NTOH32(0x00800000))\r
+#define IB_PORT_CAP_HAS_LINK_RT_LATENCY (CL_NTOH32(0x01000000))\r
+#define IB_PORT_CAP_HAS_CLIENT_REREG (CL_NTOH32(0x02000000))\r
+#define IB_PORT_CAP_RESV26        (CL_NTOH32(0x04000000))\r
+#define IB_PORT_CAP_RESV27        (CL_NTOH32(0x08000000))\r
+#define IB_PORT_CAP_RESV28        (CL_NTOH32(0x10000000))\r
+#define IB_PORT_CAP_RESV29        (CL_NTOH32(0x20000000))\r
+#define IB_PORT_CAP_RESV30        (CL_NTOH32(0x40000000))\r
+#define IB_PORT_CAP_RESV31        (CL_NTOH32(0x80000000))\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_port_state\r
+* NAME\r
+*      ib_port_info_get_port_state\r
+*\r
+* DESCRIPTION\r
+*      Returns the port state.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_port_info_get_port_state(\r
+       IN      const   ib_port_info_t* const   p_pi )\r
+{\r
+       return( (uint8_t)(p_pi->state_info1 & IB_PORT_STATE_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      Port state.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_port_state\r
+* NAME\r
+*      ib_port_info_set_port_state\r
+*\r
+* DESCRIPTION\r
+*      Sets the port state.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_port_info_set_port_state(\r
+       IN              ib_port_info_t* const   p_pi,\r
+       IN      const   uint8_t                 port_state )\r
+{\r
+       p_pi->state_info1 = (uint8_t)((p_pi->state_info1 & 0xF0) | port_state );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+*      port_state\r
+*              [in] Port state value to set.\r
+*\r
+* RETURN VALUES\r
+*      None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_vl_cap\r
+* NAME\r
+*      ib_port_info_get_vl_cap\r
+*\r
+* DESCRIPTION\r
+*      Gets the VL Capability of a port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_port_info_get_vl_cap(\r
+       IN const ib_port_info_t* const p_pi)\r
+{\r
+       return((p_pi->vl_cap >> 4) & 0x0F);\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      VL_CAP field\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_init_type\r
+* NAME\r
+*      ib_port_info_get_init_type\r
+*\r
+* DESCRIPTION\r
+*      Gets the init type of a port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_port_info_get_init_type(\r
+       IN const ib_port_info_t* const p_pi)\r
+{\r
+       return (uint8_t) (p_pi->vl_cap & 0x0F);\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      InitType field\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_op_vls\r
+* NAME\r
+*      ib_port_info_get_op_vls\r
+*\r
+* DESCRIPTION\r
+*      Gets the operational VLs on a port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_port_info_get_op_vls(\r
+       IN const ib_port_info_t* const p_pi)\r
+{\r
+       return((p_pi->vl_enforce >> 4) & 0x0F);\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      OP_VLS field\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_op_vls\r
+* NAME\r
+*      ib_port_info_set_op_vls\r
+*\r
+* DESCRIPTION\r
+*      Sets the operational VLs on a port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_port_info_set_op_vls(\r
+       IN              ib_port_info_t* const   p_pi,\r
+       IN      const   uint8_t                 op_vls )\r
+{\r
+       p_pi->vl_enforce = (uint8_t)((p_pi->vl_enforce & 0x0F) | (op_vls << 4) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+*      op_vls\r
+*              [in] Encoded operation VLs value.\r
+*\r
+* RETURN VALUES\r
+*      None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_state_no_change\r
+* NAME\r
+*      ib_port_info_set_state_no_change\r
+*\r
+* DESCRIPTION\r
+*      Sets the port state fields to the value for "no change".\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_port_info_set_state_no_change(\r
+       IN              ib_port_info_t* const   p_pi )\r
+{\r
+       ib_port_info_set_port_state( p_pi, IB_LINK_NO_CHANGE );\r
+       p_pi->state_info2 = 0;\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_link_speed_sup\r
+* NAME\r
+*      ib_port_info_get_link_speed_sup\r
+*\r
+* DESCRIPTION\r
+*      Returns the encoded value for the link speed supported.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_port_info_get_link_speed_sup(\r
+       IN      const   ib_port_info_t* const   p_pi )\r
+{\r
+       return( (uint8_t)((p_pi->state_info1 &\r
+                       IB_PORT_LINK_SPEED_SUPPORTED_MASK) >>\r
+                       IB_PORT_LINK_SPEED_SHIFT) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      Returns the encoded value for the link speed supported.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_link_speed_sup\r
+* NAME\r
+*      ib_port_info_set_link_speed_sup\r
+*\r
+* DESCRIPTION\r
+*      Given an integer of the supported link speed supported.\r
+*      Set the appropriate bits in state_info1\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_port_info_set_link_speed_sup(\r
+       IN      uint8_t const           speed,\r
+       IN      ib_port_info_t*         p_pi )\r
+{\r
+       p_pi->state_info1 =\r
+               ( ~IB_PORT_LINK_SPEED_SUPPORTED_MASK & p_pi->state_info1 ) |\r
+               ( IB_PORT_LINK_SPEED_SUPPORTED_MASK &\r
+                       (speed << IB_PORT_LINK_SPEED_SHIFT) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      speed\r
+*              [in] Supported Speeds Code.\r
+*\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      This function does not return a value.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_port_phys_state\r
+* NAME\r
+*      ib_port_info_get_port_phys_state\r
+*\r
+* DESCRIPTION\r
+*      Returns the encoded value for the port physical state.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_port_info_get_port_phys_state(\r
+       IN      const   ib_port_info_t* const   p_pi )\r
+{\r
+       return( (uint8_t)((p_pi->state_info2 &\r
+                      IB_PORT_PHYS_STATE_MASK) >>\r
+                     IB_PORT_PHYS_STATE_SHIFT) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      Returns the encoded value for the port physical state.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_port_phys_state\r
+* NAME\r
+*      ib_port_info_set_port_phys_state\r
+*\r
+* DESCRIPTION\r
+*      Given an integer of the port physical state,\r
+*      Set the appropriate bits in state_info2\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_port_info_set_port_phys_state(\r
+       IN      uint8_t const           phys_state,\r
+       IN      ib_port_info_t*         p_pi )\r
+{\r
+       p_pi->state_info2 =\r
+               ( ~IB_PORT_PHYS_STATE_MASK & p_pi->state_info2 ) |\r
+               ( IB_PORT_PHYS_STATE_MASK &\r
+        (phys_state << IB_PORT_PHYS_STATE_SHIFT) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      phys_state\r
+*              [in] port physical state.\r
+*\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      This function does not return a value.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_link_down_def_state\r
+* NAME\r
+*      ib_port_info_get_link_down_def_state\r
+*\r
+* DESCRIPTION\r
+*      Returns the link down default state.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_port_info_get_link_down_def_state(\r
+       IN      const   ib_port_info_t* const   p_pi )\r
+{\r
+       return( (uint8_t)(p_pi->state_info2 & IB_PORT_LNKDWNDFTSTATE_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      link down default state of the port.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_link_down_def_state\r
+* NAME\r
+*      ib_port_info_set_link_down_def_state\r
+*\r
+* DESCRIPTION\r
+*      Sets the link down default state of the port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_port_info_set_link_down_def_state(\r
+       IN              ib_port_info_t* const   p_pi,\r
+       IN      const   uint8_t                 link_dwn_state )\r
+{\r
+       p_pi->state_info2 = (uint8_t)((p_pi->state_info2 & 0xF0) | link_dwn_state );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+*      link_dwn_state\r
+*              [in] Link down default state of the port.\r
+*\r
+* RETURN VALUES\r
+*      None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_link_speed_active\r
+* NAME\r
+*      ib_port_info_get_link_speed_active\r
+*\r
+* DESCRIPTION\r
+*      Returns the Link Speed Active value assigned to this port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_port_info_get_link_speed_active(\r
+       IN      const   ib_port_info_t* const   p_pi )\r
+{\r
+  return( (uint8_t)((p_pi->link_speed &\r
+                     IB_PORT_LINK_SPEED_ACTIVE_MASK) >>\r
+                    IB_PORT_LINK_SPEED_SHIFT) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      Returns the link speed active value assigned to this port.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+#define IB_LINK_WIDTH_ACTIVE_1X                        1\r
+#define IB_LINK_WIDTH_ACTIVE_4X                        2\r
+#define IB_LINK_WIDTH_ACTIVE_12X               8\r
+#define IB_LINK_SPEED_ACTIVE_2_5               1\r
+#define IB_LINK_SPEED_ACTIVE_5                 2\r
+#define IB_LINK_SPEED_ACTIVE_10                        4\r
+\r
+/* following v1 ver1.2 p901 */\r
+#define IB_PATH_RECORD_RATE_2_5_GBS            2\r
+#define IB_PATH_RECORD_RATE_10_GBS             3\r
+#define IB_PATH_RECORD_RATE_30_GBS             4\r
+#define IB_PATH_RECORD_RATE_5_GBS              5\r
+#define IB_PATH_RECORD_RATE_20_GBS             6\r
+#define IB_PATH_RECORD_RATE_40_GBS             7\r
+#define IB_PATH_RECORD_RATE_60_GBS             8\r
+#define IB_PATH_RECORD_RATE_80_GBS             9\r
+#define IB_PATH_RECORD_RATE_120_GBS            10\r
+\r
+#define IB_MIN_RATE    IB_PATH_RECORD_RATE_2_5_GBS\r
+#define IB_MAX_RATE    IB_PATH_RECORD_RATE_120_GBS \r
+\r
+/****f* IBA Base: Types/ib_port_info_compute_rate\r
+* NAME\r
+*      ib_port_info_compute_rate\r
+*\r
+* DESCRIPTION\r
+*      Returns the encoded value for the path rate.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_port_info_compute_rate(\r
+       IN      const   ib_port_info_t* const   p_pi )\r
+{\r
+  uint8_t rate = 0;\r
+\r
+  switch (ib_port_info_get_link_speed_active(p_pi))\r
+  {\r
+  case IB_LINK_SPEED_ACTIVE_2_5:\r
+    switch (p_pi->link_width_active)\r
+    {\r
+    case IB_LINK_WIDTH_ACTIVE_1X:\r
+      rate = IB_PATH_RECORD_RATE_2_5_GBS;\r
+      break;\r
+      \r
+    case IB_LINK_WIDTH_ACTIVE_4X:\r
+      rate = IB_PATH_RECORD_RATE_10_GBS;\r
+      break;\r
+\r
+    case IB_LINK_WIDTH_ACTIVE_12X:\r
+      rate = IB_PATH_RECORD_RATE_30_GBS;\r
+      break;\r
+\r
+    default:\r
+      rate = IB_PATH_RECORD_RATE_2_5_GBS;\r
+      break;\r
+    }\r
+    break;\r
+  case IB_LINK_SPEED_ACTIVE_5:\r
+    switch (p_pi->link_width_active)\r
+    {\r
+    case IB_LINK_WIDTH_ACTIVE_1X:\r
+      rate = IB_PATH_RECORD_RATE_5_GBS;\r
+      break;\r
+\r
+    case IB_LINK_WIDTH_ACTIVE_4X:\r
+      rate = IB_PATH_RECORD_RATE_20_GBS;\r
+      break;\r
+\r
+    case IB_LINK_WIDTH_ACTIVE_12X:\r
+      rate = IB_PATH_RECORD_RATE_60_GBS;\r
+      break;\r
+\r
+    default:\r
+      rate = IB_PATH_RECORD_RATE_5_GBS;\r
+      break;\r
+    }\r
+    break;\r
+  case IB_LINK_SPEED_ACTIVE_10:\r
+    switch (p_pi->link_width_active)\r
+    {\r
+    case IB_LINK_WIDTH_ACTIVE_1X:\r
+      rate = IB_PATH_RECORD_RATE_10_GBS;\r
+      break;\r
+\r
+    case IB_LINK_WIDTH_ACTIVE_4X:\r
+      rate = IB_PATH_RECORD_RATE_40_GBS;\r
+      break;\r
+\r
+    case IB_LINK_WIDTH_ACTIVE_12X:\r
+      rate =IB_PATH_RECORD_RATE_120_GBS;\r
+      break;\r
+\r
+    default:\r
+      rate = IB_PATH_RECORD_RATE_10_GBS;\r
+      break;\r
+    }\r
+    break;\r
+  default:\r
+    rate = IB_PATH_RECORD_RATE_2_5_GBS;\r
+    break;\r
+  }\r
+\r
+  return rate;\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      Returns the encoded value for the link speed supported.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_get_ipd\r
+* NAME\r
+*      ib_path_get_ipd\r
+*\r
+* DESCRIPTION\r
+*      Returns the encoded value for the inter packet delay.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_path_get_ipd(\r
+       IN              uint8_t         local_link_width_supported,\r
+       IN              uint8_t         path_rec_rate )\r
+{\r
+       uint8_t ipd = 0;\r
+\r
+       switch(local_link_width_supported)\r
+       {\r
+               /* link_width_supported = 1: 1x */\r
+               case 1:\r
+                       break;\r
+\r
+               /* link_width_supported = 3: 1x or 4x */\r
+               case 3:\r
+                       switch(path_rec_rate & 0x3F)\r
+                       {\r
+                               case IB_PATH_RECORD_RATE_2_5_GBS:\r
+                                       ipd = 3;\r
+                                       break;\r
+                               default:\r
+                                       break;\r
+                       }\r
+                       break;\r
+\r
+               /* link_width_supported = 11: 1x or 4x or 12x */\r
+               case 11:\r
+                       switch(path_rec_rate & 0x3F)\r
+                       {\r
+                               case IB_PATH_RECORD_RATE_2_5_GBS:\r
+                                       ipd = 11;\r
+                                       break;\r
+                               case IB_PATH_RECORD_RATE_10_GBS:\r
+                                       ipd = 2;\r
+                                       break;\r
+                               default:\r
+                                       break;\r
+                       }\r
+                       break;\r
+\r
+               default:\r
+                       break;\r
+       }\r
+\r
+       return ipd;\r
+}\r
+/*\r
+* PARAMETERS\r
+*      local_link_width_supported\r
+*              [in] link with supported for this port\r
+*\r
+*      path_rec_rate\r
+*              [in] rate field of the path record\r
+*\r
+* RETURN VALUES\r
+*      Returns the ipd\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_mtu_cap\r
+* NAME\r
+*      ib_port_info_get_mtu_cap\r
+*\r
+* DESCRIPTION\r
+*      Returns the encoded value for the maximum MTU supported by this port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_port_info_get_mtu_cap(\r
+       IN      const   ib_port_info_t* const   p_pi )\r
+{\r
+       return( (uint8_t)(p_pi->mtu_cap & 0x0F) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      Returns the LMC value assigned to this port.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_neighbor_mtu\r
+* NAME\r
+*      ib_port_info_get_neighbor_mtu\r
+*\r
+* DESCRIPTION\r
+*      Returns the encoded value for the neighbor MTU at this port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_port_info_get_neighbor_mtu(\r
+       IN const ib_port_info_t* const p_pi )\r
+{\r
+       return( (uint8_t)((p_pi->mtu_smsl & 0xF0) >> 4) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      Returns the encoded value for the neighbor MTU at this port.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_neighbor_mtu\r
+* NAME\r
+*      ib_port_info_set_neighbor_mtu\r
+*\r
+* DESCRIPTION\r
+*      Sets the Neighbor MTU value in the PortInfo attribute.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_port_info_set_neighbor_mtu(\r
+       IN              ib_port_info_t* const   p_pi,\r
+       IN      const   uint8_t                 mtu )\r
+{\r
+       CL_ASSERT( mtu <= 5 );\r
+       CL_ASSERT( mtu != 0 );\r
+       p_pi->mtu_smsl = (uint8_t)((p_pi->mtu_smsl & 0x0F) | (mtu << 4));\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+*      mtu\r
+*              [in] Encoded MTU value to set\r
+*\r
+* RETURN VALUES\r
+*      None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_master_smsl\r
+* NAME\r
+*      ib_port_info_get_master_smsl\r
+*\r
+* DESCRIPTION\r
+*      Returns the encoded value for the Master SMSL at this port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_port_info_get_master_smsl(\r
+       IN const ib_port_info_t* const p_pi )\r
+{\r
+  return (uint8_t) (p_pi->mtu_smsl & 0x0F); \r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      Returns the encoded value for the Master SMSL at this port.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_master_smsl\r
+* NAME\r
+*      ib_port_info_set_master_smsl\r
+*\r
+* DESCRIPTION\r
+*      Sets the Master SMSL value in the PortInfo attribute.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_port_info_set_master_smsl(\r
+       IN              ib_port_info_t* const   p_pi,\r
+       IN      const   uint8_t                 smsl )\r
+{\r
+       p_pi->mtu_smsl = (uint8_t)((p_pi->mtu_smsl & 0xF0) | smsl );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+*      mtu\r
+*              [in] Encoded Master SMSL value to set\r
+*\r
+* RETURN VALUES\r
+*      None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_timeout\r
+* NAME\r
+*      ib_port_info_set_timeout\r
+*\r
+* DESCRIPTION\r
+*      Sets the encoded subnet timeout value in the PortInfo attribute.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_port_info_set_timeout(\r
+       IN              ib_port_info_t* const   p_pi,\r
+       IN      const   uint8_t                 timeout )\r
+{\r
+       CL_ASSERT( timeout <= 0x1F );\r
+       p_pi->subnet_timeout =\r
+     (uint8_t)(\r
+       (p_pi->subnet_timeout & 0x80) | (timeout & 0x1F));\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+*      timeout\r
+*              [in] Encoded timeout value to set\r
+*\r
+* RETURN VALUES\r
+*      None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_client_rereg\r
+* NAME\r
+*      ib_port_info_set_client_rereg\r
+*\r
+* DESCRIPTION\r
+*      Sets the encoded client reregistration bit value in the PortInfo attribute.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_port_info_set_client_rereg(\r
+       IN              ib_port_info_t* const   p_pi,\r
+       IN      const   uint8_t                 client_rereg )\r
+{\r
+       CL_ASSERT( client_rereg <= 0x1 );\r
+       p_pi->subnet_timeout =\r
+     (uint8_t)(\r
+       (p_pi->subnet_timeout & 0x1F) | ((client_rereg << 7) & 0x80));\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+*      client_rereg\r
+*              [in] Client reregistration value to set (either 1 or 0).\r
+*\r
+* RETURN VALUES\r
+*      None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_timeout\r
+* NAME\r
+*      ib_port_info_get_timeout\r
+*\r
+* DESCRIPTION\r
+*      Gets the encoded subnet timeout value in the PortInfo attribute.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_port_info_get_timeout(\r
+  IN                   ib_port_info_t const*   p_pi )\r
+{\r
+  return(p_pi->subnet_timeout & 0x1F );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      The encoded timeout value\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_client_rereg\r
+* NAME\r
+*      ib_port_info_get_client_rereg\r
+*\r
+* DESCRIPTION\r
+*      Gets the encoded client reregistration bit value in the PortInfo attribute.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_port_info_get_client_rereg(\r
+  IN                   ib_port_info_t const* p_pi )\r
+{\r
+  return ( (p_pi->subnet_timeout & 0x80 ) >> 7);\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      Client reregistration value (either 1 or 0).\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_hoq_lifetime\r
+* NAME\r
+*      ib_port_info_set_hoq_lifetime\r
+*\r
+* DESCRIPTION\r
+*      Sets the Head of Queue Lifetime for which a packet can live in the head \r
+*  of VL queue\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_port_info_set_hoq_lifetime(\r
+  IN           ib_port_info_t* const   p_pi,\r
+  IN   const   uint8_t                 hoq_life )\r
+{\r
+  p_pi->vl_stall_life = (uint8_t)((hoq_life & 0x1f) |\r
+                                                                                        (p_pi->vl_stall_life & 0xe0));\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+*      hoq_life\r
+*              [in] Encoded lifetime value to set\r
+*\r
+* RETURN VALUES\r
+*      None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_hoq_lifetime\r
+* NAME\r
+*      ib_port_info_get_hoq_lifetime\r
+*\r
+* DESCRIPTION\r
+*      Gets the Head of Queue Lifetime for which a packet can live in the head \r
+*  of VL queue\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_port_info_get_hoq_lifetime(\r
+  IN   const   ib_port_info_t* const   p_pi )\r
+{\r
+  return( (uint8_t)(p_pi->vl_stall_life & 0x1f) );\r
+}\r
+\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*     Encoded lifetime value\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_vl_stall_count\r
+* NAME\r
+*      ib_port_info_set_vl_stall_count\r
+*\r
+* DESCRIPTION\r
+*      Sets the VL Stall Count which define the number of contiguous \r
+*  HLL (hoq) drops that will put the VL into stalled mode.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_port_info_set_vl_stall_count(\r
+  IN           ib_port_info_t* const   p_pi,\r
+  IN   const   uint8_t                 vl_stall_count )\r
+{\r
+  p_pi->vl_stall_life = (uint8_t)((p_pi->vl_stall_life & 0x1f) |\r
+                                                                                        ((vl_stall_count << 5) & 0xe0));\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+*      vl_stall_count \r
+*              [in] value to set\r
+*\r
+* RETURN VALUES\r
+*      None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_vl_stall_count\r
+* NAME\r
+*      ib_port_info_get_vl_stall_count\r
+*\r
+* DESCRIPTION\r
+*      Gets the VL Stall Count which define the number of contiguous \r
+*  HLL (hoq) drops that will put the VL into stalled mode\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_port_info_get_vl_stall_count(\r
+  IN   const ib_port_info_t* const     p_pi )\r
+{\r
+  return( (uint8_t)(p_pi->vl_stall_life & 0xe0) >> 5);\r
+}\r
+\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*     vl stall count\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_lmc\r
+* NAME\r
+*      ib_port_info_get_lmc\r
+*\r
+* DESCRIPTION\r
+*      Returns the LMC value assigned to this port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_port_info_get_lmc(\r
+       IN      const   ib_port_info_t* const   p_pi )\r
+{\r
+       return( (uint8_t)(p_pi->mkey_lmc & IB_PORT_LMC_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      Returns the LMC value assigned to this port.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_lmc\r
+* NAME\r
+*      ib_port_info_set_lmc\r
+*\r
+* DESCRIPTION\r
+*      Sets the LMC value in the PortInfo attribute.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_port_info_set_lmc(\r
+       IN              ib_port_info_t* const   p_pi,\r
+       IN      const   uint8_t                 lmc )\r
+{\r
+       CL_ASSERT( lmc <= IB_PORT_LMC_MAX );\r
+       p_pi->mkey_lmc = (uint8_t)((p_pi->mkey_lmc & 0xF8) | lmc);\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+*      lmc\r
+*              [in] LMC value to set, must be less than 7.\r
+*\r
+* RETURN VALUES\r
+*      None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_link_speed_enabled\r
+* NAME\r
+*      ib_port_info_get_link_speed_enabled\r
+*\r
+* DESCRIPTION\r
+*      Returns the link speed enabled value assigned to this port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_port_info_get_link_speed_enabled(\r
+       IN      const   ib_port_info_t* const   p_pi )\r
+{\r
+       return( (uint8_t)(p_pi->link_speed & IB_PORT_LINK_SPEED_ENABLED_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      Port state.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_link_speed_enabled\r
+* NAME\r
+*      ib_port_info_set_link_speed_enabled\r
+*\r
+* DESCRIPTION\r
+*      Sets the link speed enabled value in the PortInfo attribute.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_port_info_set_link_speed_enabled(\r
+       IN              ib_port_info_t* const   p_pi,\r
+       IN      const   uint8_t                 link_speed_enabled )\r
+{\r
+       p_pi->link_speed = (uint8_t)((p_pi->link_speed & 0xF0) | link_speed_enabled );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+*      link_speed_enabled\r
+*              [in] link speed enabled value to set.\r
+*\r
+* RETURN VALUES\r
+*      None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_mpb\r
+* NAME\r
+*      ib_port_info_get_mpb\r
+*\r
+* DESCRIPTION\r
+*      Returns the M_Key protect bits assigned to this port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_port_info_get_mpb(\r
+       IN      const   ib_port_info_t* const   p_pi )\r
+{\r
+       return( (uint8_t)((p_pi->mkey_lmc & IB_PORT_MPB_MASK) >>\r
+                       IB_PORT_MPB_SHIFT) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_ni\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      Returns the M_Key protect bits assigned to this port.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_mpb\r
+* NAME\r
+*      ib_port_info_set_mpb\r
+*\r
+* DESCRIPTION\r
+*      Set the M_Key protect bits of this port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_port_info_set_mpb(\r
+       IN              ib_port_info_t*         p_pi,\r
+       IN              uint8_t                 mpb )\r
+{\r
+       p_pi->mkey_lmc =\r
+               (~IB_PORT_MPB_MASK & p_pi->mkey_lmc) |\r
+               ( IB_PORT_MPB_MASK & (mpb << IB_PORT_MPB_SHIFT) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      mpb\r
+*              [in] M_Key protect bits\r
+*      p_ni\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_local_phy_err_thd\r
+* NAME\r
+*      ib_port_info_get_local_phy_err_thd\r
+*\r
+* DESCRIPTION\r
+*      Returns the Phy Link Threshold\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_port_info_get_local_phy_err_thd(\r
+       IN      const   ib_port_info_t* const   p_pi )\r
+{\r
+  return (uint8_t)( (p_pi->error_threshold & 0xF0) >> 4);\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      Returns the Phy Link error threshold assigned to this port.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_overrun_err_thd\r
+* NAME\r
+*      ib_port_info_get_local_overrun_err_thd\r
+*\r
+* DESCRIPTION\r
+*      Returns the Credits Overrun Errors Threshold\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_port_info_get_overrun_err_thd(\r
+       IN      const   ib_port_info_t* const   p_pi )\r
+{\r
+  return (uint8_t)(p_pi->error_threshold & 0x0F);\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      Returns the Credits Overrun errors threshold assigned to this port.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_phy_and_overrun_err_thd\r
+* NAME\r
+*      ib_port_info_set_phy_and_overrun_err_thd\r
+*\r
+* DESCRIPTION\r
+*      Sets the Phy Link and Credits Overrun Errors Threshold\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_port_info_set_phy_and_overrun_err_thd(\r
+  IN           ib_port_info_t* const   p_pi,\r
+  IN           uint8_t                 phy_threshold,\r
+  IN           uint8_t                 overrun_threshold )\r
+{\r
+  p_pi->error_threshold = \r
+        (uint8_t)( ((phy_threshold & 0x0F) << 4) | (overrun_threshold & 0x0F) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_pi\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+*      phy_threshold\r
+*              [in] Physical Link Errors Threshold above which Trap 129 is generated \r
+*\r
+*  overrun_threshold\r
+*     [in] Credits overrun Errors Threshold above which Trap 129 is generated \r
+*\r
+* RETURN VALUES\r
+*      None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+typedef uint8_t                ib_svc_name_t[64];\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_service_record\r
+{\r
+       ib_net64_t              service_id;\r
+       ib_gid_t                service_gid;\r
+       ib_net16_t              service_pkey;\r
+       ib_net16_t              resv;\r
+       ib_net32_t              service_lease;\r
+       uint8_t                 service_key[16];\r
+       ib_svc_name_t           service_name;\r
+       uint8_t                 service_data8[16];\r
+       ib_net16_t              service_data16[8];\r
+       ib_net32_t              service_data32[4];\r
+       ib_net64_t              service_data64[2];\r
+\r
+}      PACK_SUFFIX ib_service_record_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_portinfo_record\r
+{\r
+       ib_net16_t              lid;\r
+       uint8_t                 port_num;\r
+       uint8_t                 resv;\r
+       ib_port_info_t          port_info;\r
+       uint8_t                 pad[6];\r
+\r
+}      PACK_SUFFIX ib_portinfo_record_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_link_record\r
+{\r
+       ib_net16_t              from_lid;\r
+       uint8_t                 from_port_num;\r
+       uint8_t                 to_port_num;\r
+       ib_net16_t              to_lid;\r
+       uint8_t                 pad[2];\r
+\r
+}      PACK_SUFFIX ib_link_record_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_sminfo_record\r
+{\r
+       ib_net16_t              lid;\r
+       uint16_t                resv0;\r
+       ib_sm_info_t            sm_info;\r
+       uint8_t                 pad[7];\r
+\r
+}      PACK_SUFFIX ib_sminfo_record_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+/****s* IBA Base: Types/ib_lft_record_t\r
+* NAME\r
+*      ib_lft_record_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined LinearForwardingTableRecord (15.2.5.6)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_lft_record\r
+{\r
+       ib_net16_t              lid;\r
+       ib_net16_t              block_num;\r
+       uint32_t                resv0;\r
+       uint8_t                 lft[64];\r
+}      PACK_SUFFIX ib_lft_record_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+/****s* IBA Base: Types/ib_mft_record_t\r
+* NAME\r
+*      ib_mft_record_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined MulticastForwardingTableRecord (15.2.5.8)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_mft_record\r
+{\r
+       ib_net16_t              lid;\r
+       ib_net16_t              position_block_num;\r
+       uint32_t                resv0;\r
+       ib_net16_t              mft[IB_MCAST_BLOCK_SIZE];\r
+}      PACK_SUFFIX ib_mft_record_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+/****s* IBA Base: Types/ib_switch_info_t\r
+* NAME\r
+*      ib_switch_info_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined SwitchInfo. (14.2.5.4)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_switch_info\r
+{\r
+       ib_net16_t                      lin_cap;\r
+       ib_net16_t                      rand_cap;\r
+       ib_net16_t                      mcast_cap;\r
+       ib_net16_t                      lin_top;\r
+       uint8_t                         def_port;\r
+       uint8_t                         def_mcast_pri_port;\r
+       uint8_t                         def_mcast_not_port;\r
+       uint8_t                         life_state;\r
+       ib_net16_t                      lids_per_port;\r
+       ib_net16_t                      enforce_cap;\r
+       uint8_t                         flags;\r
+\r
+}      PACK_SUFFIX ib_switch_info_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_switch_info_record\r
+{\r
+       ib_net16_t                      lid;\r
+       uint16_t                        resv0;\r
+       ib_switch_info_t                switch_info;\r
+       uint8_t                         pad[3];\r
+\r
+}      PACK_SUFFIX ib_switch_info_record_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+#define IB_SWITCH_PSC 0x04\r
+\r
+/****f* IBA Base: Types/ib_switch_info_get_state_change\r
+* NAME\r
+*      ib_switch_info_get_state_change\r
+*\r
+* DESCRIPTION\r
+*      Returns the value of the state change flag.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t        OSM_API\r
+ib_switch_info_get_state_change(\r
+       IN      const   ib_switch_info_t* const p_si )\r
+{\r
+       return( (p_si->life_state & IB_SWITCH_PSC) == IB_SWITCH_PSC );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_si\r
+*              [in] Pointer to a SwitchInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      Returns the value of the state change flag.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_switch_info_clear_state_change\r
+* NAME\r
+*      ib_switch_info_clear_state_change\r
+*\r
+* DESCRIPTION\r
+*      Clears the switch's state change bit.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_switch_info_clear_state_change(\r
+       IN              ib_switch_info_t* const p_si )\r
+{\r
+       p_si->life_state = (uint8_t)(p_si->life_state & 0xFB);\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_ni\r
+*              [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      Returns the LMC value assigned to this port.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_switch_info_is_enhanced_port0\r
+* NAME\r
+*      ib_switch_info_is_enhanced_port0\r
+*\r
+* DESCRIPTION\r
+*      Returns TRUE if the enhancedPort0 bit is on (meaning the switch\r
+*  port zero supports enhanced functions).\r
+*  Returns FALSE otherwise.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t        OSM_API\r
+ib_switch_info_is_enhanced_port0(\r
+       IN      const   ib_switch_info_t* const p_si )\r
+{\r
+       return( (p_si->flags & 0x08) == 0x08 );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_si\r
+*              [in] Pointer to a SwitchInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*      Returns TRUE if the switch supports enhanced port 0. FALSE otherwise.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_guid_info_t\r
+* NAME\r
+*      ib_guid_info_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined GuidInfo. (14.2.5.5)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define        GUID_TABLE_MAX_ENTRIES          8\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_guid_info\r
+{\r
+       ib_net64_t                      guid[GUID_TABLE_MAX_ENTRIES];\r
+\r
+}      PACK_SUFFIX ib_guid_info_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_guidinfo_record\r
+{\r
+       ib_net16_t              lid;\r
+       uint8_t                 block_num;\r
+       uint8_t                 resv;\r
+       uint32_t                reserved;\r
+       ib_guid_info_t          guid_info;\r
+}      PACK_SUFFIX ib_guidinfo_record_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+#define IB_MULTIPATH_MAX_GIDS 11       /* Support max that can fit into first MAD (for now) */\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_multipath_rec_t\r
+{\r
+       ib_net32_t              hop_flow_raw;\r
+       uint8_t                 tclass;\r
+       uint8_t                 num_path;\r
+       ib_net16_t              pkey;\r
+       uint8_t                 resv0;\r
+       uint8_t                 sl;\r
+       uint8_t                 mtu;\r
+       uint8_t                 rate;\r
+       uint8_t                 pkt_life;\r
+       uint8_t                 resv1;\r
+       uint8_t                 independence;   /* formerly resv2 */\r
+       uint8_t                 sgid_count;\r
+       uint8_t                 dgid_count;\r
+       uint8_t                 resv3[7];\r
+       ib_gid_t                gids[IB_MULTIPATH_MAX_GIDS];\r
+}      PACK_SUFFIX ib_multipath_rec_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+*       hop_flow_raw\r
+*               Global routing parameters: hop count, flow label and raw bit.\r
+*\r
+*       tclass\r
+*               Another global routing parameter.\r
+*\r
+*       num_path\r
+*     Reversible path - 1 bit to say if path is reversible.\r
+*               num_path [6:0] In queries, maximum number of paths to return.\r
+*               In responses, undefined.\r
+*\r
+*       pkey\r
+*               Partition key (P_Key) to use on this path.\r
+*\r
+*       sl\r
+*               Service level to use on this path.\r
+*\r
+*       mtu\r
+*               MTU and MTU selector fields to use on this path\r
+*       rate\r
+*               Rate and rate selector fields to use on this path.\r
+*\r
+*       pkt_life\r
+*               Packet lifetime\r
+*\r
+*       preference\r
+*               Indicates the relative merit of this path versus other path\r
+*               records returned from the SA.  Lower numbers are better.\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_multipath_rec_num_path\r
+* NAME\r
+*       ib_multipath_rec_num_path\r
+*\r
+* DESCRIPTION\r
+*       Get max number of paths to return.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_multipath_rec_num_path(\r
+       IN      const   ib_multipath_rec_t* const       p_rec )\r
+{\r
+        return( p_rec->num_path &0x7F );\r
+}\r
+/*\r
+* PARAMETERS\r
+*       p_rec\r
+*               [in] Pointer to the multipath record object.\r
+*\r
+* RETURN VALUES\r
+*       Maximum number of paths to return for each unique SGID_DGID combination.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*       ib_multipath_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_multipath_rec_sl\r
+* NAME\r
+*       ib_multipath_rec_sl\r
+*\r
+* DESCRIPTION\r
+*       Get multipath service level.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_multipath_rec_sl(\r
+       IN      const   ib_multipath_rec_t* const       p_rec )\r
+{\r
+        return( (uint8_t)((cl_ntoh16( p_rec->sl )) & 0xF) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*       p_rec\r
+*               [in] Pointer to the multipath record object.\r
+*\r
+* RETURN VALUES\r
+*      SL.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*       ib_multipath_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_multipath_rec_mtu\r
+* NAME\r
+*       ib_multipath_rec_mtu\r
+*\r
+* DESCRIPTION\r
+*       Get encoded path MTU.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_multipath_rec_mtu(\r
+       IN      const   ib_multipath_rec_t* const       p_rec )\r
+{\r
+        return( (uint8_t)(p_rec->mtu & IB_MULTIPATH_REC_BASE_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*       p_rec\r
+*               [in] Pointer to the multipath record object.\r
+*\r
+* RETURN VALUES\r
+*       Encoded path MTU.\r
+*               1: 256\r
+*               2: 512\r
+*               3: 1024\r
+*               4: 2048\r
+*               5: 4096\r
+*               others: reserved\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*       ib_multipath_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_multipath_rec_mtu_sel\r
+* NAME\r
+*       ib_multipath_rec_mtu_sel\r
+*\r
+* DESCRIPTION\r
+*       Get encoded multipath MTU selector.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_multipath_rec_mtu_sel(\r
+       IN      const   ib_multipath_rec_t* const       p_rec )\r
+{\r
+        return( (uint8_t)((p_rec->mtu & IB_MULTIPATH_REC_SELECTOR_MASK) >> 6) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*       p_rec\r
+*               [in] Pointer to the multipath record object.\r
+*\r
+* RETURN VALUES\r
+*       Encoded path MTU selector value (for queries).\r
+*               0: greater than MTU specified\r
+*               1: less than MTU specified\r
+*               2: exactly the MTU specified\r
+*               3: largest MTU available\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*       ib_multipath_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_multipath_rec_rate\r
+* NAME\r
+*       ib_multipath_rec_rate\r
+*\r
+* DESCRIPTION\r
+*       Get encoded multipath rate.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_multipath_rec_rate(\r
+       IN      const   ib_multipath_rec_t* const       p_rec )\r
+{\r
+        return( (uint8_t)(p_rec->rate & IB_MULTIPATH_REC_BASE_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*       p_rec\r
+*               [in] Pointer to the multipath record object.\r
+*\r
+* RETURN VALUES\r
+*       Encoded multipath rate.\r
+*               2: 2.5 Gb/sec.\r
+*               3: 10 Gb/sec.\r
+*               4: 30 Gb/sec.\r
+*               others: reserved\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*       ib_multipath_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_multipath_rec_rate_sel\r
+* NAME\r
+*       ib_multipath_rec_rate_sel\r
+*\r
+* DESCRIPTION\r
+*       Get encoded multipath rate selector.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_multipath_rec_rate_sel(\r
+       IN      const   ib_multipath_rec_t* const       p_rec )\r
+{\r
+        return( (uint8_t)((p_rec->rate & IB_MULTIPATH_REC_SELECTOR_MASK) >> 6) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*       p_rec\r
+*               [in] Pointer to the multipath record object.\r
+*\r
+* RETURN VALUES\r
+*       Encoded path rate selector value (for queries).\r
+*               0: greater than rate specified\r
+*               1: less than rate specified\r
+*               2: exactly the rate specified\r
+*               3: largest rate available\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*       ib_multipath_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_multipath_rec_pkt_life\r
+* NAME\r
+*       ib_multipath_rec_pkt_life\r
+*\r
+* DESCRIPTION\r
+*       Get encoded multipath pkt_life.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_multipath_rec_pkt_life(\r
+       IN      const   ib_multipath_rec_t* const       p_rec )\r
+{\r
+        return( (uint8_t)(p_rec->pkt_life & IB_MULTIPATH_REC_BASE_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*       p_rec\r
+*               [in] Pointer to the multipath record object.\r
+*\r
+* RETURN VALUES\r
+*       Encoded multipath pkt_life = 4.096 Âµsec * 2 ** PacketLifeTime.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*       ib_multipath_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_multipath_rec_pkt_life_sel\r
+* NAME\r
+*       ib_multipath_rec_pkt_life_sel\r
+*\r
+* DESCRIPTION\r
+*       Get encoded multipath pkt_lifetime selector.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_multipath_rec_pkt_life_sel(\r
+       IN      const   ib_multipath_rec_t* const       p_rec )\r
+{\r
+        return( (uint8_t)((p_rec->pkt_life & IB_MULTIPATH_REC_SELECTOR_MASK) >> 6 ));\r
+}\r
+/*\r
+* PARAMETERS\r
+*       p_rec\r
+*               [in] Pointer to the multipath record object.\r
+*\r
+* RETURN VALUES\r
+*       Encoded path pkt_lifetime selector value (for queries).\r
+*               0: greater than rate specified\r
+*               1: less than rate specified\r
+*               2: exactly the rate specified\r
+*               3: smallest packet lifetime available\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*       ib_multipath_rec_t\r
+*********/\r
+\r
+#define IB_NUM_PKEY_ELEMENTS_IN_BLOCK          32\r
+/****s* IBA Base: Types/ib_pkey_table_t\r
+* NAME\r
+*      ib_pkey_table_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined PKey table. (14.2.5.7)\r
+*\r
+* SYNOPSIS\r
+*/\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_pkey_table\r
+{\r
+       ib_net16_t              pkey_entry[IB_NUM_PKEY_ELEMENTS_IN_BLOCK];\r
+\r
+}      PACK_SUFFIX ib_pkey_table_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+/****s* IBA Base: Types/ib_pkey_table_record_t\r
+* NAME\r
+*      ib_pkey_table_record_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined P_Key Table Record for SA Query. (15.2.5.11)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_pkey_table_record\r
+{\r
+       ib_net16_t              lid; // for CA: lid of port, for switch lid of port 0\r
+       uint16_t                block_num;\r
+   uint8_t                     port_num; // for switch: port number, for CA: reserved\r
+       uint8_t                 reserved1;\r
+       uint16_t                reserved2;\r
+       ib_pkey_table_t         pkey_tbl;\r
+\r
+}      PACK_SUFFIX ib_pkey_table_record_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+#define IB_DROP_VL 15\r
+#define IB_MAX_NUM_VLS 16\r
+/****s* IBA Base: Types/ib_slvl_table_t\r
+* NAME\r
+*      ib_slvl_table_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined SL2VL Mapping Table Attribute. (14.2.5.8)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_slvl_table\r
+{\r
+       uint8_t raw_vl_by_sl[IB_MAX_NUM_VLS/2];\r
+}      PACK_SUFFIX ib_slvl_table_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+/****s* IBA Base: Types/ib_slvl_table_record_t\r
+* NAME\r
+*      ib_slvl_table_record_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined SL to VL Mapping Table Record for SA Query. (15.2.5.4)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_slvl_table_record\r
+{\r
+       ib_net16_t              lid; // for CA: lid of port, for switch lid of port 0\r
+       uint8_t                 in_port_num;    // reserved for CAs\r
+       uint8_t                 out_port_num;   // reserved for CAs\r
+       uint32_t                resv;\r
+       ib_slvl_table_t         slvl_tbl;\r
+\r
+}      PACK_SUFFIX ib_slvl_table_record_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+/****f* IBA Base: Types/ib_slvl_table_set\r
+* NAME\r
+*      ib_slvl_table_set\r
+*\r
+* DESCRIPTION\r
+*      Set slvl table entry.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_slvl_table_set(\r
+  IN           ib_slvl_table_t*        p_slvl_tbl,\r
+  IN           uint8_t                 sl_index,\r
+  IN           uint8_t                 vl )\r
+{\r
+  uint8_t idx = sl_index/2;\r
+  CL_ASSERT(vl <= 15);\r
+  CL_ASSERT(sl_index <= 15);\r
+\r
+  if (sl_index%2)\r
+  {\r
+    /* this is an odd sl. Need to update the ls bits */\r
+    p_slvl_tbl->raw_vl_by_sl[idx] = ( p_slvl_tbl->raw_vl_by_sl[idx] & 0xF0 ) | vl ;\r
+  }\r
+  else\r
+  {\r
+    /* this is an even sl. Need to update the ms bits */\r
+    p_slvl_tbl->raw_vl_by_sl[idx] = ( vl << 4 ) | ( p_slvl_tbl->raw_vl_by_sl[idx] & 0x0F );\r
+  }\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_slvl_tbl\r
+*              [in] pointer to ib_slvl_table_t object.\r
+*\r
+*      sl_index\r
+*              [in] the sl index in the table to be updated.\r
+*\r
+*      vl\r
+*              [in] the vl value to update for that sl.\r
+*\r
+* RETURN VALUES\r
+*      None\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_slvl_table_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_slvl_table_get\r
+* NAME\r
+*      ib_slvl_table_get\r
+*\r
+* DESCRIPTION\r
+*      Get slvl table entry.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_slvl_table_get(\r
+  IN   const   ib_slvl_table_t*        p_slvl_tbl,\r
+  IN           uint8_t                 sl_index )\r
+{\r
+  uint8_t idx = sl_index/2;\r
+  CL_ASSERT(sl_index <= 15);\r
+\r
+  if (sl_index%2)\r
+  {\r
+    /* this is an odd sl. Need to return the ls bits. */\r
+    return ( p_slvl_tbl->raw_vl_by_sl[idx] & 0x0F );\r
+  }\r
+  else\r
+  {\r
+    /* this is an even sl. Need to return the ms bits. */\r
+    return ( (p_slvl_tbl->raw_vl_by_sl[idx] & 0xF0) >> 4 );\r
+  }\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_slvl_tbl\r
+*              [in] pointer to ib_slvl_table_t object.\r
+*\r
+*      sl_index\r
+*              [in] the sl index in the table whose value should be returned.\r
+*\r
+* RETURN VALUES\r
+*      vl for the requested sl_index.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_slvl_table_t\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_vl_arb_element_t\r
+* NAME\r
+*      ib_vl_arb_element_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined VL Arbitration Table Element. (14.2.5.9)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_vl_arb_element\r
+{\r
+  uint8_t vl;\r
+  uint8_t weight;\r
+}      PACK_SUFFIX ib_vl_arb_element_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+#define IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK 32\r
+\r
+/****s* IBA Base: Types/ib_vl_arb_table_t\r
+* NAME\r
+*      ib_vl_arb_table_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined VL Arbitration Table. (14.2.5.9)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_vl_arb_table\r
+{\r
+       ib_vl_arb_element_t vl_entry[IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK];\r
+}      PACK_SUFFIX ib_vl_arb_table_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+/****s* IBA Base: Types/ib_vl_arb_table_record_t\r
+* NAME\r
+*      ib_vl_arb_table_record_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined VL Arbitration Table Record for SA Query. (15.2.5.9)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_vl_arb_table_record\r
+{\r
+       ib_net16_t              lid; // for CA: lid of port, for switch lid of port 0\r
+       uint8_t                 port_num;\r
+       uint8_t                 block_num;\r
+       uint32_t                reserved;\r
+       ib_vl_arb_table_t       vl_arb_tbl;\r
+}      PACK_SUFFIX ib_vl_arb_table_record_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+/*\r
+ *     Global route header information received with unreliable datagram messages\r
+ */\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_grh\r
+{\r
+       ib_net32_t              ver_class_flow;\r
+       uint16_t                resv1;\r
+       uint8_t                 resv2;\r
+       uint8_t                 hop_limit;\r
+       ib_gid_t                src_gid;\r
+       ib_gid_t                dest_gid;\r
+}      PACK_SUFFIX ib_grh_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+/****f* IBA Base: Types/ib_grh_get_ver_class_flow\r
+* NAME\r
+*      ib_grh_get_ver_class_flow\r
+*\r
+* DESCRIPTION\r
+*      Get encoded version, traffic class and flow label in grh\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_grh_get_ver_class_flow(\r
+       IN      const   ib_net32_t              ver_class_flow,\r
+       OUT             uint8_t* const          p_ver,\r
+       OUT             uint8_t* const          p_tclass,\r
+       OUT             uint32_t* const         p_flow_lbl )\r
+{\r
+       ib_net32_t tmp_ver_class_flow;\r
+\r
+       if (p_ver)\r
+               *p_ver = (uint8_t)(ver_class_flow & 0x0f);\r
+\r
+       tmp_ver_class_flow = ver_class_flow >> 4;\r
+\r
+       if (p_tclass)\r
+               *p_tclass = (uint8_t)(tmp_ver_class_flow & 0xff);\r
+\r
+       tmp_ver_class_flow = tmp_ver_class_flow >> 8;\r
+\r
+       if (p_flow_lbl)\r
+               *p_flow_lbl = tmp_ver_class_flow & 0xfffff;\r
+}\r
+/*\r
+* PARAMETERS\r
+*      ver_class_flow\r
+*              [in] the version, traffic class and flow label info.\r
+*\r
+* RETURN VALUES\r
+*      p_ver\r
+*              [out] pointer to the version info.\r
+*\r
+*      p_tclass\r
+*              [out] pointer to the traffic class info.\r
+*\r
+*      p_flow_lbl\r
+*              [out] pointer to the flow label info\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_grh_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_grh_set_ver_class_flow\r
+* NAME\r
+*      ib_grh_set_ver_class_flow\r
+*\r
+* DESCRIPTION\r
+*      Set encoded version, traffic class and flow label in grh\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net32_t       OSM_API\r
+ib_grh_set_ver_class_flow(\r
+       IN      const   uint8_t                 ver,\r
+       IN      const   uint8_t                 tclass,\r
+       IN      const   uint32_t                flow_lbl )\r
+{\r
+       ib_net32_t              ver_class_flow;\r
+\r
+       ver_class_flow = flow_lbl;\r
+       ver_class_flow = ver_class_flow << 8;\r
+       ver_class_flow = ver_class_flow | tclass;\r
+       ver_class_flow = ver_class_flow << 4;\r
+       ver_class_flow = ver_class_flow | ver;\r
+       return (ver_class_flow);\r
+}\r
+/*\r
+* PARAMETERS\r
+*      ver\r
+*              [in] the version info.\r
+*\r
+*      tclass\r
+*              [in] the traffic class info.\r
+*\r
+*      flow_lbl\r
+*              [in] the flow label info\r
+*\r
+* RETURN VALUES\r
+*      ver_class_flow\r
+*              [out] the version, traffic class and flow label info.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_grh_t\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_member_rec_t\r
+* NAME\r
+*      ib_member_rec_t\r
+*\r
+* DESCRIPTION\r
+*      Multicast member record, used to create, join, and leave multicast\r
+*      groups.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_member_rec\r
+{\r
+       ib_gid_t                                mgid;\r
+       ib_gid_t                                port_gid;\r
+       ib_net32_t                              qkey;\r
+       ib_net16_t                              mlid;\r
+       uint8_t                                 mtu;\r
+       uint8_t                                 tclass;\r
+       ib_net16_t                              pkey;\r
+       uint8_t                                 rate;\r
+       uint8_t                                 pkt_life;\r
+       ib_net32_t                              sl_flow_hop;\r
+       uint8_t                                 scope_state;\r
+       uint8_t                                 proxy_join:1;\r
+       uint8_t                                 reserved[2];\r
+       uint8_t                                 pad[4];\r
+\r
+}      PACK_SUFFIX ib_member_rec_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+*      mgid\r
+*              Multicast GID address for this multicast group.\r
+*\r
+*      port_gid\r
+*              Valid GID of the endpoint joining this multicast group.\r
+*\r
+*      qkey\r
+*              Q_Key to be sued by this multicast group.\r
+*\r
+*      mlid\r
+*              Multicast LID for this multicast group.\r
+*\r
+*      mtu\r
+*              MTU and MTU selector fields to use on this path\r
+*\r
+*      tclass\r
+*              Another global routing parameter.\r
+*\r
+*      pkey\r
+*              Partition key (P_Key) to use for this member.\r
+*\r
+*      rate\r
+*              Rate and rate selector fields to use on this path.\r
+*\r
+*      pkt_life\r
+*              Packet lifetime\r
+*\r
+*      sl_flow_hop\r
+*              Global routing parameters: service level, hop count, and flow label.\r
+*\r
+*      scope_state\r
+*              MGID scope and JoinState of multicast request.\r
+*\r
+*      proxy_join\r
+*              Enables others in the Partition to proxy add/remove from the group\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_member_get_sl_flow_hop\r
+* NAME\r
+*      ib_member_get_sl_flow_hop\r
+*\r
+* DESCRIPTION\r
+*      Get encoded sl, flow label, and hop limit\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_member_get_sl_flow_hop(\r
+       IN const ib_net32_t sl_flow_hop,\r
+       OUT uint8_t* const p_sl,\r
+       OUT uint32_t* const p_flow_lbl,\r
+       OUT uint8_t* const p_hop )\r
+{\r
+       uint32_t tmp;\r
+\r
+       tmp = cl_ntoh32(sl_flow_hop);\r
+       if (p_hop)\r
+               *p_hop = (uint8_t)tmp;\r
+       tmp >>= 8;\r
+\r
+       if (p_flow_lbl)\r
+               *p_flow_lbl = (uint32_t)(tmp & 0xfffff);\r
+       tmp >>= 20;\r
+\r
+       if (p_sl)\r
+               *p_sl = (uint8_t)tmp;\r
+}\r
+/*\r
+* PARAMETERS\r
+*      sl_flow_hop\r
+*              [in] the sl, flow label, and hop limit of MC Group\r
+*\r
+* RETURN VALUES\r
+*      p_sl\r
+*              [out] pointer to the service level\r
+*\r
+*      p_flow_lbl\r
+*              [out] pointer to the flow label info\r
+*\r
+*      p_hop\r
+*              [out] pointer to the hop count limit.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_member_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_member_set_sl_flow_hop\r
+* NAME\r
+*      ib_member_set_sl_flow_hop\r
+*\r
+* DESCRIPTION\r
+*      Set encoded sl, flow label, and hop limit\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net32_t       OSM_API\r
+ib_member_set_sl_flow_hop(\r
+       IN const uint8_t sl,\r
+       IN const uint32_t flow_label,\r
+       IN const uint8_t hop_limit )\r
+{\r
+       uint32_t tmp;\r
+\r
+       tmp = (sl << 28) | ((flow_label & 0xfffff) << 8) | hop_limit;\r
+       return cl_hton32(tmp);\r
+}\r
+/*\r
+* PARAMETERS\r
+*      sl\r
+*              [in] the service level.\r
+*\r
+*      flow_lbl\r
+*              [in] the flow label info\r
+*\r
+*      hop_limit\r
+*              [in] the hop limit.\r
+*\r
+* RETURN VALUES\r
+*      sl_flow_hop\r
+*              [out] the encoded sl, flow label, and hop limit\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_member_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_member_get_scope_state\r
+* NAME\r
+*      ib_member_get_scope_state\r
+*\r
+* DESCRIPTION\r
+*      Get encoded MGID scope and JoinState\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_member_get_scope_state(\r
+       IN      const   uint8_t                 scope_state,\r
+       OUT             uint8_t* const          p_scope,\r
+       OUT             uint8_t* const          p_state )\r
+{\r
+       uint8_t         tmp_scope_state;\r
+\r
+       if (p_state)\r
+               *p_state = (uint8_t)(scope_state & 0x0f);\r
+\r
+       tmp_scope_state = scope_state >> 4;\r
+\r
+       if (p_scope)\r
+               *p_scope = (uint8_t)(tmp_scope_state & 0x0f);\r
+\r
+}\r
+/*\r
+* PARAMETERS\r
+*      scope_state\r
+*              [in] the scope and state\r
+*\r
+* RETURN VALUES\r
+*      p_scope\r
+*              [out] pointer to the MGID scope\r
+*\r
+*      p_state\r
+*              [out] pointer to the join state\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_member_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_member_set_scope_state\r
+* NAME\r
+*      ib_member_set_scope_state\r
+*\r
+* DESCRIPTION\r
+*      Set encoded version, MGID scope and JoinState\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_member_set_scope_state(\r
+       IN      const   uint8_t                 scope,\r
+       IN      const   uint8_t                 state )\r
+{\r
+       uint8_t         scope_state;\r
+\r
+       scope_state = scope;\r
+       scope_state = scope_state << 4;\r
+       scope_state = scope_state | state;\r
+       return (scope_state);\r
+}\r
+/*\r
+* PARAMETERS\r
+*      scope\r
+*              [in] the MGID scope\r
+*\r
+*      state\r
+*              [in] the JoinState\r
+*\r
+* RETURN VALUES\r
+*      scope_state\r
+*              [out] the encoded one\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_member_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_member_set_join_state\r
+* NAME\r
+*      ib_member_set_join_state\r
+*\r
+* DESCRIPTION\r
+*      Set JoinState\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_member_set_join_state(\r
+       IN OUT          ib_member_rec_t         *p_mc_rec,\r
+       IN      const   uint8_t                 state )\r
+{\r
+       /* keep the scope as it is */\r
+       p_mc_rec->scope_state = (p_mc_rec->scope_state & 0xF0) | (0x0f & state);\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_mc_rec\r
+*              [in] pointer to the member record\r
+*\r
+*      state\r
+*              [in] the JoinState\r
+*\r
+* RETURN VALUES\r
+*      NONE\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_member_rec_t\r
+*********/\r
+\r
+/*\r
+ * Join State Codes:\r
+ */\r
+#define IB_MC_REC_STATE_FULL_MEMBER 0x01\r
+#define IB_MC_REC_STATE_NON_MEMBER 0x02\r
+#define IB_MC_REC_STATE_SEND_ONLY_MEMBER 0x04\r
+\r
+/*\r
+ *     Generic MAD notice types\r
+ */\r
+#define IB_NOTICE_TYPE_FATAL                           0x00\r
+#define IB_NOTICE_TYPE_URGENT                          0x01\r
+#define IB_NOTICE_TYPE_SECURITY                                0x02\r
+#define IB_NOTICE_TYPE_SUBN_MGMT                       0x03\r
+#define IB_NOTICE_TYPE_INFO                            0x04\r
+#define IB_NOTICE_TYPE_EMPTY                           0x7F\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_mad_notice_attr    // Total Size calc  Accumulated\r
+{\r
+  uint8_t                      generic_type;    // 1                1\r
+  \r
+  union _notice_g_or_v\r
+  {\r
+        struct _notice_generic            // 5                6\r
+        {\r
+               uint8_t         prod_type_msb;\r
+               ib_net16_t      prod_type_lsb;\r
+               ib_net16_t      trap_num;\r
+        }      PACK_SUFFIX generic;\r
+        \r
+        struct _notice_vend\r
+        {\r
+               uint8_t         vend_id_msb;\r
+               ib_net16_t      vend_id_lsb;\r
+               ib_net16_t      dev_id;\r
+        }      PACK_SUFFIX vend;\r
+  } g_or_v;\r
+  \r
+  ib_net16_t                   issuer_lid;    // 2                 8\r
+  ib_net16_t                   toggle_count;  // 2                 10\r
+  \r
+  union _data_details               // 54                64\r
+       {\r
+         struct _raw_data\r
+         {\r
+                uint8_t        details[54];\r
+         } PACK_SUFFIX raw_data;\r
+\r
+         struct _ntc_64_67\r
+         {\r
+                uint8_t    res[6];\r
+                ib_gid_t   gid;        // the Node or Multicast Group that came in/out\r
+         } PACK_SUFFIX ntc_64_67;\r
+\r
+         struct _ntc_128 {\r
+                ib_net16_t sw_lid; // the sw lid of which link state changed\r
+         } PACK_SUFFIX ntc_128;\r
+         \r
+         struct _ntc_129_131 {\r
+                ib_net16_t    pad;\r
+                ib_net16_t    lid;             // lid and port number of the violation\r
+                uint8_t     port_num;\r
+         } PACK_SUFFIX ntc_129_131;\r
+         \r
+         struct _ntc_144 {\r
+                ib_net16_t    pad1;\r
+                ib_net16_t    lid;             // lid where capability mask changed\r
+                ib_net16_t    pad2;\r
+                ib_net32_t    new_cap_mask; // new capability mask\r
+         } PACK_SUFFIX ntc_144;\r
+\r
+         struct _ntc_145 {\r
+                ib_net16_t    pad1;\r
+                ib_net16_t    lid;             // lid where sys guid changed\r
+                ib_net16_t    pad2;\r
+                ib_net64_t    new_sys_guid; // new system image guid\r
+         } PACK_SUFFIX ntc_145;\r
+\r
+         struct _ntc_256 {                       // total: 54\r
+                ib_net16_t    pad1;                   // 2\r
+                ib_net16_t    lid;                    // 2\r
+                ib_net16_t    pad2;                   // 2\r
+                uint8_t       method;                 // 1\r
+                uint8_t       pad3;                   // 1\r
+                ib_net16_t    attr_id;                // 2\r
+                ib_net32_t    attr_mod;               // 4\r
+                ib_net64_t    mkey;                   // 8\r
+                uint8_t       dr_slid;                // 1\r
+                uint8_t       dr_trunc_hop;           // 1\r
+                uint8_t       dr_rtn_path[30];        // 30\r
+         } PACK_SUFFIX ntc_256;\r
+\r
+         struct _ntc_257_258 // violation of p/q_key // 49\r
+         {\r
+                ib_net16_t    pad1;                   // 2\r
+                ib_net16_t    lid1;                   // 2\r
+                ib_net16_t    lid2;                   // 2\r
+                ib_net32_t    key;                    // 2\r
+                uint8_t       sl;                     // 1\r
+                ib_net32_t    qp1;                    // 4\r
+                ib_net32_t    qp2;                    // 4\r
+                ib_gid_t      gid1;                   // 16\r
+                ib_gid_t      gid2;                   // 16\r
+         } PACK_SUFFIX ntc_257_258;\r
+\r
+         struct _ntc_259 // p/q_key violation with sw info 53\r
+         {\r
+                ib_net16_t    data_valid;   // 2\r
+                ib_net16_t    lid1;         // 2\r
+                ib_net16_t    lid2;         // 2\r
+                ib_net32_t    key;          // 4\r
+                uint8_t       sl;           // 1\r
+                ib_net32_t    qp1;          // 4\r
+                uint8_t       qp2_msb;      // 1\r
+                ib_net16_t    qp2_lsb;      // 2\r
+                ib_gid_t      gid1;         // 16\r
+                ib_gid_t      gid2;         // 16\r
+                ib_net16_t    sw_lid;       // 2\r
+                uint8_t       port_no;      // 1\r
+         } PACK_SUFFIX ntc_259;\r
+\r
+       } data_details;\r
+\r
+  ib_gid_t                     issuer_gid;    // 16          80\r
+\r
+}      PACK_SUFFIX ib_mad_notice_attr_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+/****f* IBA Base: Types/ib_notice_is_generic\r
+* NAME\r
+*      ib_notice_is_generic\r
+*\r
+* DESCRIPTION\r
+*      Check if the notice is generic\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t        OSM_API\r
+ib_notice_is_generic(\r
+  IN           const   ib_mad_notice_attr_t *p_ntc )\r
+{\r
+  return (p_ntc->generic_type & 0x80);\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_ntc\r
+*              [in] Pointer to  the notice MAD attribute\r
+*\r
+* RETURN VALUES\r
+*      TRUE if mad is generic\r
+*\r
+* SEE ALSO\r
+*      ib_mad_notice_attr_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_notice_get_type\r
+* NAME\r
+*      ib_notice_get_type\r
+*\r
+* DESCRIPTION\r
+*      Get the notice type\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_notice_get_type(\r
+  IN           const   ib_mad_notice_attr_t *p_ntc )\r
+{\r
+  return p_ntc->generic_type & 0x7f;\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_ntc\r
+*              [in] Pointer to  the notice MAD attribute\r
+*\r
+* RETURN VALUES\r
+*      TRUE if mad is generic\r
+*\r
+* SEE ALSO\r
+*      ib_mad_notice_attr_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_notice_get_prod_type\r
+* NAME\r
+*      ib_notice_get_prod_type\r
+*\r
+* DESCRIPTION\r
+*      Get the notice Producer Type of Generic Notice\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net32_t       OSM_API\r
+ib_notice_get_prod_type(\r
+  IN              const        ib_mad_notice_attr_t *p_ntc )\r
+{\r
+  uint32_t pt;\r
+\r
+  pt = cl_ntoh16(p_ntc->g_or_v.generic.prod_type_lsb) |\r
+    (p_ntc->g_or_v.generic.prod_type_msb << 16);\r
+  return cl_hton32(pt);\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_ntc\r
+*              [in] Pointer to the notice MAD attribute\r
+*\r
+* RETURN VALUES\r
+*      The producer type\r
+*\r
+* SEE ALSO\r
+*      ib_mad_notice_attr_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_notice_set_prod_type\r
+* NAME\r
+*      ib_notice_set_prod_type\r
+*\r
+* DESCRIPTION\r
+*      Set the notice Producer Type of Generic Notice\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_notice_set_prod_type(\r
+  IN ib_mad_notice_attr_t *p_ntc,\r
+  IN ib_net32_t prod_type_val )\r
+{\r
+  uint32_t ptv = cl_ntoh32(prod_type_val);\r
+  p_ntc->g_or_v.generic.prod_type_lsb = cl_hton16((uint16_t)(ptv & 0x0000ffff));\r
+  p_ntc->g_or_v.generic.prod_type_msb = (uint8_t)( (ptv & 0x00ff0000) >> 16);\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_ntc\r
+*              [in] Pointer to the notice MAD attribute\r
+*\r
+*  prod_type\r
+*     [in] The producer Type code\r
+*\r
+* RETURN VALUES\r
+*      None\r
+*\r
+* SEE ALSO\r
+*      ib_mad_notice_attr_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_notice_set_prod_type_ho\r
+* NAME\r
+*      ib_notice_set_prod_type_ho\r
+*\r
+* DESCRIPTION\r
+*      Set the notice Producer Type of Generic Notice given Host Order\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_notice_set_prod_type_ho(\r
+  IN ib_mad_notice_attr_t *p_ntc,\r
+  IN uint32_t prod_type_val_ho )\r
+{\r
+  p_ntc->g_or_v.generic.prod_type_lsb = \r
+         cl_hton16( (uint16_t)(prod_type_val_ho & 0x0000ffff) );\r
+  p_ntc->g_or_v.generic.prod_type_msb = \r
+         (uint8_t)( (prod_type_val_ho & 0x00ff0000) >> 16);\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_ntc\r
+*              [in] Pointer to the notice MAD attribute\r
+*\r
+*      prod_type\r
+*              [in] The producer Type code in host order\r
+*\r
+* RETURN VALUES\r
+*      None\r
+*\r
+* SEE ALSO\r
+*      ib_mad_notice_attr_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_notice_get_vend_id\r
+* NAME\r
+*      ib_notice_get_vend_id\r
+*\r
+* DESCRIPTION\r
+*      Get the Vendor Id of Vendor type Notice\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net32_t       OSM_API\r
+ib_notice_get_vend_id(\r
+  IN           const   ib_mad_notice_attr_t *p_ntc )\r
+{\r
+  uint32_t vi;\r
+\r
+  vi = cl_ntoh16(p_ntc->g_or_v.vend.vend_id_lsb) |\r
+    (p_ntc->g_or_v.vend.vend_id_msb << 16);\r
+  return cl_hton32(vi);\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_ntc\r
+*              [in] Pointer to the notice MAD attribute\r
+*\r
+* RETURN VALUES\r
+*      The Vendor Id of Vendor type Notice\r
+*\r
+* SEE ALSO\r
+*      ib_mad_notice_attr_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_notice_set_vend_id\r
+* NAME\r
+*      ib_notice_set_vend_id\r
+*\r
+* DESCRIPTION\r
+*      Set the notice Producer Type of Generic Notice\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_notice_set_vend_id(\r
+  IN ib_mad_notice_attr_t *p_ntc,\r
+  IN ib_net32_t vend_id )\r
+{\r
+  uint32_t vi = cl_ntoh32(vend_id);\r
+  p_ntc->g_or_v.vend.vend_id_lsb = cl_hton16((uint16_t)(vi & 0x0000ffff));\r
+  p_ntc->g_or_v.vend.vend_id_msb = (uint8_t)((vi & 0x00ff0000) >> 16);\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_ntc\r
+*              [in] Pointer to the notice MAD attribute\r
+*\r
+*      vend_id\r
+*              [in] The producer Type code\r
+*\r
+* RETURN VALUES\r
+*      None\r
+*\r
+* SEE ALSO\r
+*      ib_mad_notice_attr_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_notice_set_vend_id_ho\r
+* NAME\r
+*      ib_notice_set_vend_id_ho\r
+*\r
+* DESCRIPTION\r
+*      Set the notice Producer Type of Generic Notice given a host order value\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_notice_set_vend_id_ho(\r
+  IN ib_mad_notice_attr_t *p_ntc,\r
+  IN uint32_t vend_id_ho )\r
+{\r
+  p_ntc->g_or_v.vend.vend_id_lsb = \r
+         cl_hton16((uint16_t)(vend_id_ho & 0x0000ffff));\r
+  p_ntc->g_or_v.vend.vend_id_msb =\r
+         (uint8_t)((vend_id_ho & 0x00ff0000) >> 16);\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_ntc\r
+*              [in] Pointer to the notice MAD attribute\r
+*\r
+*      vend_id_ho\r
+*              [in] The producer Type code in host order\r
+*\r
+* RETURN VALUES\r
+*      None\r
+*\r
+* SEE ALSO\r
+*      ib_mad_notice_attr_t\r
+*********/\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_inform_info\r
+{\r
+  ib_gid_t                             gid;\r
+  ib_net16_t                           lid_range_begin;\r
+  ib_net16_t                           lid_range_end;\r
+  ib_net16_t                           reserved1;\r
+  uint8_t                              is_generic;\r
+  uint8_t                              subscribe;\r
+  ib_net16_t                           trap_type;\r
+  union _inform_g_or_v\r
+  {\r
+        struct _inform_generic\r
+        {\r
+               ib_net16_t              trap_num;\r
+               ib_net32_t              qpn_resp_time_val;\r
+               uint8_t                 reserved2;\r
+               uint8_t                 node_type_msb;\r
+               ib_net16_t              node_type_lsb;\r
+        } PACK_SUFFIX generic;\r
+        \r
+        struct _inform_vend\r
+        {\r
+               ib_net16_t              dev_id;\r
+               ib_net32_t              qpn_resp_time_val;\r
+               uint8_t                 reserved2;\r
+               uint8_t                 vendor_id_msb;\r
+               ib_net16_t              vendor_id_lsb;\r
+        } PACK_SUFFIX vend;\r
+        \r
+  }    PACK_SUFFIX g_or_v;\r
+  \r
+}      PACK_SUFFIX ib_inform_info_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+/****f* IBA Base: Types/ib_inform_info_get_qpn_resp_time\r
+* NAME\r
+*      ib_inform_info_get_qpn_resp_time\r
+*\r
+* DESCRIPTION\r
+*      Get QPN of the inform info\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_inform_info_get_qpn_resp_time(\r
+  IN   const   ib_net32_t              qpn_resp_time_val,\r
+  OUT          ib_net32_t* const       p_qpn,\r
+  OUT          uint8_t* const          p_resp_time_val )\r
+{\r
+  uint32_t tmp = cl_ntoh32(qpn_resp_time_val);\r
+\r
+  if (p_qpn)\r
+    *p_qpn = cl_hton32((tmp & 0xffffff00) >> 8);\r
+       \r
+       if (p_resp_time_val)\r
+               *p_resp_time_val = (uint8_t)(tmp & 0x0000001f);\r
+}\r
+/*\r
+* PARAMETERS\r
+*      qpn_resp_time_val\r
+*              [in] the  qpn and resp time val from the mad\r
+*\r
+* RETURN VALUES\r
+*      p_qpn\r
+*              [out] pointer to the qpn\r
+*\r
+*      p_state\r
+*              [out] pointer to the resp time val\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_inform_info_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_inform_info_set_qpn\r
+* NAME\r
+*      ib_inform_info_set_qpn\r
+*\r
+* DESCRIPTION\r
+*      Set the QPN of the inform info\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void     OSM_API\r
+ib_inform_info_set_qpn(\r
+  IN   ib_inform_info_t        *p_ii,\r
+  IN   ib_net32_t const        qpn)\r
+{\r
+  uint32_t tmp = cl_ntoh32(p_ii->g_or_v.generic.qpn_resp_time_val);\r
+\r
+  p_ii->g_or_v.generic.qpn_resp_time_val = \r
+    cl_hton32(\r
+      (tmp & 0x000000ff) |\r
+      ((cl_ntoh32(qpn) << 8) & 0xffffff00)\r
+      );\r
+}\r
+/*\r
+* PARAMETERS\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_inform_info_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_inform_info_get_prod_type\r
+* NAME\r
+*      ib_inform_info_get_prod_type\r
+*\r
+* DESCRIPTION\r
+*      Get Producer Type of the Inform Info\r
+*      13.4.8.3 InformInfo\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net32_t OSM_API\r
+ib_inform_info_get_prod_type(IN const ib_inform_info_t * p_inf)\r
+{\r
+       uint32_t nt;\r
+\r
+       nt = cl_ntoh16(p_inf->g_or_v.generic.node_type_lsb) |\r
+           (p_inf->g_or_v.generic.node_type_msb << 16);\r
+       return cl_hton32(nt);\r
+}\r
+\r
+/*\r
+* PARAMETERS\r
+*      p_inf\r
+*              [in] pointer to an inform info\r
+*\r
+* RETURN VALUES\r
+*     The producer type\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_inform_info_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_inform_info_get_node_type\r
+* NAME\r
+*      ib_inform_info_get_node_type\r
+*\r
+* DESCRIPTION\r
+*      Get Node Type of the Inform Info\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net32_t       OSM_API\r
+ib_inform_info_get_node_type(\r
+  IN           const   ib_inform_info_t  *p_inf)\r
+{\r
+  uint32_t nt;\r
+\r
+  nt = cl_ntoh16(p_inf->g_or_v.generic.node_type_lsb) |\r
+    (p_inf->g_or_v.generic.node_type_msb << 16);\r
+  return cl_hton32(nt);\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_inf\r
+*              [in] pointer to an inform info\r
+*\r
+* RETURN VALUES\r
+*     The node type\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_inform_info_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_inform_info_get_vend_id\r
+* NAME\r
+*      ib_inform_info_get_vend_id\r
+*\r
+* DESCRIPTION\r
+*      Get Node Type of the Inform Info\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net32_t       OSM_API\r
+ib_inform_info_get_vend_id(\r
+  IN           const   ib_inform_info_t  *p_inf)\r
+{\r
+  uint32_t vi;\r
+\r
+  vi = cl_ntoh16(p_inf->g_or_v.vend.vendor_id_lsb) |\r
+    (p_inf->g_or_v.vend.vendor_id_msb << 16);\r
+  return cl_hton32(vi);\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_inf\r
+*              [in] pointer to an inform info\r
+*\r
+* RETURN VALUES\r
+*     The node type\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_inform_info_t\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_inform_info_record_t\r
+* NAME\r
+*      ib_inform_info_record_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined InformInfo Record. (15.2.5.12)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_inform_info_record\r
+{\r
+       ib_gid_t                        subscriber_gid;\r
+       ib_net16_t                      subscriber_enum;\r
+       uint8_t                         reserved[6];\r
+       ib_inform_info_t                inform_info;\r
+       uint8_t                         pad[4];\r
+}      PACK_SUFFIX ib_inform_info_record_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+/****d* IBA Base: Types/DM_SVC_NAME\r
+* NAME\r
+*      DM_SVC_NAME\r
+*\r
+* DESCRIPTION\r
+*      IBA defined Device Management service name (16.3)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define        DM_SVC_NAME                             "DeviceManager.IBTA"\r
+/*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_dm_mad_t\r
+* NAME\r
+*      ib_dm_mad_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined Device Management MAD (16.3.1)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_dm_mad\r
+{\r
+       ib_mad_t                header;\r
+       uint8_t                 resv[40];\r
+\r
+#define        IB_DM_DATA_SIZE         192\r
+       uint8_t                 data[IB_DM_DATA_SIZE];\r
+\r
+}      PACK_SUFFIX ib_dm_mad_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+*      header\r
+*              Common MAD header.\r
+*\r
+*      resv\r
+*              Reserved.\r
+*\r
+*      data\r
+*              Device Management payload.  The structure and content of this field\r
+*              depend upon the method, attr_id, and attr_mod fields in the header.\r
+*\r
+* SEE ALSO\r
+* ib_mad_t\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_iou_info_t\r
+* NAME\r
+*      ib_iou_info_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined IO Unit information structure (16.3.3.3)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_iou_info\r
+{\r
+       ib_net16_t              change_id;\r
+       uint8_t                 max_controllers;\r
+       uint8_t                 diag_rom;\r
+\r
+#define        IB_DM_CTRL_LIST_SIZE    128\r
+\r
+       uint8_t                 controller_list[IB_DM_CTRL_LIST_SIZE];\r
+#define        IOC_NOT_INSTALLED               0x0\r
+#define        IOC_INSTALLED                   0x1\r
+//             Reserved values                         0x02-0xE\r
+#define        SLOT_DOES_NOT_EXIST             0xF\r
+\r
+}      PACK_SUFFIX ib_iou_info_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+*      change_id\r
+*              Value incremented, with rollover, by any change to the controller_list.\r
+*\r
+*      max_controllers\r
+*              Number of slots in controller_list.\r
+*\r
+*      diag_rom\r
+*              A byte containing two fields: DiagDeviceID and OptionROM.\r
+*              These fields may be read using the ib_iou_info_diag_dev_id\r
+*              and ib_iou_info_option_rom functions.\r
+*\r
+*      controller_list\r
+*              A series of 4-bit nibbles, with each nibble representing a slot\r
+*              in the IO Unit.  Individual nibbles may be read using the\r
+*              ioc_at_slot function.\r
+*\r
+* SEE ALSO\r
+* ib_dm_mad_t, ib_iou_info_diag_dev_id, ib_iou_info_option_rom, ioc_at_slot\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_iou_info_diag_dev_id\r
+* NAME\r
+*      ib_iou_info_diag_dev_id\r
+*\r
+* DESCRIPTION\r
+*      Returns the DiagDeviceID.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_iou_info_diag_dev_id(\r
+       IN      const   ib_iou_info_t* const    p_iou_info )\r
+{\r
+       return( (uint8_t)(p_iou_info->diag_rom >> 6 & 1) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_iou_info\r
+*              [in] Pointer to the IO Unit information structure.\r
+*\r
+* RETURN VALUES\r
+*      DiagDeviceID field of the IO Unit information.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_iou_info_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_iou_info_option_rom\r
+* NAME\r
+*      ib_iou_info_option_rom\r
+*\r
+* DESCRIPTION\r
+*      Returns the OptionROM.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ib_iou_info_option_rom(\r
+       IN      const   ib_iou_info_t*  const   p_iou_info )\r
+{\r
+       return( (uint8_t)(p_iou_info->diag_rom >> 7) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_iou_info\r
+*              [in] Pointer to the IO Unit information structure.\r
+*\r
+* RETURN VALUES\r
+*      OptionROM field of the IO Unit information.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_iou_info_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ioc_at_slot\r
+* NAME\r
+*      ioc_at_slot\r
+*\r
+* DESCRIPTION\r
+*      Returns the IOC value at the specified slot.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t  OSM_API\r
+ioc_at_slot(\r
+       IN      const   ib_iou_info_t*  const   p_iou_info,\r
+       IN              uint8_t                 slot )\r
+{\r
+       if( slot >= IB_DM_CTRL_LIST_SIZE ) return SLOT_DOES_NOT_EXIST;\r
+       else return (int8_t)\r
+               ( (slot%2) ?\r
+                       ((p_iou_info->controller_list[slot/2] & 0xf0) >> 4 ):\r
+                       (p_iou_info->controller_list[slot/2] & 0x0f) );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_iou_info\r
+*              [in] Pointer to the IO Unit information structure.\r
+*\r
+*      slot\r
+*              [in] Pointer to the IO Unit information structure.\r
+*\r
+* RETURN VALUES\r
+*      OptionROM field of the IO Unit information.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*      ib_iou_info_t\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_ioc_profile_t\r
+* NAME\r
+*      ib_ioc_profile_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined IO Controller profile structure (16.3.3.4)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_ioc_profile\r
+{\r
+       ib_net64_t                              ioc_guid;\r
+\r
+       ib_net32_t                              vend_id;\r
+\r
+       ib_net32_t                              dev_id;\r
+       ib_net16_t                              dev_ver;\r
+       ib_net16_t                              resv2;\r
+\r
+       ib_net32_t                              subsys_vend_id;\r
+       ib_net32_t                              subsys_id;\r
+\r
+       ib_net16_t                              io_class;\r
+       ib_net16_t                              io_subclass;\r
+       ib_net16_t                              protocol;\r
+       ib_net16_t                              protocol_ver;\r
+\r
+       ib_net32_t                              resv3;\r
+       ib_net16_t                              send_msg_depth;\r
+       uint8_t                                 resv4;\r
+       uint8_t                                 rdma_read_depth;\r
+       ib_net32_t                              send_msg_size;\r
+       ib_net32_t                              rdma_size;\r
+\r
+       uint8_t                                 ctrl_ops_cap;\r
+#define        CTRL_OPS_CAP_ST         0x01\r
+#define        CTRL_OPS_CAP_SF         0x02\r
+#define        CTRL_OPS_CAP_RT         0x04\r
+#define        CTRL_OPS_CAP_RF         0x08\r
+#define        CTRL_OPS_CAP_WT         0x10\r
+#define        CTRL_OPS_CAP_WF         0x20\r
+#define        CTRL_OPS_CAP_AT         0x40\r
+#define        CTRL_OPS_CAP_AF         0x80\r
+\r
+       uint8_t                                 resv5;\r
+\r
+       uint8_t                                 num_svc_entries;\r
+#define        MAX_NUM_SVC_ENTRIES     0xff\r
+\r
+       uint8_t                                 resv6[9];\r
+\r
+#define        CTRL_ID_STRING_LEN      64\r
+       char                                    id_string[CTRL_ID_STRING_LEN];\r
+\r
+}      PACK_SUFFIX ib_ioc_profile_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+*      ioc_guid\r
+*              An EUI-64 GUID used to uniquely identify the IO controller.\r
+*\r
+*      vend_id\r
+*              IO controller vendor ID, IEEE format.\r
+*\r
+*      dev_id\r
+*              A number assigned by the vendor to identify the type of controller.\r
+*\r
+*      dev_ver\r
+*              A number assigned by the vendor to identify the divice version.\r
+*\r
+*      subsys_vend_id\r
+*              ID of the vendor of the enclosure, if any, in which the IO controller\r
+*              resides in IEEE format; otherwise zero.\r
+*\r
+*      subsys_id\r
+*              A number identifying the subsystem where the controller resides.\r
+*\r
+*      io_class\r
+*              0x0000 - 0xfffe = reserved for IO classes encompased by InfiniBand\r
+*              Architecture.  0xffff = Vendor specific.\r
+*\r
+*      io_subclass\r
+*              0x0000 - 0xfffe = reserved for IO subclasses encompased by InfiniBand\r
+*              Architecture.  0xffff = Vendor specific.  This shall be set to 0xfff\r
+*              if the io_class component is 0xffff.\r
+*\r
+*      protocol\r
+*              0x0000 - 0xfffe = reserved for IO subclasses encompased by InfiniBand\r
+*              Architecture.  0xffff = Vendor specific.  This shall be set to 0xfff\r
+*              if the io_class component is 0xffff.\r
+*\r
+*      protocol_ver\r
+*              Protocol specific.\r
+*\r
+*      send_msg_depth\r
+*              Maximum depth of the send message queue.\r
+*\r
+*      rdma_read_depth\r
+*              Maximum depth of the per-channel RDMA read queue.\r
+*\r
+*      send_msg_size\r
+*              Maximum size of send messages.\r
+*\r
+*      ctrl_ops_cap\r
+*              Supported operation types of this IO controller.  A bit set to one\r
+*              for affirmation of supported capability.\r
+*\r
+*      num_svc_entries\r
+*              Number of entries in the service entries table.\r
+*\r
+*      id_string\r
+*              UTF-8 encoded string for identifying the controller to an operator.\r
+*\r
+* SEE ALSO\r
+* ib_dm_mad_t\r
+*********/\r
+\r
+static inline uint32_t OSM_API\r
+ib_ioc_profile_get_vend_id(\r
+       IN      const   ib_ioc_profile_t* const         p_ioc_profile )\r
+{\r
+       return( cl_ntoh32(p_ioc_profile->vend_id) >> 8 );\r
+}\r
+\r
+\r
+static inline void     OSM_API\r
+ib_ioc_profile_set_vend_id(\r
+       IN              ib_ioc_profile_t* const         p_ioc_profile,\r
+       IN      const   uint32_t                        vend_id )\r
+{\r
+       p_ioc_profile->vend_id = (cl_hton32(vend_id) << 8);\r
+}\r
+\r
+/****s* IBA Base: Types/ib_svc_entry_t\r
+* NAME\r
+*      ib_svc_entry_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined IO Controller service entry structure (16.3.3.5)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_svc_entry\r
+{\r
+#define        MAX_SVC_ENTRY_NAME_LEN          40\r
+       char                            name[MAX_SVC_ENTRY_NAME_LEN];\r
+\r
+       ib_net64_t                      id;\r
+\r
+}      PACK_SUFFIX ib_svc_entry_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+*      name\r
+*              UTF-8 encoded, null-terminated name of the service.\r
+*\r
+*      id\r
+*              An identifier of the associated Service.\r
+*\r
+* SEE ALSO\r
+* ib_svc_entries_t\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_svc_entries_t\r
+* NAME\r
+*      ib_svc_entries_t\r
+*\r
+* DESCRIPTION\r
+*      IBA defined IO Controller service entry array (16.3.3.5)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_svc_entries\r
+{\r
+#define        SVC_ENTRY_COUNT                 4\r
+       ib_svc_entry_t                  service_entry[SVC_ENTRY_COUNT];\r
+\r
+}      PACK_SUFFIX ib_svc_entries_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+*      service_entry\r
+*              An array of IO controller service entries.\r
+*\r
+* SEE ALSO\r
+* ib_dm_mad_t, ib_svc_entry_t\r
+*********/\r
+\r
+static inline void     OSM_API\r
+ib_dm_get_slot_lo_hi(\r
+       IN      const   ib_net32_t              slot_lo_hi,\r
+       OUT             uint8_t         *const  p_slot,\r
+       OUT             uint8_t         *const  p_lo,\r
+       OUT             uint8_t         *const  p_hi )\r
+{\r
+       ib_net32_t              tmp_slot_lo_hi = CL_NTOH32( slot_lo_hi );\r
+\r
+       if( p_slot )\r
+               *p_slot = (uint8_t)( ( tmp_slot_lo_hi >> 16 ) & 0x0f );\r
+\r
+       if( p_hi )\r
+               *p_hi   = (uint8_t)( ( tmp_slot_lo_hi >> 8 ) & 0xff );\r
+\r
+       if( p_lo )\r
+               *p_lo   = (uint8_t)( ( tmp_slot_lo_hi >> 0 ) & 0xff );\r
+}\r
+\r
+/*\r
+ *     IBA defined information describing an I/O controller\r
+ */\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_ioc_info\r
+{\r
+       ib_net64_t                              module_guid;\r
+       ib_net64_t                              iou_guid;\r
+       ib_ioc_profile_t                        ioc_profile;\r
+       ib_net64_t                              access_key;\r
+       uint16_t                                initiators_conf;\r
+       uint8_t                                 resv[38];\r
+\r
+}      PACK_SUFFIX ib_ioc_info_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+/*\r
+ * Defines known Communication management class versions\r
+ */\r
+#define IB_MCLASS_CM_VER_2                             2\r
+#define IB_MCLASS_CM_VER_1                             1\r
+\r
+/*\r
+ *     Defines the size of user available data in communication management MADs\r
+ */\r
+#define IB_REQ_CM_RDMA_PDATA_SIZE                      56\r
+#define IB_REQ_PDATA_SIZE_VER2                         92\r
+#define IB_MRA_PDATA_SIZE_VER2                         222\r
+#define IB_REJ_PDATA_SIZE_VER2                         148\r
+#define IB_REP_PDATA_SIZE_VER2                         196\r
+#define IB_RTU_PDATA_SIZE_VER2                         224\r
+#define IB_LAP_PDATA_SIZE_VER2                         168\r
+#define IB_APR_PDATA_SIZE_VER2                         148\r
+#define IB_DREQ_PDATA_SIZE_VER2                                220\r
+#define IB_DREP_PDATA_SIZE_VER2                                224\r
+#define IB_SIDR_REQ_PDATA_SIZE_VER2                    216\r
+#define IB_SIDR_REP_PDATA_SIZE_VER2                    136\r
+\r
+#define IB_REQ_PDATA_SIZE_VER1                         92\r
+#define IB_MRA_PDATA_SIZE_VER1                         222\r
+#define IB_REJ_PDATA_SIZE_VER1                         148\r
+#define IB_REP_PDATA_SIZE_VER1                         204\r
+#define IB_RTU_PDATA_SIZE_VER1                         224\r
+#define IB_LAP_PDATA_SIZE_VER1                         168\r
+#define IB_APR_PDATA_SIZE_VER1                         151\r
+#define IB_DREQ_PDATA_SIZE_VER1                                220\r
+#define IB_DREP_PDATA_SIZE_VER1                                224\r
+#define IB_SIDR_REQ_PDATA_SIZE_VER1                    216\r
+#define IB_SIDR_REP_PDATA_SIZE_VER1                    140\r
+\r
+#define IB_ARI_SIZE                                    72              // redefine\r
+#define IB_APR_INFO_SIZE                               72\r
+\r
+/****d* Access Layer/ib_rej_status_t\r
+* NAME\r
+*      ib_rej_status_t\r
+*\r
+* DESCRIPTION\r
+*      Rejection reasons.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef        ib_net16_t                                      ib_rej_status_t;\r
+/*\r
+* SEE ALSO\r
+*      ib_cm_rej, ib_cm_rej_rec_t\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_REJ_INSUF_QP                                        CL_HTON16(1)\r
+#define IB_REJ_INSUF_EEC                               CL_HTON16(2)\r
+#define IB_REJ_INSUF_RESOURCES                         CL_HTON16(3)\r
+#define IB_REJ_TIMEOUT                                 CL_HTON16(4)\r
+#define IB_REJ_UNSUPPORTED                             CL_HTON16(5)\r
+#define IB_REJ_INVALID_COMM_ID                         CL_HTON16(6)\r
+#define IB_REJ_INVALID_COMM_INSTANCE                   CL_HTON16(7)\r
+#define IB_REJ_INVALID_SID                             CL_HTON16(8)\r
+#define IB_REJ_INVALID_XPORT                           CL_HTON16(9)\r
+#define IB_REJ_STALE_CONN                              CL_HTON16(10)\r
+#define IB_REJ_RDC_NOT_EXIST                           CL_HTON16(11)\r
+#define IB_REJ_INVALID_GID                             CL_HTON16(12)\r
+#define IB_REJ_INVALID_LID                             CL_HTON16(13)\r
+#define IB_REJ_INVALID_SL                              CL_HTON16(14)\r
+#define IB_REJ_INVALID_TRAFFIC_CLASS                   CL_HTON16(15)\r
+#define IB_REJ_INVALID_HOP_LIMIT                       CL_HTON16(16)\r
+#define IB_REJ_INVALID_PKT_RATE                                CL_HTON16(17)\r
+#define IB_REJ_INVALID_ALT_GID                         CL_HTON16(18)\r
+#define IB_REJ_INVALID_ALT_LID                         CL_HTON16(19)\r
+#define IB_REJ_INVALID_ALT_SL                          CL_HTON16(20)\r
+#define IB_REJ_INVALID_ALT_TRAFFIC_CLASS               CL_HTON16(21)\r
+#define IB_REJ_INVALID_ALT_HOP_LIMIT                   CL_HTON16(22)\r
+#define IB_REJ_INVALID_ALT_PKT_RATE                    CL_HTON16(23)\r
+#define IB_REJ_PORT_REDIRECT                           CL_HTON16(24)\r
+#define IB_REJ_INVALID_MTU                             CL_HTON16(26)\r
+#define IB_REJ_INSUFFICIENT_RESP_RES                   CL_HTON16(27)\r
+#define IB_REJ_USER_DEFINED                            CL_HTON16(28)\r
+#define IB_REJ_INVALID_RNR_RETRY                       CL_HTON16(29)\r
+#define IB_REJ_DUPLICATE_LOCAL_COMM_ID                 CL_HTON16(30)\r
+#define IB_REJ_INVALID_CLASS_VER                       CL_HTON16(31)\r
+#define IB_REJ_INVALID_FLOW_LBL                                CL_HTON16(32)\r
+#define IB_REJ_INVALID_ALT_FLOW_LBL                    CL_HTON16(33)\r
+\r
+#define IB_REJ_SERVICE_HANDOFF                         CL_HTON16(65535)\r
+/******/\r
+\r
+/****d* Access Layer/ib_apr_status_t\r
+* NAME\r
+*      ib_apr_status_t\r
+*\r
+* DESCRIPTION\r
+*      Automatic path migration status information.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint8_t                                                ib_apr_status_t;\r
+/*\r
+* SEE ALSO\r
+*      ib_cm_apr, ib_cm_apr_rec_t\r
+*\r
+* SOURCE\r
+ */\r
+#define IB_AP_SUCCESS                                  0\r
+#define IB_AP_INVALID_COMM_ID                          1\r
+#define IB_AP_UNSUPPORTED                              2\r
+#define IB_AP_REJECT                                   3\r
+#define IB_AP_REDIRECT                                 4\r
+#define IB_AP_IS_CURRENT                               5\r
+#define IB_AP_INVALID_QPN_EECN                         6\r
+#define IB_AP_INVALID_LID                              7\r
+#define IB_AP_INVALID_GID                              8\r
+#define IB_AP_INVALID_FLOW_LBL                         9\r
+#define IB_AP_INVALID_TCLASS                           10\r
+#define IB_AP_INVALID_HOP_LIMIT                                11\r
+#define IB_AP_INVALID_PKT_RATE                         12\r
+#define IB_AP_INVALID_SL                               13\r
+/******/\r
+\r
+/****d* Access Layer/ib_cm_cap_mask_t\r
+* NAME\r
+*      ib_cm_cap_mask_t\r
+*\r
+* DESCRIPTION\r
+*      Capability mask values in ClassPortInfo.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define IB_CM_RELIABLE_CONN_CAPABLE                    CL_HTON16(9)\r
+#define IB_CM_RELIABLE_DGRM_CAPABLE                    CL_HTON16(10)\r
+#define IB_CM_RDGRM_CAPABLE                            CL_HTON16(11)\r
+#define IB_CM_UNRELIABLE_CONN_CAPABLE                  CL_HTON16(12)\r
+#define IB_CM_SIDR_CAPABLE                             CL_HTON16(13)\r
+/*\r
+* SEE ALSO\r
+*      ib_cm_rep, ib_class_port_info_t\r
+*\r
+* SOURCE\r
+*\r
+*******/\r
+\r
+/*\r
+ *     Service ID resolution status\r
+ */\r
+typedef uint16_t                                       ib_sidr_status_t;\r
+#define IB_SIDR_SUCCESS                                        0\r
+#define IB_SIDR_UNSUPPORTED                            1\r
+#define IB_SIDR_REJECT                                 2\r
+#define IB_SIDR_NO_QP                                  3\r
+#define IB_SIDR_REDIRECT                               4\r
+#define IB_SIDR_UNSUPPORTED_VER                                5\r
+\r
+/*\r
+ *     The following definitions are shared between the Access Layer and VPD\r
+ */\r
+\r
+\r
+typedef struct _ib_ca*                 ib_ca_handle_t ;\r
+typedef struct _ib_pd*                 ib_pd_handle_t ;\r
+typedef struct _ib_rdd*                        ib_rdd_handle_t;\r
+typedef struct _ib_mr*                 ib_mr_handle_t;\r
+typedef struct _ib_mw*                 ib_mw_handle_t;\r
+typedef struct _ib_qp*                 ib_qp_handle_t;\r
+typedef struct _ib_eec*                        ib_eec_handle_t;\r
+typedef struct _ib_cq*                 ib_cq_handle_t;\r
+typedef struct _ib_av*                 ib_av_handle_t;\r
+typedef struct _ib_mcast*              ib_mcast_handle_t;\r
+/* Currently for windows branch, use the extended version of ib special verbs struct \r
+       in order to be compliant with Infinicon ib_types; later we'll change it to support \r
+       OpenSM ib_types.h */\r
+\r
+#ifndef WIN32\r
+/****d* Access Layer/ib_api_status_t\r
+* NAME\r
+*      ib_api_status_t\r
+*\r
+* DESCRIPTION\r
+*      Function return codes indicating the success or failure of an API call.\r
+*      Note that success is indicated by the return value IB_SUCCESS, which\r
+*      is always zero.\r
+*\r
+* NOTES\r
+*      IB_VERBS_PROCESSING_DONE is used by UVP library to terminate a verbs call\r
+*      in the pre-ioctl step itself.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_api_status_t\r
+{\r
+       IB_SUCCESS,\r
+       IB_INSUFFICIENT_RESOURCES,\r
+       IB_INSUFFICIENT_MEMORY,\r
+       IB_INVALID_PARAMETER,\r
+       IB_INVALID_SETTING,\r
+       IB_NOT_FOUND,\r
+       IB_TIMEOUT,\r
+       IB_CANCELED,\r
+       IB_INTERRUPTED,\r
+       IB_INVALID_PERMISSION,\r
+       IB_UNSUPPORTED,\r
+       IB_OVERFLOW,\r
+       IB_MAX_MCAST_QPS_REACHED,\r
+       IB_INVALID_QP_STATE,\r
+       IB_INVALID_EEC_STATE,\r
+       IB_INVALID_APM_STATE,\r
+       IB_INVALID_PORT_STATE,\r
+       IB_INVALID_STATE,\r
+       IB_RESOURCE_BUSY,\r
+       IB_INVALID_PKEY,\r
+       IB_INVALID_LKEY,\r
+       IB_INVALID_RKEY,\r
+       IB_INVALID_MAX_WRS,\r
+       IB_INVALID_MAX_SGE,\r
+       IB_INVALID_CQ_SIZE,\r
+       IB_INVALID_SERVICE_TYPE,\r
+       IB_INVALID_GID,\r
+       IB_INVALID_LID,\r
+       IB_INVALID_GUID,\r
+       IB_INVALID_GUID_MASK,\r
+       IB_INVALID_CA_HANDLE,\r
+       IB_INVALID_AV_HANDLE,\r
+       IB_INVALID_CQ_HANDLE,\r
+       IB_INVALID_EEC_HANDLE,\r
+       IB_INVALID_QP_HANDLE,\r
+       IB_INVALID_PD_HANDLE,\r
+       IB_INVALID_MR_HANDLE,\r
+       IB_INVALID_MW_HANDLE,\r
+       IB_INVALID_RDD_HANDLE,\r
+       IB_INVALID_MCAST_HANDLE,\r
+       IB_INVALID_CALLBACK,\r
+       IB_INVALID_AL_HANDLE,                   /* InfiniBand Access Layer */\r
+       IB_INVALID_HANDLE,                      /* InfiniBand Access Layer */\r
+       IB_ERROR,                               /* InfiniBand Access Layer */\r
+       IB_REMOTE_ERROR,                        /* Infiniband Access Layer */\r
+       IB_VERBS_PROCESSING_DONE,               /* See Notes above         */\r
+       IB_INVALID_WR_TYPE,\r
+       IB_QP_IN_TIMEWAIT,\r
+       IB_EE_IN_TIMEWAIT,\r
+       IB_INVALID_PORT,\r
+       IB_NOT_DONE,\r
+       IB_UNKNOWN_ERROR                        /* ALWAYS LAST ENUM VALUE! */\r
+\r
+}      ib_api_status_t;\r
+/*****/\r
+\r
+OSM_EXPORT const char* ib_error_str[];\r
+\r
+/****f* IBA Base: Types/ib_get_err_str\r
+* NAME\r
+*      ib_get_err_str\r
+*\r
+* DESCRIPTION\r
+*      Returns a string for the specified status value.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline const char*      OSM_API\r
+ib_get_err_str(\r
+       IN              ib_api_status_t                 status )\r
+{\r
+       if( status > IB_UNKNOWN_ERROR )\r
+               status = IB_UNKNOWN_ERROR;\r
+       return( ib_error_str[status] );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      status\r
+*              [in] status value\r
+*\r
+* RETURN VALUES\r
+*      Pointer to the status description string.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****d* Verbs/ib_async_event_t\r
+* NAME\r
+*      ib_async_event_t -- Async event types\r
+*\r
+* DESCRIPTION\r
+*      This type indicates the reason the async callback was called.\r
+*      The context in the ib_event_rec_t indicates the resource context\r
+*      that associated with the callback.  For example, for IB_AE_CQ_ERROR\r
+*      the context provided during the ib_create_cq is returned in the event.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_async_event_t\r
+{\r
+       IB_AE_SQ_ERROR = 1,\r
+       IB_AE_SQ_DRAINED,\r
+       IB_AE_RQ_ERROR,\r
+       IB_AE_CQ_ERROR,\r
+       IB_AE_QP_FATAL,\r
+       IB_AE_QP_COMM,\r
+       IB_AE_QP_APM,\r
+       IB_AE_EEC_FATAL,\r
+       IB_AE_EEC_COMM,\r
+       IB_AE_EEC_APM,\r
+       IB_AE_LOCAL_FATAL,\r
+       IB_AE_PKEY_TRAP,\r
+       IB_AE_QKEY_TRAP,\r
+       IB_AE_MKEY_TRAP,\r
+       IB_AE_PORT_TRAP,\r
+       IB_AE_SYSIMG_GUID_TRAP,\r
+       IB_AE_BUF_OVERRUN,\r
+       IB_AE_LINK_INTEGRITY,\r
+       IB_AE_FLOW_CTRL_ERROR,\r
+       IB_AE_BKEY_TRAP,\r
+       IB_AE_QP_APM_ERROR,\r
+       IB_AE_EEC_APM_ERROR,\r
+       IB_AE_WQ_REQ_ERROR,\r
+       IB_AE_WQ_ACCESS_ERROR,\r
+       IB_AE_PORT_ACTIVE,\r
+       IB_AE_PORT_DOWN,\r
+       IB_AE_UNKNOWN           /* ALWAYS LAST ENUM VALUE */\r
+\r
+}      ib_async_event_t;\r
+/*\r
+* VALUES\r
+*      IB_AE_SQ_ERROR\r
+*              An error occurred when accessing the send queue of the QP or EEC.\r
+*              This event is optional.\r
+*\r
+*      IB_AE_SQ_DRAINED\r
+*              The send queue of the specified QP has completed the outstanding\r
+*              messages in progress when the state change was requested and, if\r
+*              applicable, has received all acknowledgements for those messages.\r
+*\r
+*      IB_AE_RQ_ERROR\r
+*              An error occurred when accessing the receive queue of the QP or EEC.\r
+*              This event is optional.\r
+*\r
+*      IB_AE_CQ_ERROR\r
+*              An error occurred when writing an entry to the CQ.\r
+*\r
+*      IB_AE_QP_FATAL\r
+*              A catastrophic error occurred while accessing or processing the\r
+*              work queue that prevents reporting of completions.\r
+*\r
+*      IB_AE_QP_COMM\r
+*              The first packet has arrived for the receive work queue where the\r
+*              QP is still in the RTR state.\r
+*\r
+*      IB_AE_QP_APM\r
+*              If alternate path migration is supported, this event indicates that\r
+*              the QP connection has migrated to the alternate path.\r
+*\r
+*      IB_AE_EEC_FATAL\r
+*              If reliable datagram service is supported, this event indicates that\r
+*              a catastrophic error occurred while accessing or processing the EEC\r
+*              that prevents reporting of completions.\r
+*\r
+*      IB_AE_EEC_COMM\r
+*              If reliable datagram service is supported, this event indicates that\r
+*              the first packet has arrived for the receive work queue where the\r
+*              EEC is still in the RTR state.\r
+*\r
+*      IB_AE_EEC_APM\r
+*              If reliable datagram service and alternate path migration is supported,\r
+*              this event indicates that the EEC connection has migrated to the\r
+*              alternate path.\r
+*\r
+*      IB_AE_LOCAL_FATAL\r
+*              A catastrophic HCA error occurred which cannot be attributed to any\r
+*              resource; behavior is indeterminate.\r
+*\r
+*      IB_AE_PKEY_TRAP\r
+*              A PKEY violation was detected.  This event is optional.\r
+*\r
+*      IB_AE_QKEY_TRAP\r
+*              A QKEY violation was detected.  This event is optional.\r
+*\r
+*      IB_AE_MKEY_TRAP\r
+*              An MKEY violation was detected.  This event is optional.\r
+*\r
+*      IB_AE_PORT_TRAP\r
+*              A port capability change was detected.  This event is optional.\r
+*\r
+*      IB_AE_SYSIMG_GUID_TRAP\r
+*              If the system image GUID is supported, this event indicates that the\r
+*              system image GUID of this HCA has been changed.  This event is\r
+*              optional.\r
+*\r
+*      IB_AE_BUF_OVERRUN\r
+*              The number of consecutive flow control update periods with at least\r
+*              one overrun error in each period has exceeded the threshold specified\r
+*              in the port info attributes.  This event is optional.\r
+*\r
+*      IB_AE_LINK_INTEGRITY\r
+*              The detection of excessively frequent local physical errors has\r
+*              exceeded the threshold specified in the port info attributes.  This\r
+*              event is optional.\r
+*\r
+*      IB_AE_FLOW_CTRL_ERROR\r
+*              An HCA watchdog timer monitoring the arrival of flow control updates\r
+*              has expired without receiving an update.  This event is optional.\r
+*\r
+*      IB_AE_BKEY_TRAP\r
+*              An BKEY violation was detected.  This event is optional.\r
+*\r
+*      IB_AE_QP_APM_ERROR\r
+*              If alternate path migration is supported, this event indicates that\r
+*              an incoming path migration request to this QP was not accepted.\r
+*\r
+*      IB_AE_EEC_APM_ERROR\r
+*              If reliable datagram service and alternate path migration is supported,\r
+*              this event indicates that an incoming path migration request to this\r
+*              EEC was not accepted.\r
+*\r
+*      IB_AE_WQ_REQ_ERROR\r
+*              An OpCode violation was detected at the responder.\r
+*\r
+*      IB_AE_WQ_ACCESS_ERROR\r
+*              An access violation was detected at the responder.\r
+*\r
+*      IB_AE_PORT_ACTIVE\r
+*              If the port active event is supported, this event is generated\r
+*              when the link becomes active: IB_LINK_ACTIVE.\r
+*\r
+*      IB_AE_PORT_DOWN\r
+*              The link is declared unavailable: IB_LINK_INIT, IB_LINK_ARMED,\r
+*              IB_LINK_DOWN.\r
+*\r
+*      IB_AE_UNKNOWN\r
+*              An unknown error occurred which cannot be attributed to any\r
+*              resource; behavior is indeterminate.\r
+*\r
+*****/\r
+\r
+OSM_EXPORT const char* ib_async_event_str[];\r
+\r
+/****f* IBA Base: Types/ib_get_async_event_str\r
+* NAME\r
+*      ib_get_async_event_str\r
+*\r
+* DESCRIPTION\r
+*      Returns a string for the specified asynchronous event.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline const char*      OSM_API\r
+ib_get_async_event_str(\r
+       IN              ib_async_event_t                event )\r
+{\r
+       if( event > IB_AE_UNKNOWN )\r
+               event = IB_AE_UNKNOWN;\r
+       return( ib_async_event_str[event] );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      event\r
+*              [in] event value\r
+*\r
+* RETURN VALUES\r
+*      Pointer to the asynchronous event description string.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****s* Verbs/ib_event_rec_t\r
+* NAME\r
+*      ib_event_rec_t -- Async event notification record\r
+*\r
+* DESCRIPTION\r
+*      When an async event callback is made, this structure is passed to indicate\r
+*      the type of event, the source of event that caused it, and the context\r
+*      associated with this event.\r
+*\r
+*      context -- Context of the resource that caused the event.\r
+*              -- ca_context if this is a port/adapter event.\r
+*              -- qp_context if the source is a QP event\r
+*              -- cq_context if the source is a CQ event.\r
+*              -- ee_context if the source is an EE event.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_event_rec\r
+{\r
+       void                                    *context;\r
+       ib_async_event_t                        type;\r
+\r
+       /* HCA vendor specific event information. */\r
+       uint64_t                                vendor_specific;\r
+\r
+       /* The following structures are valid only for trap types. */\r
+       union _trap\r
+       {\r
+               struct\r
+               {\r
+                       uint16_t                        lid;\r
+                       ib_net64_t                      port_guid;\r
+                       uint8_t                         port_num;\r
+\r
+                       /*\r
+                        * The following structure is valid only for\r
+                        * P_KEY, Q_KEY, and M_KEY violation traps.\r
+                        */\r
+                       struct\r
+                       {\r
+                               uint8_t                 sl;\r
+                               uint16_t                src_lid;\r
+                               uint16_t                dest_lid;\r
+                               union _key\r
+                               {\r
+                                       uint16_t        pkey;\r
+                                       uint32_t        qkey;\r
+                                       uint64_t        mkey;\r
+                               } key;\r
+                               uint32_t                src_qp;\r
+                               uint32_t                dest_qp;\r
+                               ib_gid_t                src_gid;\r
+                               ib_gid_t                dest_gid;\r
+\r
+                       }       violation;\r
+\r
+               } info;\r
+\r
+               ib_net64_t                              sysimg_guid;\r
+\r
+       }       trap;\r
+\r
+}      ib_event_rec_t;\r
+/*******/\r
+\r
+/****d* Access Layer/ib_atomic_t\r
+* NAME\r
+*      ib_atomic_t\r
+*\r
+* DESCRIPTION\r
+*      Indicates atomicity levels supported by an adapter.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_atomic_t\r
+{\r
+       IB_ATOMIC_NONE,\r
+       IB_ATOMIC_LOCAL,\r
+       IB_ATOMIC_GLOBAL\r
+\r
+}      ib_atomic_t;\r
+/*\r
+* VALUES\r
+*      IB_ATOMIC_NONE\r
+*              Atomic operations not supported.\r
+*\r
+*      IB_ATOMIC_LOCAL\r
+*              Atomic operations guaranteed between QPs of a single CA.\r
+*\r
+*      IB_ATOMIC_GLOBAL\r
+*              Atomic operations are guaranteed between CA and any other entity\r
+*              in the system.\r
+*****/\r
+\r
+/****s* Access Layer/ib_port_cap_t\r
+* NAME\r
+*      ib_port_cap_t\r
+*\r
+* DESCRIPTION\r
+*      Indicates which management agents are currently available on the specified\r
+*      port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_port_cap\r
+{\r
+       boolean_t               cm;\r
+       boolean_t               snmp;\r
+       boolean_t               dev_mgmt;\r
+       boolean_t               vend;\r
+       boolean_t               sm;\r
+       boolean_t               sm_disable;\r
+       boolean_t               qkey_ctr;\r
+       boolean_t               pkey_ctr;\r
+       boolean_t               notice;\r
+       boolean_t               trap;\r
+       boolean_t               apm;\r
+       boolean_t               slmap;\r
+       boolean_t               pkey_nvram;\r
+       boolean_t               mkey_nvram;\r
+       boolean_t               sysguid;\r
+       boolean_t               dr_notice;\r
+       boolean_t               boot_mgmt;\r
+       boolean_t               capm_notice;\r
+       boolean_t               reinit;\r
+       boolean_t               ledinfo;\r
+       boolean_t               port_active;\r
+\r
+}      ib_port_cap_t;\r
+/*****/\r
+\r
+/****d* Access Layer/ib_init_type_t\r
+* NAME\r
+*      ib_init_type_t\r
+*\r
+* DESCRIPTION\r
+*      If supported by the HCA, the type of initialization requested by\r
+*      this port before SM moves it to the active or armed state.  If the\r
+*      SM implements reinitialization, it shall set these bits to indicate\r
+*      the type of initialization performed prior to activating the port.\r
+*      Otherwise, these bits shall be set to 0.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint8_t                                        ib_init_type_t;\r
+#define IB_INIT_TYPE_NO_LOAD                   0x01\r
+#define IB_INIT_TYPE_PRESERVE_CONTENT          0x02\r
+#define IB_INIT_TYPE_PRESERVE_PRESENCE         0x04\r
+#define IB_INIT_TYPE_DO_NOT_RESUSCITATE                0x08\r
+/*****/\r
+\r
+/****s* Access Layer/ib_port_attr_mod_t\r
+* NAME\r
+*      ib_port_attr_mod_t\r
+*\r
+* DESCRIPTION\r
+*      Port attributes that may be modified.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_port_attr_mod\r
+{\r
+       ib_port_cap_t                           cap;\r
+       uint16_t                                pkey_ctr;\r
+       uint16_t                                qkey_ctr;\r
+\r
+       ib_init_type_t                          init_type;\r
+       ib_net64_t                              system_image_guid;\r
+\r
+}      ib_port_attr_mod_t;\r
+/*\r
+* SEE ALSO\r
+*      ib_port_cap_t\r
+*****/\r
+\r
+/****s* Access Layer/ib_port_attr_t\r
+* NAME\r
+*      ib_port_attr_t\r
+*\r
+* DESCRIPTION\r
+*      Information about a port on a given channel adapter.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_port_attr\r
+{\r
+       ib_net64_t                              port_guid;\r
+       uint8_t                                 port_num;\r
+       uint8_t                                 mtu;\r
+       uint64_t                                max_msg_size;\r
+       ib_net16_t                              lid;\r
+       uint8_t                                 lmc;\r
+\r
+       /*\r
+        * LinkWidthSupported as defined in PortInfo.  Required to calculate\r
+        * inter-packet delay (a.k.a. static rate).\r
+        */\r
+       uint8_t                                 link_width_supported;\r
+\r
+       uint16_t                                max_vls;\r
+\r
+       ib_net16_t                              sm_lid;\r
+       uint8_t                                 sm_sl;\r
+       uint8_t                                 link_state;\r
+\r
+       ib_init_type_t                          init_type_reply; /* Optional */\r
+\r
+       /*\r
+        * subnet_timeout:\r
+        * The maximum expected subnet propagation delay to reach any port on\r
+        * the subnet.  This value also determines the rate at which traps can\r
+        * be generated from this node.\r
+        *\r
+        * timeout = 4.096 microseconds * 2^subnet_timeout\r
+        */\r
+       uint8_t                                 subnet_timeout;\r
+\r
+       ib_port_cap_t                           cap;\r
+       uint16_t                                pkey_ctr;\r
+       uint16_t                                qkey_ctr;\r
+\r
+       uint16_t                                num_gids;\r
+       uint16_t                                num_pkeys;\r
+       /*\r
+        * Pointers at the end of the structure to allow doing a simple\r
+        * memory comparison of contents up to the first pointer.\r
+        */\r
+       ib_gid_t                                *p_gid_table;\r
+       ib_net16_t                              *p_pkey_table;\r
+\r
+}      ib_port_attr_t;\r
+/*\r
+* SEE ALSO\r
+*      uint8_t, ib_port_cap_t, ib_link_states_t\r
+*****/\r
+\r
+/****s* Access Layer/ib_ca_attr_t\r
+* NAME\r
+*      ib_ca_attr_t\r
+*\r
+* DESCRIPTION\r
+*      Information about a channel adapter.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_ca_attr\r
+{\r
+       ib_net64_t                              ca_guid;\r
+\r
+       uint32_t                                vend_id;\r
+       uint16_t                                dev_id;\r
+       uint16_t                                revision;\r
+       uint64_t                                fw_ver;\r
+\r
+       /*\r
+        * Total size of the ca attributes in bytes\r
+        */\r
+       uint32_t                                size;\r
+       uint32_t                                max_qps;\r
+       uint32_t                                max_wrs;\r
+\r
+       uint32_t                                max_sges;\r
+       uint32_t                                max_rd_sges;\r
+\r
+       uint32_t                                max_cqs;\r
+       uint32_t                                max_cqes;\r
+\r
+       uint32_t                                max_pds;\r
+\r
+       uint32_t                                init_regions;\r
+       uint64_t                                init_region_size;\r
+\r
+       uint32_t                                init_windows;\r
+       uint64_t                                max_addr_handles;\r
+\r
+       uint32_t                                max_partitions;\r
+\r
+       ib_atomic_t                             atomicity;\r
+\r
+       uint8_t                                 max_qp_resp_res;\r
+       uint8_t                                 max_eec_resp_res;\r
+       uint8_t                                 max_resp_res;\r
+\r
+       uint8_t                                 max_qp_init_depth;\r
+       uint8_t                                 max_eec_init_depth;\r
+\r
+       uint32_t                                max_eecs;\r
+       uint32_t                                max_rdds;\r
+\r
+       uint32_t                                max_ipv6_qps;\r
+       uint32_t                                max_ether_qps;\r
+\r
+       uint32_t                                max_mcast_grps;\r
+       uint32_t                                max_mcast_qps;\r
+       uint32_t                                max_qps_per_mcast_grp;\r
+       uint32_t                                max_fmr;\r
+       uint32_t                                max_map_per_fmr;\r
+\r
+       /*\r
+        * local_ack_delay:\r
+        * Specifies the maximum time interval between the local CA receiving\r
+        * a message and the transmission of the associated ACK or NAK.\r
+        *\r
+        * timeout = 4.096 microseconds * 2^local_ack_delay\r
+        */\r
+       uint8_t                                 local_ack_delay;\r
+\r
+       boolean_t                               bad_pkey_ctr_support;\r
+       boolean_t                               bad_qkey_ctr_support;\r
+       boolean_t                               raw_mcast_support;\r
+       boolean_t                               apm_support;\r
+       boolean_t                               av_port_check;\r
+       boolean_t                               change_primary_port;\r
+       boolean_t                               modify_wr_depth;\r
+       boolean_t                               current_qp_state_support;\r
+       boolean_t                               shutdown_port_capability;\r
+       boolean_t                               init_type_support;\r
+       boolean_t                               port_active_event_support;\r
+       boolean_t                               system_image_guid_support;\r
+       boolean_t                               hw_agents;\r
+\r
+       ib_net64_t                              system_image_guid;\r
+\r
+       uint32_t                                num_page_sizes;\r
+       uint8_t                                 num_ports;\r
+\r
+       uint32_t                                *p_page_size;\r
+       ib_port_attr_t                          *p_port_attr;\r
+\r
+}      ib_ca_attr_t;\r
+/*\r
+* FIELDS\r
+*      ca_guid\r
+*              GUID for this adapter.\r
+*\r
+*      vend_id\r
+*              IEEE vendor ID for this adapter\r
+*\r
+*      dev_id\r
+*              Device ID of this adapter. (typically from PCI device ID)\r
+*\r
+*      revision\r
+*              Revision ID of this adapter\r
+*\r
+*      fw_ver\r
+*              Device Firmware version.\r
+*\r
+*      size\r
+*              Total size in bytes for the HCA attributes.  This size includes total\r
+*              size required for all the variable members of the structure.  If a\r
+*              vendor requires to pass vendor specific fields beyond this structure,\r
+*              the HCA vendor can choose to report a larger size.  If a vendor is\r
+*              reporting extended vendor specific features, they should also provide\r
+*              appropriate access functions to aid with the required interpretation.\r
+*\r
+*      max_qps\r
+*              Maximum number of QP's supported by this HCA.\r
+*\r
+*      max_wrs\r
+*              Maximum number of work requests supported by this HCA.\r
+*\r
+*      max_sges\r
+*              Maximum number of scatter gather elements supported per work request.\r
+*\r
+*      max_rd_sges\r
+*              Maximum number of scatter gather elements supported for READ work\r
+*              requests for a Reliable Datagram QP.  This value must be zero if RD\r
+*              service is not supported.\r
+*\r
+*      max_cqs\r
+*              Maximum number of Completion Queues supported.\r
+*\r
+*      max_cqes\r
+*              Maximum number of CQ elements supported per CQ.\r
+*\r
+*      max_pds\r
+*              Maximum number of protection domains supported.\r
+*\r
+*      init_regions\r
+*              Initial number of memory regions supported.  These are only informative\r
+*              values.  HCA vendors can extended and grow these limits on demand.\r
+*\r
+*      init_region_size\r
+*              Initial limit on the size of the registered memory region.\r
+*\r
+*      init_windows\r
+*              Initial number of window entries supported.\r
+*\r
+*      max_addr_handles\r
+*              Maximum number of address handles supported.\r
+*\r
+*      max_partitions\r
+*              Maximum number of partitions supported.\r
+*\r
+*      atomicity\r
+*              Indicates level of atomic operations supported by this HCA.\r
+*\r
+*      max_qp_resp_res\r
+*      max_eec_resp_res\r
+*              Maximum limit on number of responder resources for incoming RDMA\r
+*              operations, on QPs and EEC's respectively.\r
+*\r
+*      max_resp_res\r
+*              Maximum number of responder resources per HCA, with this HCA used as\r
+*              the target.\r
+*\r
+*      max_qp_init_depth\r
+*      max_eec_init_depth\r
+*              Maximimum initiator depth per QP or EEC for initiating RDMA reads and\r
+*              atomic operations.\r
+*\r
+*      max_eecs\r
+*              Maximimum number of EEC's supported by the HCA.\r
+*\r
+*      max_rdds\r
+*              Maximum number of Reliable datagram domains supported.\r
+*\r
+*      max_ipv6_qps\r
+*      max_ether_qps\r
+*              Maximum number of IPV6 and raw ether QP's supported by this HCA.\r
+*\r
+*      max_mcast_grps\r
+*              Maximum number of multicast groups supported.\r
+*\r
+*      max_mcast_qps\r
+*              Maximum number of QP's that can support multicast operations.\r
+*\r
+*      max_qps_per_mcast_grp\r
+*              Maximum number of multicast QP's per multicast group.\r
+*\r
+*      local_ack_delay\r
+*              Specifies the maximum time interval between the local CA receiving\r
+*              a message and the transmission of the associated ACK or NAK.\r
+*              timeout = 4.096 microseconds * 2^local_ack_delay\r
+*\r
+*      bad_pkey_ctr_support\r
+*      bad_qkey_ctr_support\r
+*              Indicates support for the bad pkey and qkey counters.\r
+*\r
+*      raw_mcast_support\r
+*              Indicates support for raw packet multicast.\r
+*\r
+*      apm_support\r
+*              Indicates support for Automatic Path Migration.\r
+*\r
+*      av_port_check\r
+*              Indicates ability to check port number in address handles.\r
+*\r
+*      change_primary_port\r
+*              Indicates ability to change primary port for a QP or EEC during a\r
+*              SQD->RTS transition.\r
+*\r
+*      modify_wr_depth\r
+*              Indicates ability to modify QP depth during a modify QP operation.\r
+*              Check the verb specification for permitted states.\r
+*\r
+*      current_qp_state_support\r
+*              Indicates ability of the HCA to support the current QP state modifier\r
+*              during a modify QP operation.\r
+*\r
+*      shutdown_port_capability\r
+*              Shutdown port capability support indicator.\r
+*\r
+*      init_type_support\r
+*              Indicates init_type_reply and ability to set init_type is supported.\r
+*\r
+*      port_active_event_support\r
+*              Port active event support indicator.\r
+*\r
+*      system_image_guid_support\r
+*              System image GUID support indicator.\r
+*\r
+*      hw_agents\r
+*              Indicates SMA is implemented in HW.\r
+*\r
+*      system_image_guid\r
+*              Optional system image GUID.  This field is valid only if the\r
+*              system_image_guid_support flag is set.\r
+*\r
+*      num_page_sizes\r
+*              Indicates support for different page sizes supported by the HCA.\r
+*              The variable size array can be obtained from p_page_size.\r
+*\r
+*      num_ports\r
+*              Number of physical ports supported on this HCA.\r
+*\r
+*      p_page_size\r
+*              Array holding different page size supported.\r
+*\r
+*      p_port_attr\r
+*              Array holding port attributes.\r
+*\r
+* NOTES\r
+*      This structure contains the attributes of a channel adapter.  Users must\r
+*      call ib_copy_ca_attr to copy the contents of this structure to a new\r
+*      memory region.\r
+*\r
+* SEE ALSO\r
+*      ib_port_attr_t, ib_atomic_t, ib_copy_ca_attr\r
+*****/\r
+\r
+/****f* Access layer/ib_copy_ca_attr\r
+* NAME\r
+*      ib_copy_ca_attr\r
+*\r
+* DESCRIPTION\r
+*      Copies CA attributes.\r
+*\r
+* SYNOPSIS\r
+*/\r
+ib_ca_attr_t*\r
+ib_copy_ca_attr(\r
+       IN              ib_ca_attr_t* const             p_dest,\r
+       IN      const   ib_ca_attr_t* const             p_src );\r
+/*\r
+* PARAMETERS\r
+*      p_dest\r
+*              Pointer to the buffer that is the destination of the copy.\r
+*\r
+*      p_src\r
+*              Pointer to the CA attributes to copy.\r
+*\r
+* RETURN VALUE\r
+*      Pointer to the copied CA attributes.\r
+*\r
+* NOTES\r
+*      The buffer pointed to by the p_dest parameter must be at least the size\r
+*      specified in the size field of the buffer pointed to by p_src.\r
+*\r
+* SEE ALSO\r
+*      ib_ca_attr_t, ib_dup_ca_attr, ib_free_ca_attr\r
+*****/\r
+\r
+/****s* Access Layer/ib_av_attr_t\r
+* NAME\r
+*      ib_av_attr_t\r
+*\r
+* DESCRIPTION\r
+*      IBA address vector.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_av_attr\r
+{\r
+       uint8_t                                 port_num;\r
+\r
+       uint8_t                                 sl;\r
+       ib_net16_t                              dlid;\r
+\r
+       boolean_t                               grh_valid;\r
+       ib_grh_t                                grh;\r
+       uint8_t                                 static_rate;\r
+       uint8_t                                 path_bits;\r
+\r
+       struct _av_conn\r
+       {\r
+               uint8_t                         path_mtu;\r
+               uint8_t                         local_ack_timeout;\r
+               uint8_t                         seq_err_retry_cnt;\r
+               uint8_t                         rnr_retry_cnt;\r
+\r
+       }       conn;\r
+\r
+}      ib_av_attr_t;\r
+/*\r
+* SEE ALSO\r
+*      ib_gid_t\r
+*****/\r
+\r
+/****d* Access Layer/ib_qp_type_t\r
+* NAME\r
+*      ib_qp_type_t\r
+*\r
+* DESCRIPTION\r
+*      Indicates the type of queue pair being created.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_qp_type\r
+{\r
+       IB_QPT_RELIABLE_CONN    = 0,    /* Matches CM REQ transport type */\r
+       IB_QPT_UNRELIABLE_CONN  = 1,    /* Matches CM REQ transport type */\r
+       IB_QPT_RELIABLE_DGRM    = 2,    /* Matches CM REQ transport type */\r
+       IB_QPT_UNRELIABLE_DGRM,\r
+       IB_QPT_QP0,\r
+       IB_QPT_QP1,\r
+       IB_QPT_RAW_IPV6,\r
+       IB_QPT_RAW_ETHER,\r
+       IB_QPT_MAD,                     /* InfiniBand Access Layer */\r
+       IB_QPT_QP0_ALIAS,               /* InfiniBand Access Layer */\r
+       IB_QPT_QP1_ALIAS                /* InfiniBand Access Layer */\r
+\r
+}      ib_qp_type_t;\r
+/*\r
+* VALUES\r
+*      IB_QPT_RELIABLE_CONN\r
+*              Reliable, connected queue pair.\r
+*\r
+*      IB_QPT_UNRELIABLE_CONN\r
+*              Unreliable, connected queue pair.\r
+*\r
+*      IB_QPT_RELIABLE_DGRM\r
+*              Reliable, datagram queue pair.\r
+*\r
+*      IB_QPT_UNRELIABLE_DGRM\r
+*              Unreliable, datagram queue pair.\r
+*\r
+*      IB_QPT_QP0\r
+*              Queue pair 0.\r
+*\r
+*      IB_QPT_QP1\r
+*              Queue pair 1.\r
+*\r
+*      IB_QPT_RAW_DGRM\r
+*              Raw datagram queue pair.\r
+*\r
+*      IB_QPT_RAW_IPV6\r
+*              Raw IP version 6 queue pair.\r
+*\r
+*      IB_QPT_RAW_ETHER\r
+*              Raw Ethernet queue pair.\r
+*\r
+*      IB_QPT_MAD\r
+*              Unreliable, datagram queue pair that will send and receive management\r
+*              datagrams with assistance from the access layer.\r
+*\r
+*      IB_QPT_QP0_ALIAS\r
+*              Alias to queue pair 0.  Aliased QPs can only be created on an aliased\r
+*              protection domain.\r
+*\r
+*      IB_QPT_QP1_ALIAS\r
+*              Alias to queue pair 1.  Aliased QPs can only be created on an aliased\r
+*              protection domain.\r
+*****/\r
+\r
+/****d* Access Layer/ib_access_t\r
+* NAME\r
+*      ib_access_t\r
+*\r
+* DESCRIPTION\r
+*      Indicates the type of access is permitted on resources such as QPs,\r
+*      memory regions and memory windows.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t                               ib_access_t;\r
+#define IB_AC_RDMA_READ                                0x00000001\r
+#define IB_AC_RDMA_WRITE                       0x00000002\r
+#define IB_AC_ATOMIC                           0x00000004\r
+#define IB_AC_LOCAL_WRITE                      0x00000008\r
+#define IB_AC_MW_BIND                          0x00000010\r
+/*\r
+* NOTES\r
+*      Users may combine access rights using a bit-wise or operation to specify\r
+*      additional access.  For example: IB_AC_RDMA_READ | IB_AC_RDMA_WRITE grants\r
+*      RDMA read and write access.\r
+*****/\r
+\r
+/****d* Access Layer/ib_qp_state_t\r
+* NAME\r
+*      ib_qp_state_t\r
+*\r
+* DESCRIPTION\r
+*      Indicates or sets the state of a queue pair.  The current state of a queue\r
+*      pair is returned through the ib_qp_query call and set via the\r
+*      ib_qp_modify call.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t                               ib_qp_state_t;\r
+#define IB_QPS_RESET                           0x00000001\r
+#define IB_QPS_INIT                            0x00000002\r
+#define IB_QPS_RTR                             0x00000004\r
+#define IB_QPS_RTS                             0x00000008\r
+#define IB_QPS_SQD                             0x00000010\r
+#define IB_QPS_SQD_DRAINING                    0x00000030\r
+#define IB_QPS_SQD_DRAINED                     0x00000050\r
+#define IB_QPS_SQERR                           0x00000080\r
+#define IB_QPS_ERROR                           0x00000100\r
+#define IB_QPS_TIME_WAIT                       0xDEAD0000      /* InfiniBand Access Layer */\r
+/*****/\r
+\r
+/****d* Access Layer/ib_apm_state_t\r
+* NAME\r
+*      ib_apm_state_t\r
+*\r
+* DESCRIPTION\r
+*      The current automatic path migration state of a queue pair\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_apm_state\r
+{\r
+       IB_APM_MIGRATED = 1,\r
+       IB_APM_REARM,\r
+       IB_APM_ARMED\r
+\r
+}      ib_apm_state_t;\r
+/*****/\r
+\r
+/****s* Access Layer/ib_qp_create_t\r
+* NAME\r
+*      ib_qp_create_t\r
+*\r
+* DESCRIPTION\r
+*      Attributes used to initialize a queue pair at creation time.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_qp_create\r
+{\r
+       ib_qp_type_t                    qp_type;\r
+\r
+TO_LONG_PTR(   struct _ib_rdd* ,                       h_rdd) ; \r
+\r
+       uint32_t                        sq_depth;\r
+       uint32_t                        rq_depth;\r
+       uint32_t                        sq_sge;\r
+       uint32_t                        rq_sge;\r
+\r
+TO_LONG_PTR(   ib_cq_handle_t ,                        h_sq_cq) ; \r
+TO_LONG_PTR(   ib_cq_handle_t ,                        h_rq_cq) ; \r
+\r
+       boolean_t                       sq_signaled;\r
+\r
+}      ib_qp_create_t;\r
+/*\r
+* FIELDS\r
+*      type\r
+*              Specifies the type of queue pair to create.\r
+*\r
+*      h_rdd\r
+*              A handle to a reliable datagram domain to associate with the queue\r
+*              pair.  This field is ignored if the queue pair is not a reliable\r
+*              datagram type queue pair.\r
+*\r
+*      sq_depth\r
+*              Indicates the requested maximum number of work requests that may be\r
+*              outstanding on the queue pair's send queue.  This value must be less\r
+*              than or equal to the maximum reported by the channel adapter associated\r
+*              with the queue pair.\r
+*\r
+*      rq_depth\r
+*              Indicates the requested maximum number of work requests that may be\r
+*              outstanding on the queue pair's receive queue.  This value must be less\r
+*              than or equal to the maximum reported by the channel adapter associated\r
+*              with the queue pair.\r
+*\r
+*      sq_sge\r
+*              Indicates the maximum number scatter-gather elements that may be\r
+*              given in a send work request.  This value must be less\r
+*              than or equal to the maximum reported by the channel adapter associated\r
+*              with the queue pair.\r
+*\r
+*      rq_sge\r
+*              Indicates the maximum number scatter-gather elements that may be\r
+*              given in a receive work request.  This value must be less\r
+*              than or equal to the maximum reported by the channel adapter associated\r
+*              with the queue pair.\r
+*\r
+*      h_sq_cq\r
+*              A handle to the completion queue that will be used to report send work\r
+*              request completions.  This handle must be NULL if the type is\r
+*              IB_QPT_MAD, IB_QPT_QP0_ALIAS, or IB_QPT_QP1_ALIAS.\r
+*\r
+*      h_rq_cq\r
+*              A handle to the completion queue that will be used to report receive\r
+*              work request completions.  This handle must be NULL if the type is\r
+*              IB_QPT_MAD, IB_QPT_QP0_ALIAS, or IB_QPT_QP1_ALIAS.\r
+*\r
+*      sq_signaled\r
+*              A flag that is used to indicate whether the queue pair will signal\r
+*              an event upon completion of a send work request.  If set to\r
+*              TRUE, send work requests will always generate a completion\r
+*              event.  If set to FALSE, a completion event will only be\r
+*              generated if the send_opt field of the send work request has the\r
+*              IB_SEND_OPT_SIGNALED flag set.\r
+*\r
+* SEE ALSO\r
+*      ib_qp_type_t, ib_qp_attr_t\r
+*****/\r
+\r
+/****s* Access Layer/ib_qp_attr_t\r
+* NAME\r
+*      ib_qp_attr_t\r
+*\r
+* DESCRIPTION\r
+*      Queue pair attributes returned through ib_query_qp.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_qp_attr\r
+{\r
+TO_LONG_PTR(   struct _ib_pd* ,                                h_pd) ; \r
+       ib_qp_type_t                            qp_type;\r
+       ib_access_t                             access_ctrl;\r
+       uint16_t                                pkey_index;\r
+\r
+       uint32_t                                sq_depth;\r
+       uint32_t                                rq_depth;\r
+       uint32_t                                sq_sge;\r
+       uint32_t                                rq_sge;\r
+       uint8_t                                 init_depth;\r
+       uint8_t                                 resp_res;\r
+\r
+TO_LONG_PTR(   ib_cq_handle_t ,                                h_sq_cq) ; \r
+TO_LONG_PTR(   ib_cq_handle_t ,                                h_rq_cq) ; \r
+TO_LONG_PTR(   struct _ib_rdd* ,                               h_rdd) ; \r
+\r
+       boolean_t                               sq_signaled;\r
+\r
+       ib_qp_state_t                           state;\r
+       ib_net32_t                              num;\r
+       ib_net32_t                              dest_num;\r
+       ib_net32_t                              qkey;\r
+\r
+       ib_net32_t                              sq_psn;\r
+       ib_net32_t                              rq_psn;\r
+\r
+       uint8_t                                 primary_port;\r
+       uint8_t                                 alternate_port;\r
+       ib_av_attr_t                            primary_av;\r
+       ib_av_attr_t                            alternate_av;\r
+       ib_apm_state_t                          apm_state;\r
+\r
+}      ib_qp_attr_t;\r
+/*\r
+* FIELDS\r
+*      h_pd\r
+*              This is a handle to a protection domain associated with the queue\r
+*              pair, or NULL if the queue pair is type IB_QPT_RELIABLE_DGRM.\r
+*\r
+* NOTES\r
+*      Other fields are defined by the Infiniband specification.\r
+*\r
+* SEE ALSO\r
+*      ib_qp_type_t, ib_access_t, ib_qp_state_t, ib_av_attr_t, ib_apm_state_t\r
+*****/\r
+\r
+/****d* Access Layer/ib_qp_opts_t\r
+* NAME\r
+*      ib_qp_opts_t\r
+*\r
+* DESCRIPTION\r
+*      Optional fields supplied in the modify QP operation.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t                               ib_qp_opts_t;\r
+#define IB_MOD_QP_ALTERNATE_AV                 0x00000001\r
+#define IB_MOD_QP_PKEY                         0x00000002\r
+#define IB_MOD_QP_APM_STATE                    0x00000004\r
+#define IB_MOD_QP_PRIMARY_AV                   0x00000008\r
+#define IB_MOD_QP_RNR_NAK_TIMEOUT              0x00000010\r
+#define IB_MOD_QP_RESP_RES                     0x00000020\r
+#define IB_MOD_QP_INIT_DEPTH                   0x00000040\r
+#define IB_MOD_QP_PRIMARY_PORT                 0x00000080\r
+#define IB_MOD_QP_ACCESS_CTRL                  0x00000100\r
+#define IB_MOD_QP_QKEY                         0x00000200\r
+#define IB_MOD_QP_SQ_DEPTH                     0x00000400\r
+#define IB_MOD_QP_RQ_DEPTH                     0x00000800\r
+#define IB_MOD_QP_CURRENT_STATE                        0x00001000\r
+#define IB_MOD_QP_RETRY_CNT                    0x00002000\r
+#define IB_MOD_QP_LOCAL_ACK_TIMEOUT            0x00004000\r
+#define IB_MOD_QP_RNR_RETRY_CNT                        0x00008000\r
+/*\r
+* SEE ALSO\r
+*      ib_qp_mod_t\r
+*****/\r
+\r
+/****s* Access Layer/ib_qp_mod_t\r
+* NAME\r
+*      ib_qp_mod_t\r
+*\r
+* DESCRIPTION\r
+*      Information needed to change the state of a queue pair through the\r
+*      ib_modify_qp call.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_qp_mod\r
+{\r
+       ib_qp_state_t                           req_state;\r
+\r
+       union _qp_state\r
+       {\r
+               struct _qp_reset\r
+               {\r
+                       /*\r
+                        * Time, in milliseconds, that the QP needs to spend in\r
+                        * the time wait state before being reused.\r
+                        */\r
+                       uint32_t                timewait;\r
+\r
+               }       reset;\r
+\r
+               struct _qp_init\r
+               {\r
+                       ib_qp_opts_t            opts;\r
+                       uint8_t                 primary_port;\r
+                       ib_net32_t              qkey;\r
+                       uint16_t                pkey_index;\r
+                       ib_access_t             access_ctrl;\r
+\r
+               }       init;\r
+\r
+               struct _qp_rtr\r
+               {\r
+                       ib_net32_t              rq_psn;\r
+                       ib_net32_t              dest_qp;\r
+                       ib_av_attr_t            primary_av;\r
+                       uint8_t                 resp_res;\r
+\r
+                       ib_qp_opts_t            opts;\r
+                       ib_av_attr_t            alternate_av;\r
+                       ib_net32_t              qkey;\r
+                       uint16_t                pkey_index;\r
+                       ib_access_t             access_ctrl;\r
+                       uint32_t                sq_depth;\r
+                       uint32_t                rq_depth;\r
+                       uint8_t                 rnr_nak_timeout;\r
+\r
+               }       rtr;\r
+\r
+               struct _qp_rts\r
+               {\r
+                       ib_net32_t              sq_psn;\r
+                       uint8_t                 retry_cnt;\r
+                       uint8_t                 rnr_retry_cnt;\r
+                       uint8_t                 rnr_nak_timeout;\r
+                       uint8_t                 local_ack_timeout;\r
+                       uint8_t                 init_depth;\r
+\r
+                       ib_qp_opts_t            opts;\r
+                       ib_qp_state_t           current_state;\r
+                       ib_net32_t              qkey;\r
+                       ib_access_t             access_ctrl;\r
+                       uint8_t                 resp_res;\r
+\r
+                       ib_av_attr_t            primary_av;\r
+                       ib_av_attr_t            alternate_av;\r
+\r
+                       uint32_t                sq_depth;\r
+                       uint32_t                rq_depth;\r
+\r
+                       ib_apm_state_t          apm_state;\r
+                       uint8_t                 primary_port;\r
+                       uint16_t                pkey_index;\r
+\r
+               }       rts;\r
+\r
+               struct _qp_sqd\r
+               {\r
+                       boolean_t               sqd_event;\r
+\r
+               }       sqd;\r
+\r
+       }       state;\r
+\r
+}      ib_qp_mod_t;\r
+/*\r
+* SEE ALSO\r
+*      ib_qp_state_t, ib_access_t, ib_av_attr_t, ib_apm_state_t\r
+*****/\r
+\r
+/****s* Access Layer/ib_eec_attr_t\r
+* NAME\r
+*      ib_eec_attr_t\r
+*\r
+* DESCRIPTION\r
+*      Information about an end-to-end context.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_eec_attr\r
+{\r
+       ib_qp_state_t                           state;\r
+TO_LONG_PTR(   struct _ib_rdd* ,                               h_rdd) ; \r
+       ib_net32_t                              local_eecn;\r
+\r
+       ib_net32_t                              sq_psn;\r
+       ib_net32_t                              rq_psn;\r
+       uint8_t                                 primary_port;\r
+       uint16_t                                pkey_index;\r
+       uint32_t                                resp_res;\r
+       ib_net32_t                              remote_eecn;\r
+       uint32_t                                init_depth;\r
+       uint32_t                                dest_num;       // ??? What is this?\r
+       ib_av_attr_t                            primary_av;\r
+       ib_av_attr_t                            alternate_av;\r
+       ib_apm_state_t                          apm_state;\r
+\r
+}      ib_eec_attr_t;\r
+/*\r
+* SEE ALSO\r
+*      ib_qp_state_t, ib_av_attr_t, ib_apm_state_t\r
+*****/\r
+\r
+/****d* Access Layer/ib_eec_opts_t\r
+* NAME\r
+*      ib_eec_opts_t\r
+*\r
+* DESCRIPTION\r
+*      Optional fields supplied in the modify EEC operation.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t                               ib_eec_opts_t;\r
+#define IB_MOD_EEC_ALTERNATE_AV                        0x00000001\r
+#define IB_MOD_EEC_PKEY                                0x00000002\r
+#define IB_MOD_EEC_APM_STATE                   0x00000004\r
+#define IB_MOD_EEC_PRIMARY_AV                  0x00000008\r
+#define IB_MOD_EEC_RNR                         0x00000010\r
+#define IB_MOD_EEC_RESP_RES                    0x00000020\r
+#define IB_MOD_EEC_OUTSTANDING                 0x00000040\r
+#define IB_MOD_EEC_PRIMARY_PORT                        0x00000080\r
+/*\r
+* NOTES\r
+*\r
+*\r
+*****/\r
+\r
+/****s* Access Layer/ib_eec_mod_t\r
+* NAME\r
+*      ib_eec_mod_t\r
+*\r
+* DESCRIPTION\r
+*      Information needed to change the state of an end-to-end context through\r
+*      the ib_modify_eec function.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_eec_mod\r
+{\r
+       ib_qp_state_t                                   req_state;\r
+\r
+       union _eec_state\r
+       {\r
+               struct _eec_init\r
+               {\r
+                       uint8_t                         primary_port;\r
+                       uint16_t                        pkey_index;\r
+\r
+               }       init;\r
+\r
+               struct _eec_rtr\r
+               {\r
+                       ib_net32_t                      rq_psn;\r
+                       ib_net32_t                      remote_eecn;\r
+                       ib_av_attr_t                    primary_av;\r
+                       uint8_t                         resp_res;\r
+\r
+                       ib_eec_opts_t                   opts;\r
+                       ib_av_attr_t                    alternate_av;\r
+                       uint16_t                        pkey_index;\r
+\r
+               }       rtr;\r
+\r
+               struct _eec_rts\r
+               {\r
+                       ib_net32_t                      sq_psn;\r
+                       uint8_t                         retry_cnt;\r
+                       uint8_t                         rnr_retry_cnt;\r
+                       uint8_t                         local_ack_timeout;\r
+                       uint8_t                         init_depth;\r
+\r
+                       ib_eec_opts_t                   opts;\r
+                       ib_av_attr_t                    alternate_av;\r
+                       ib_apm_state_t                  apm_state;\r
+\r
+                       ib_av_attr_t                    primary_av;\r
+                       uint16_t                        pkey_index;\r
+                       uint8_t                         primary_port;\r
+\r
+               }       rts;\r
+\r
+               struct _eec_sqd\r
+               {\r
+                       boolean_t                       sqd_event;\r
+\r
+               }       sqd;\r
+\r
+       }       state;\r
+\r
+}      ib_eec_mod_t;\r
+/*\r
+* SEE ALSO\r
+*      ib_qp_state_t, ib_av_attr_t, ib_apm_state_t\r
+*****/\r
+\r
+/****d* Access Layer/ib_wr_type_t\r
+* NAME\r
+*      ib_wr_type_t\r
+*\r
+* DESCRIPTION\r
+*      Identifies the type of work request posted to a queue pair.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_wr_type_t\r
+{\r
+       WR_SEND = 1,\r
+       WR_RDMA_WRITE,\r
+       WR_RDMA_READ,\r
+       WR_COMPARE_SWAP,\r
+       WR_FETCH_ADD\r
+\r
+}      ib_wr_type_t;\r
+/*****/\r
+\r
+/****s* Access Layer/ib_local_ds_t\r
+* NAME\r
+*      ib_local_ds_t\r
+*\r
+* DESCRIPTION\r
+*      Local data segment information referenced by send and receive work\r
+*      requests.  This is used to specify local data buffers used as part of a\r
+*      work request.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_local_ds\r
+{\r
+       void                                    *vaddr;\r
+       uint32_t                                length;\r
+       uint32_t                                lkey;\r
+\r
+}      ib_local_ds_t;\r
+/*****/\r
+\r
+/****d* Access Layer/ib_send_opt_t\r
+* NAME\r
+*      ib_send_opt_t\r
+*\r
+* DESCRIPTION\r
+*      Optional flags used when posting send work requests.  These flags\r
+*      indicate specific processing for the send operation.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t                       ib_send_opt_t;\r
+#define IB_SEND_OPT_IMMEDIATE          0x00000001\r
+#define IB_SEND_OPT_FENCE              0x00000002\r
+#define IB_SEND_OPT_SIGNALED           0x00000004\r
+#define IB_SEND_OPT_SOLICITED          0x00000008\r
+#define IB_SEND_OPT_INLINE             0x00000010\r
+#define IB_SEND_OPT_LOCAL              0x00000020\r
+#define IB_SEND_OPT_VEND_MASK          0xFFFF0000\r
+/*\r
+* VALUES\r
+*      The following flags determine the behavior of a work request when\r
+*      posted to the send side.\r
+*\r
+*      IB_SEND_OPT_IMMEDIATE\r
+*              Send immediate data with the given request.\r
+*\r
+*      IB_SEND_OPT_FENCE\r
+*              The operation is fenced.  Complete all pending send operations\r
+*              before processing this request.\r
+*\r
+*      IB_SEND_OPT_SIGNALED\r
+*              If the queue pair is configured for signaled completion, then\r
+*              generate a completion queue entry when this request completes.\r
+*\r
+*      IB_SEND_OPT_SOLICITED\r
+*              Set the solicited bit on the last packet of this request.\r
+*\r
+*      IB_SEND_OPT_INLINE\r
+*              Indicates that the requested send data should be copied into a VPD\r
+*              owned data buffer.  This flag permits the user to issue send operations\r
+*              without first needing to register the buffer(s) associated with the\r
+*              send operation.  Verb providers that support this operation may place\r
+*              vendor specific restrictions on the size of send operation that may\r
+*              be performed as inline.\r
+*\r
+*\r
+*  IB_SEND_OPT_LOCAL\r
+*     Indicates that a sent MAD request should be given to the local VPD for\r
+*     processing.  MADs sent using this option are not placed on the wire.\r
+*     This send option is only valid for MAD send operations.\r
+*\r
+*\r
+*      IB_SEND_OPT_VEND_MASK\r
+*              This mask indicates bits reserved in the send options that may be used\r
+*              by the verbs provider to indicate vendor specific options.  Bits set\r
+*              in this area of the send options are ignored by the Access Layer, but\r
+*              may have specific meaning to the underlying VPD.\r
+*\r
+*****/\r
+\r
+/****s* Access Layer/ib_send_wr_t\r
+* NAME\r
+*      ib_send_wr_t\r
+*\r
+* DESCRIPTION\r
+*      Information used to submit a work request to the send queue of a queue\r
+*      pair.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_send_wr\r
+{\r
+       struct _ib_send_wr                      *p_next;\r
+       uint64_t                                wr_id;\r
+       ib_wr_type_t                            wr_type;\r
+       ib_send_opt_t                           send_opt;\r
+       uint32_t                                num_ds;\r
+       ib_local_ds_t                           *ds_array;\r
+       ib_net32_t                              immediate_data;\r
+\r
+       union _send_dgrm\r
+       {\r
+               struct _send_ud\r
+               {\r
+                       ib_net32_t              remote_qp;\r
+                       ib_net32_t              remote_qkey;\r
+TO_LONG_PTR(                   ib_av_handle_t ,                h_av) ; \r
+\r
+               }       ud;\r
+\r
+               struct _send_rd\r
+               {\r
+                       ib_net32_t              remote_qp;\r
+                       ib_net32_t              remote_qkey;\r
+                       ib_net32_t              eecn;\r
+\r
+               }       rd;\r
+\r
+               struct _send_raw_ether\r
+               {\r
+                       ib_net16_t              dest_lid;\r
+                       uint8_t                 path_bits;\r
+                       uint8_t                 sl;\r
+                       uint8_t                 max_static_rate;\r
+                       ib_net16_t              ether_type;\r
+\r
+               }       raw_ether;\r
+\r
+               struct _send_raw_ipv6\r
+               {\r
+                       ib_net16_t              dest_lid;\r
+                       uint8_t                 path_bits;\r
+                       uint8_t                 sl;\r
+                       uint8_t                 max_static_rate;\r
+\r
+               }       raw_ipv6;\r
+\r
+       }       dgrm;\r
+\r
+       struct _send_remote_ops\r
+       {\r
+               uint64_t                        vaddr;\r
+               uint32_t                        rkey;\r
+\r
+               ib_net64_t                      atomic1;\r
+               ib_net64_t                      atomic2;\r
+\r
+       }       remote_ops;\r
+\r
+}      ib_send_wr_t;\r
+/*\r
+* FIELDS\r
+*      p_next\r
+*              A pointer used to chain work requests together.  This permits multiple\r
+*              work requests to be posted to a queue pair through a single function\r
+*              call.  This value is set to NULL to mark the end of the chain.\r
+*\r
+*      wr_id\r
+*              A 64-bit work request identifier that is returned to the consumer\r
+*              as part of the work completion.\r
+*\r
+*      wr_type\r
+*              The type of work request being submitted to the send queue.\r
+*\r
+*      send_opt\r
+*              Optional send control parameters.\r
+*\r
+*      num_ds\r
+*              Number of local data segments specified by this work request.\r
+*\r
+*      ds_array\r
+*              A reference to an array of local data segments used by the send\r
+*              operation.\r
+*\r
+*      immediate_data\r
+*              32-bit field sent as part of a message send or RDMA write operation.\r
+*              This field is only valid if the send_opt flag IB_SEND_OPT_IMMEDIATE\r
+*              has been set.\r
+*\r
+*      dgrm.ud.remote_qp\r
+*              Identifies the destination queue pair of an unreliable datagram send\r
+*              operation.\r
+*\r
+*      dgrm.ud.remote_qkey\r
+*              The qkey for the destination queue pair.\r
+*\r
+*      dgrm.ud.h_av\r
+*              An address vector that specifies the path information used to route\r
+*              the outbound datagram to the destination queue pair.\r
+*\r
+*      dgrm.rd.remote_qp\r
+*              Identifies the destination queue pair of a reliable datagram send\r
+*              operation.\r
+*\r
+*      dgrm.rd.remote_qkey\r
+*              The qkey for the destination queue pair.\r
+*\r
+*      dgrm.rd.eecn\r
+*              The local end-to-end context number to use with the reliable datagram\r
+*              send operation.\r
+*\r
+*      dgrm.raw_ether.dest_lid\r
+*              The destination LID that will receive this raw ether send.\r
+*\r
+*      dgrm.raw_ether.path_bits\r
+*              path bits...\r
+*\r
+*      dgrm.raw_ether.sl\r
+*              service level...\r
+*\r
+*      dgrm.raw_ether.max_static_rate\r
+*              static rate...\r
+*\r
+*      dgrm.raw_ether.ether_type\r
+*              ether type...\r
+*\r
+*      dgrm.raw_ipv6.dest_lid\r
+*              The destination LID that will receive this raw ether send.\r
+*\r
+*      dgrm.raw_ipv6.path_bits\r
+*              path bits...\r
+*\r
+*      dgrm.raw_ipv6.sl\r
+*              service level...\r
+*\r
+*      dgrm.raw_ipv6.max_static_rate\r
+*              static rate...\r
+*\r
+*      remote_ops.vaddr\r
+*              The registered virtual memory address of the remote memory to access\r
+*              with an RDMA or atomic operation.\r
+*\r
+*      remote_ops.rkey\r
+*              The rkey associated with the specified remote vaddr. This data must\r
+*              be presented exactly as obtained from the remote node. No swapping\r
+*              of data must be performed.\r
+*\r
+*      atomic1\r
+*              The first operand for an atomic operation.\r
+*\r
+*      atomic2\r
+*              The second operand for an atomic operation.\r
+*\r
+* NOTES\r
+*      The format of data sent over the fabric is user-defined and is considered\r
+*      opaque to the access layer.  The sole exception to this are MADs posted\r
+*      to a MAD QP service.  MADs are expected to match the format defined by\r
+*      the Infiniband specification and must be in network-byte order when posted\r
+*      to the MAD QP service.\r
+*\r
+* SEE ALSO\r
+*      ib_wr_type_t, ib_local_ds_t, ib_send_opt_t\r
+*****/\r
+\r
+/****s* Access Layer/ib_recv_wr_t\r
+* NAME\r
+*      ib_recv_wr_t\r
+*\r
+* DESCRIPTION\r
+*      Information used to submit a work request to the receive queue of a queue\r
+*      pair.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_recv_wr\r
+{\r
+       struct _ib_recv_wr              *p_next;\r
+       uint64_t                        wr_id;\r
+       uint32_t                        num_ds;\r
+       ib_local_ds_t                   *ds_array;\r
+}      ib_recv_wr_t;\r
+/*\r
+* FIELDS\r
+*      p_next\r
+*              A pointer used to chain work requests together.  This permits multiple\r
+*              work requests to be posted to a queue pair through a single function\r
+*              call.  This value is set to NULL to mark the end of the chain.\r
+*\r
+*      wr_id\r
+*              A 64-bit work request identifier that is returned to the consumer\r
+*              as part of the work completion.\r
+*\r
+*      num_ds\r
+*              Number of local data segments specified by this work request.\r
+*\r
+*      ds_array\r
+*              A reference to an array of local data segments used by the send\r
+*              operation.\r
+*\r
+* SEE ALSO\r
+*      ib_local_ds_t\r
+*****/\r
+\r
+/****s* Access Layer/ib_bind_wr_t\r
+* NAME\r
+*      ib_bind_wr_t\r
+*\r
+* DESCRIPTION\r
+*      Information used to submit a memory window bind work request to the send\r
+*      queue of a queue pair.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_bind_wr\r
+{\r
+       uint64_t                                wr_id;\r
+       ib_send_opt_t                           send_opt;\r
+\r
+TO_LONG_PTR(   struct _ib_mr* ,                                h_mr) ; \r
+       ib_access_t                             access_ctrl;\r
+       uint32_t                                current_rkey;\r
+\r
+       ib_local_ds_t                           local_ds;\r
+\r
+}      ib_bind_wr_t;\r
+/*\r
+* FIELDS\r
+*      wr_id\r
+*              A 64-bit work request identifier that is returned to the consumer\r
+*              as part of the work completion.\r
+*\r
+*      send_opt\r
+*              Optional send control parameters.\r
+*\r
+*      h_mr\r
+*              Handle to the memory region to which this window is being bound.\r
+*\r
+*      access_ctrl\r
+*              Access rights for this memory window.\r
+*\r
+*      current_rkey\r
+*              The current rkey assigned to this window for remote access.\r
+*\r
+*      local_ds\r
+*              A reference to a local data segment used by the bind operation.\r
+*\r
+* SEE ALSO\r
+*      ib_send_opt_t, ib_access_t, ib_local_ds_t\r
+*****/\r
+\r
+/****d* Access Layer/ib_wc_status_t\r
+* NAME\r
+*      ib_wc_status_t\r
+*\r
+* DESCRIPTION\r
+*      Indicates the status of a completed work request.  These VALUES are\r
+*      returned to the user when retrieving completions.  Note that success is\r
+*      identified as IB_WCS_SUCCESS, which is always zero.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_wc_status_t\r
+{\r
+       IB_WCS_SUCCESS,\r
+       IB_WCS_LOCAL_LEN_ERR,\r
+       IB_WCS_LOCAL_OP_ERR,\r
+       IB_WCS_LOCAL_PROTECTION_ERR,\r
+       IB_WCS_WR_FLUSHED_ERR,\r
+       IB_WCS_MEM_WINDOW_BIND_ERR,\r
+       IB_WCS_REM_ACCESS_ERR,\r
+       IB_WCS_REM_OP_ERR,\r
+       IB_WCS_RNR_RETRY_ERR,\r
+       IB_WCS_TIMEOUT_RETRY_ERR,\r
+       IB_WCS_REM_INVALID_REQ_ERR,\r
+       IB_WCS_BAD_RESP_ERR,\r
+       IB_WCS_LOCAL_ACCESS_ERR,\r
+       IB_WCS_GENERAL_ERR,\r
+       IB_WCS_UNMATCHED_RESPONSE,                      /* InfiniBand Access Layer */\r
+       IB_WCS_CANCELED,                                        /* InfiniBand Access Layer */\r
+       IB_WCS_REM_ABORT_ERR,\r
+       IB_WCS_UNKNOWN                                          /* Must be last. */\r
+\r
+}      ib_wc_status_t;\r
+/*\r
+* VALUES\r
+*      IB_WCS_SUCCESS\r
+*              Work request completed successfully.\r
+*\r
+*      IB_WCS_MAD\r
+*              The completed work request was associated with a managmenet datagram\r
+*              that requires post processing.  The MAD will be returned to the user\r
+*              through a callback once all post processing has completed.\r
+*\r
+*      IB_WCS_LOCAL_LEN_ERR\r
+*              Generated for a work request posted to the send queue when the\r
+*              total of the data segment lengths exceeds the message length of the\r
+*              channel.  Generated for a work request posted to the receive queue when\r
+*              the total of the data segment lengths is too small for a\r
+*              valid incoming message.\r
+*\r
+*      IB_WCS_LOCAL_OP_ERR\r
+*              An internal QP consistency error was generated while processing this\r
+*              work request.  This may indicate that the QP was in an incorrect state\r
+*              for the requested operation.\r
+*\r
+*      IB_WCS_LOCAL_EEC_OP_ERR\r
+*              An internal EEC consistency error was generated while processing\r
+*              this work request.  This may indicate that the EEC was in an incorrect\r
+*              state for the requested operation.\r
+*\r
+*      IB_WCS_LOCAL_PROTECTION_ERR\r
+*              The data segments of the locally posted work request did not refer to\r
+*              a valid memory region.  The memory may not have been properly\r
+*              registered for the requested operation.\r
+*\r
+*      IB_WCS_WR_FLUSHED_ERR\r
+*              The work request was flushed from the QP before being completed.\r
+*\r
+*      IB_WCS_MEM_WINDOW_BIND_ERR\r
+*              A memory window bind operation failed due to insufficient access\r
+*              rights.\r
+*\r
+*      IB_WCS_REM_ACCESS_ERR,\r
+*              A protection error was detected at the remote node for a RDMA or atomic\r
+*              operation.\r
+*\r
+*      IB_WCS_REM_OP_ERR,\r
+*              The operation could not be successfully completed at the remote node.\r
+*              This may indicate that the remote QP was in an invalid state or\r
+*              contained an invalid work request.\r
+*\r
+*      IB_WCS_RNR_RETRY_ERR,\r
+*              The RNR retry count was exceeded while trying to send this message.\r
+*\r
+*      IB_WCS_TIMEOUT_RETRY_ERR\r
+*              The local transport timeout counter expired while trying to send this\r
+*              message.\r
+*\r
+*      IB_WCS_REM_INVALID_REQ_ERR,\r
+*              The remote node detected an invalid message on the channel.  This error\r
+*              is usually a result of one of the following:\r
+*                      - The operation was not supported on receive queue.\r
+*                      - There was insufficient buffers to receive a new RDMA request.\r
+*                      - There was insufficient buffers to receive a new atomic operation.\r
+*                      - An RDMA request was larger than 2^31 bytes.\r
+*\r
+*      IB_WCS_REM_INVALID_RD_REQ_ERR,\r
+*              Responder detected an invalid RD message.  This may be the result of an\r
+*              invalid qkey or an RDD mismatch.\r
+*\r
+*      IB_WCS_REM_ABORT_ERR,\r
+*              The operation was aborted (e.g., For UD QPs associated with an SRQ, \r
+*              the responder aborted the operation).\r
+*\r
+*      IB_WCS_UNMATCHED_RESPONSE\r
+*              A response MAD was received for which there was no matching send.  The\r
+*              send operation may have been canceled by the user or may have timed\r
+*              out.\r
+*\r
+*      IB_WCS_CANCELED\r
+*              The completed work request was canceled by the user.\r
+*****/\r
+\r
+OSM_EXPORT const char* ib_wc_status_str[];\r
+\r
+/****f* IBA Base: Types/ib_get_wc_status_str\r
+* NAME\r
+*      ib_get_wc_status_str\r
+*\r
+* DESCRIPTION\r
+*      Returns a string for the specified work completion status.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline const char*      OSM_API\r
+ib_get_wc_status_str(\r
+       IN              ib_wc_status_t                  wc_status )\r
+{\r
+       if( wc_status > IB_WCS_UNKNOWN )\r
+               wc_status = IB_WCS_UNKNOWN;\r
+       return( ib_wc_status_str[wc_status] );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      wc_status\r
+*              [in] work completion status value\r
+*\r
+* RETURN VALUES\r
+*      Pointer to the work completion status description string.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****d* Access Layer/ib_wc_type_t\r
+* NAME\r
+*      ib_wc_type_t\r
+*\r
+* DESCRIPTION\r
+*      Indicates the type of work completion.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_wc_type_t\r
+{\r
+       IB_WC_SEND,\r
+       IB_WC_RDMA_WRITE,\r
+       IB_WC_RECV,\r
+       IB_WC_RDMA_READ,\r
+       IB_WC_MW_BIND,\r
+       IB_WC_FETCH_ADD,\r
+       IB_WC_COMPARE_SWAP,\r
+       IB_WC_RECV_RDMA_WRITE\r
+\r
+}      ib_wc_type_t;\r
+/*****/\r
+\r
+/****d* Access Layer/ib_recv_opt_t\r
+* NAME\r
+*      ib_recv_opt_t\r
+*\r
+* DESCRIPTION\r
+*      Indicates optional fields valid in a receive work completion.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t                       ib_recv_opt_t;\r
+#define        IB_RECV_OPT_IMMEDIATE           0x00000001\r
+#define IB_RECV_OPT_FORWARD            0x00000002\r
+#define IB_RECV_OPT_GRH_VALID          0x00000004\r
+#define IB_RECV_OPT_VEND_MASK          0xFFFF0000\r
+/*\r
+* VALUES\r
+*      IB_RECV_OPT_IMMEDIATE\r
+*              Indicates that immediate data is valid for this work completion.\r
+*\r
+*      IB_RECV_OPT_FORWARD\r
+*              Indicates that the received trap should be forwarded to the SM.\r
+*\r
+*      IB_RECV_OPT_GRH_VALID\r
+*              Indicates presence of the global route header. When set, the first\r
+*              40 bytes received are the GRH.\r
+*\r
+*      IB_RECV_OPT_VEND_MASK\r
+*              This mask indicates bits reserved in the receive options that may be\r
+*              used by the verbs provider to indicate vendor specific options.  Bits\r
+*              set in this area of the receive options are ignored by the Access Layer,\r
+*              but may have specific meaning to the underlying VPD.\r
+*****/\r
+\r
+/****s* Access Layer/ib_wc_t\r
+* NAME\r
+*      ib_wc_t\r
+*\r
+* DESCRIPTION\r
+*      Work completion information.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_wc\r
+{\r
+       struct _ib_wc                   *p_next;\r
+       uint64_t                        wr_id;\r
+       ib_wc_type_t                    wc_type;\r
+\r
+       uint32_t                        length;\r
+       ib_wc_status_t                  status;\r
+       uint64_t                        vendor_specific;\r
+\r
+       union _wc_recv\r
+       {\r
+               struct _wc_conn\r
+               {\r
+                       ib_recv_opt_t   recv_opt;\r
+                       ib_net32_t      immediate_data;\r
+\r
+               }       conn;\r
+\r
+               struct _wc_ud\r
+               {\r
+                       ib_recv_opt_t   recv_opt;\r
+                       ib_net32_t      immediate_data;\r
+                       ib_net32_t      remote_qp;\r
+                       uint16_t        pkey_index;\r
+                       ib_net16_t      remote_lid;\r
+                       uint8_t         remote_sl;\r
+                       uint8_t         path_bits;\r
+\r
+               }       ud;\r
+\r
+               struct _wc_rd\r
+               {\r
+                       ib_net32_t      remote_eecn;\r
+                       ib_net32_t      remote_qp;\r
+                       ib_net16_t      remote_lid;\r
+                       uint8_t         remote_sl;\r
+                       uint32_t        free_cnt;\r
+\r
+               }       rd;\r
+\r
+               struct _wc_raw_ipv6\r
+               {\r
+                       ib_net16_t      remote_lid;\r
+                       uint8_t         remote_sl;\r
+                       uint8_t         path_bits;\r
+\r
+               }       raw_ipv6;\r
+\r
+               struct _wc_raw_ether\r
+               {\r
+                       ib_net16_t      remote_lid;\r
+                       uint8_t         remote_sl;\r
+                       uint8_t         path_bits;\r
+                       ib_net16_t      ether_type;\r
+\r
+               }       raw_ether;\r
+\r
+       }       recv;\r
+\r
+}      ib_wc_t;\r
+/*\r
+* FIELDS\r
+*      p_next\r
+*              A pointer used to chain work completions.  This permits multiple\r
+*              work completions to be retrieved from a completion queue through a\r
+*              single function call.  This value is set to NULL to mark the end of\r
+*              the chain.\r
+*\r
+*      wr_id\r
+*              The 64-bit work request identifier that was specified when posting the\r
+*              work request.\r
+*\r
+*      wc_type\r
+*              Indicates the type of work completion.\r
+*\r
+*\r
+*      length\r
+*              The total length of the data sent or received with the work request.\r
+*\r
+*      status\r
+*              The result of the work request.\r
+*\r
+*      vendor_specific\r
+*              HCA vendor specific information returned as part of the completion.\r
+*\r
+*      recv.conn.recv_opt\r
+*              Indicates optional fields valid as part of a work request that\r
+*              completed on a connected (reliable or unreliable) queue pair.\r
+*\r
+*      recv.conn.immediate_data\r
+*              32-bit field received as part of an inbound message on a connected\r
+*              queue pair.  This field is only valid if the recv_opt flag\r
+*              IB_RECV_OPT_IMMEDIATE has been set.\r
+*\r
+*      recv.ud.recv_opt\r
+*              Indicates optional fields valid as part of a work request that\r
+*              completed on an unreliable datagram queue pair.\r
+*\r
+*      recv.ud.immediate_data\r
+*              32-bit field received as part of an inbound message on a unreliable\r
+*              datagram queue pair.  This field is only valid if the recv_opt flag\r
+*              IB_RECV_OPT_IMMEDIATE has been set.\r
+*\r
+*      recv.ud.remote_qp\r
+*              Identifies the source queue pair of a received datagram.\r
+*\r
+*      recv.ud.pkey_index\r
+*              The pkey index for the source queue pair. This is valid only for\r
+*              GSI type QP's.\r
+*\r
+*      recv.ud.remote_lid\r
+*              The source LID of the received datagram.\r
+*\r
+*      recv.ud.remote_sl\r
+*              The service level used by the source of the received datagram.\r
+*\r
+*      recv.ud.path_bits\r
+*              path bits...\r
+*\r
+*      recv.rd.remote_eecn\r
+*              The remote end-to-end context number that sent the received message.\r
+*\r
+*      recv.rd.remote_qp\r
+*              Identifies the source queue pair of a received message.\r
+*\r
+*      recv.rd.remote_lid\r
+*              The source LID of the received message.\r
+*\r
+*      recv.rd.remote_sl\r
+*              The service level used by the source of the received message.\r
+*\r
+*      recv.rd.free_cnt\r
+*              The number of available entries in the completion queue.  Reliable\r
+*              datagrams may complete out of order, so this field may be used to\r
+*              determine the number of additional completions that may occur.\r
+*\r
+*      recv.raw_ipv6.remote_lid\r
+*              The source LID of the received message.\r
+*\r
+*      recv.raw_ipv6.remote_sl\r
+*              The service level used by the source of the received message.\r
+*\r
+*      recv.raw_ipv6.path_bits\r
+*              path bits...\r
+*\r
+*      recv.raw_ether.remote_lid\r
+*              The source LID of the received message.\r
+*\r
+*      recv.raw_ether.remote_sl\r
+*              The service level used by the source of the received message.\r
+*\r
+*      recv.raw_ether.path_bits\r
+*              path bits...\r
+*\r
+*      recv.raw_ether.ether_type\r
+*              ether type...\r
+* NOTES\r
+*      When the work request completes with error, the only values that the\r
+*      consumer can depend on are the wr_id field, and the status of the\r
+*      operation.\r
+*\r
+*      If the consumer is using the same CQ for completions from more than\r
+*      one type of QP (i.e Reliable Connected, Datagram etc), then the consumer\r
+*      must have additional information to decide what fields of the union are\r
+*      valid.\r
+* SEE ALSO\r
+*      ib_wc_type_t, ib_qp_type_t, ib_wc_status_t, ib_recv_opt_t\r
+*****/\r
+\r
+/****s* Access Layer/ib_mr_create_t\r
+* NAME\r
+*      ib_mr_create_t\r
+*\r
+* DESCRIPTION\r
+*      Information required to create a registered memory region.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_mr_create\r
+{\r
+       void                                    *vaddr;\r
+       uint64_t                                length;\r
+       ib_access_t                             access_ctrl;\r
+}      ib_mr_create_t;\r
+/*\r
+* FIELDS\r
+*      vaddr\r
+*              Starting virtual address of the region being registered.\r
+*\r
+*      length\r
+*              Length of the buffer to register.\r
+*\r
+*      access_ctrl\r
+*              Access rights of the registered region.\r
+*\r
+* SEE ALSO\r
+*      ib_access_t\r
+*****/\r
+\r
+/****s* Access Layer/ib_phys_create_t\r
+* NAME\r
+*      ib_phys_create_t\r
+*\r
+* DESCRIPTION\r
+*      Information required to create a physical memory region.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_phys_create\r
+{\r
+       uint64_t                                length;\r
+       uint32_t                                num_bufs;\r
+       uint64_t                                *buf_array;\r
+       uint32_t                                buf_offset;\r
+       uint32_t                                page_size;\r
+       ib_access_t                             access_ctrl;\r
+}      ib_phys_create_t;\r
+/*\r
+*      length\r
+*              The length of the memory region in bytes.\r
+*\r
+*      num_bufs\r
+*              Number of buffers listed in the specified buffer array.\r
+*\r
+*      buf_array\r
+*              An array of physical buffers to be registered as a single memory\r
+*              region.\r
+*\r
+*      buf_offset\r
+*              The offset into the first physical page of the specified memory\r
+*              region to start the virtual address.\r
+*\r
+*      page_size\r
+*              The physical page size of the memory being registered.\r
+*\r
+*      access_ctrl\r
+*              Access rights of the registered region.\r
+*\r
+* SEE ALSO\r
+*      ib_access_t\r
+*****/\r
+\r
+/****s* Access Layer/ib_mr_attr_t\r
+* NAME\r
+*      ib_mr_attr_t\r
+*\r
+* DESCRIPTION\r
+*      Attributes of a registered memory region.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_mr_attr\r
+{\r
+TO_LONG_PTR(   struct _ib_pd* ,                        h_pd) ; \r
+       void                            *local_lb;\r
+       void                            *local_ub;\r
+       void                            *remote_lb;\r
+       void                            *remote_ub;\r
+       ib_access_t                     access_ctrl;\r
+       uint32_t                        lkey;\r
+       uint32_t                        rkey;\r
+}      ib_mr_attr_t;\r
+/*\r
+* DESCRIPTION\r
+*      h_pd\r
+*              Handle to the protection domain for this memory region.\r
+*\r
+*      local_lb\r
+*              The virtual address of the lower bound of protection for local\r
+*              memory access.\r
+*\r
+*      local_ub\r
+*              The virtual address of the upper bound of protection for local\r
+*              memory access.\r
+*\r
+*      remote_lb\r
+*              The virtual address of the lower bound of protection for remote\r
+*              memory access.\r
+*\r
+*      remote_ub\r
+*              The virtual address of the upper bound of protection for remote\r
+*              memory access.\r
+*\r
+*      access_ctrl\r
+*              Access rights for the specified memory region.\r
+*\r
+*      lkey\r
+*              The lkey associated with this memory region.\r
+*\r
+*      rkey\r
+*              The rkey associated with this memory region.\r
+*\r
+* NOTES\r
+*      The remote_lb, remote_ub, and rkey are only valid if remote memory access\r
+*      is enabled for this memory region.\r
+*\r
+* SEE ALSO\r
+*      ib_access_t\r
+*****/\r
+\r
+/****d* Access Layer/ib_ca_mod_t\r
+* NAME\r
+*      ib_ca_mod_t -- Modify port attributes and error counters\r
+*\r
+* DESCRIPTION\r
+*      Specifies modifications to the port attributes of a channel adapter.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t                               ib_ca_mod_t;\r
+#define IB_CA_MOD_IS_CM_SUPPORTED              0x00000001\r
+#define IB_CA_MOD_IS_SNMP_SUPPORTED            0x00000002\r
+#define        IB_CA_MOD_IS_DEV_MGMT_SUPPORTED         0x00000004\r
+#define        IB_CA_MOD_IS_VEND_SUPPORTED             0x00000008\r
+#define        IB_CA_MOD_IS_SM                         0x00000010\r
+#define IB_CA_MOD_IS_SM_DISABLED               0x00000020\r
+#define IB_CA_MOD_QKEY_CTR                     0x00000040\r
+#define IB_CA_MOD_PKEY_CTR                     0x00000080\r
+#define IB_CA_MOD_IS_NOTICE_SUPPORTED          0x00000100\r
+#define IB_CA_MOD_IS_TRAP_SUPPORTED            0x00000200\r
+#define IB_CA_MOD_IS_APM_SUPPORTED             0x00000400\r
+#define IB_CA_MOD_IS_SLMAP_SUPPORTED           0x00000800\r
+#define IB_CA_MOD_IS_PKEY_NVRAM_SUPPORTED      0x00001000\r
+#define IB_CA_MOD_IS_MKEY_NVRAM_SUPPORTED      0x00002000\r
+#define IB_CA_MOD_IS_SYSGUID_SUPPORTED         0x00004000\r
+#define IB_CA_MOD_IS_DR_NOTICE_SUPPORTED       0x00008000\r
+#define IB_CA_MOD_IS_BOOT_MGMT_SUPPORTED       0x00010000\r
+#define IB_CA_MOD_IS_CAPM_NOTICE_SUPPORTED     0x00020000\r
+#define IB_CA_MOD_IS_REINIT_SUPORTED           0x00040000\r
+#define IB_CA_MOD_IS_LEDINFO_SUPPORTED         0x00080000\r
+#define IB_CA_MOD_SHUTDOWN_PORT                        0x00100000\r
+#define IB_CA_MOD_INIT_TYPE_VALUE              0x00200000\r
+#define IB_CA_MOD_SYSTEM_IMAGE_GUID            0x00400000\r
+/*\r
+* VALUES\r
+*      IB_CA_MOD_IS_CM_SUPPORTED\r
+*              Indicates if there is a communication manager accessible through\r
+*              the port.\r
+*\r
+*      IB_CA_MOD_IS_SNMP_SUPPORTED\r
+*              Indicates if there is an SNMP agent accessible through the port.\r
+*\r
+*      IB_CA_MOD_IS_DEV_MGMT_SUPPORTED\r
+*              Indicates if there is a device management agent accessible\r
+*              through the port.\r
+*\r
+*      IB_CA_MOD_IS_VEND_SUPPORTED\r
+*              Indicates if there is a vendor supported agent accessible\r
+*              through the port.\r
+*\r
+*      IB_CA_MOD_IS_SM\r
+*              Indicates if there is a subnet manager accessible through\r
+*              the port.\r
+*\r
+*      IB_CA_MOD_IS_SM_DISABLED\r
+*              Indicates if the port has been disabled for configuration by the\r
+*              subnet manager.\r
+*\r
+*      IB_CA_MOD_QKEY_CTR\r
+*              Used to reset the qkey violation counter associated with the\r
+*              port.\r
+*\r
+*      IB_CA_MOD_PKEY_CTR\r
+*              Used to reset the pkey violation counter associated with the\r
+*              port.\r
+*\r
+*      IB_CA_MOD_IS_NOTICE_SUPPORTED\r
+*              Indicates that this CA supports ability to generate Notices for\r
+*              Port State changes. (only applicable to switches)\r
+*\r
+*      IB_CA_MOD_IS_TRAP_SUPPORTED\r
+*              Indicates that this management port supports ability to generate\r
+*              trap messages. (only applicable to switches)\r
+*\r
+*      IB_CA_MOD_IS_APM_SUPPORTED\r
+*              Indicates that this port is capable of performing Automatic\r
+*              Path Migration.\r
+*\r
+*      IB_CA_MOD_IS_SLMAP_SUPPORTED\r
+*              Indicates this port supports SLMAP capability.\r
+*\r
+*      IB_CA_MOD_IS_PKEY_NVRAM_SUPPORTED\r
+*              Indicates that PKEY is supported in NVRAM\r
+*\r
+*      IB_CA_MOD_IS_MKEY_NVRAM_SUPPORTED\r
+*              Indicates that MKEY is supported in NVRAM\r
+*\r
+*      IB_CA_MOD_IS_SYSGUID_SUPPORTED\r
+*              Indicates System Image GUID support.\r
+*\r
+*      IB_CA_MOD_IS_DR_NOTICE_SUPPORTED\r
+*              Indicate support for generating Direct Routed Notices\r
+*\r
+*      IB_CA_MOD_IS_BOOT_MGMT_SUPPORTED\r
+*              Indicates support for Boot Management\r
+*\r
+*      IB_CA_MOD_IS_CAPM_NOTICE_SUPPORTED\r
+*              Indicates capability to generate notices for changes to CAPMASK\r
+*\r
+*      IB_CA_MOD_IS_REINIT_SUPORTED\r
+*              Indicates type of node init supported. Refer to Chapter 14 for\r
+*              Initialization actions.\r
+*\r
+*      IB_CA_MOD_IS_LEDINFO_SUPPORTED\r
+*              Indicates support for LED info.\r
+*\r
+*      IB_CA_MOD_SHUTDOWN_PORT\r
+*              Used to modify the port active indicator.\r
+*\r
+*      IB_CA_MOD_INIT_TYPE_VALUE\r
+*              Used to modify the init_type value for the port.\r
+*\r
+*      IB_CA_MOD_SYSTEM_IMAGE_GUID\r
+*              Used to modify the system image GUID for the port.\r
+*****/\r
+\r
+/****d* Access Layer/ib_mr_mod_t\r
+* NAME\r
+*      ib_mr_mod_t\r
+*\r
+* DESCRIPTION\r
+*      Mask used to specify which attributes of a registered memory region are\r
+*      being modified.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t                                               ib_mr_mod_t;\r
+#define IB_MR_MOD_ADDR                                 0x00000001\r
+#define IB_MR_MOD_PD                                   0x00000002\r
+#define IB_MR_MOD_ACCESS                               0x00000004\r
+/*\r
+* PARAMETERS\r
+*      IB_MEM_MOD_ADDR\r
+*              The address of the memory region is being modified.\r
+*\r
+*      IB_MEM_MOD_PD\r
+*              The protection domain associated with the memory region is being\r
+*              modified.\r
+*\r
+*      IB_MEM_MOD_ACCESS\r
+*              The access rights the memory region are being modified.\r
+*****/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_STATE_INIT\r
+* NAME\r
+*      IB_SMINFO_STATE_INIT\r
+*\r
+* DESCRIPTION\r
+*      Encoded state value used in the SMInfo attribute.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_STATE_INIT                                   4\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_HANDOVER\r
+* NAME\r
+*      IB_SMINFO_ATTR_MOD_HANDOVER\r
+*\r
+* DESCRIPTION\r
+*      Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_ATTR_MOD_HANDOVER            (CL_NTOH32(0x000001))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_ACKNOWLEDGE\r
+* NAME\r
+*      IB_SMINFO_ATTR_MOD_ACKNOWLEDGE\r
+*\r
+* DESCRIPTION\r
+*      Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_ATTR_MOD_ACKNOWLEDGE         (CL_NTOH32(0x000002))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_DISABLE\r
+* NAME\r
+*      IB_SMINFO_ATTR_MOD_DISABLE\r
+*\r
+* DESCRIPTION\r
+*      Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_ATTR_MOD_DISABLE                     (CL_NTOH32(0x000003))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_STANDBY\r
+* NAME\r
+*      IB_SMINFO_ATTR_MOD_STANDBY\r
+*\r
+* DESCRIPTION\r
+*      Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_ATTR_MOD_STANDBY                     (CL_NTOH32(0x000004))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_DISCOVER\r
+* NAME\r
+*      IB_SMINFO_ATTR_MOD_DISCOVER\r
+*\r
+* DESCRIPTION\r
+*      Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_ATTR_MOD_DISCOVER                    (CL_NTOH32(0x000005))\r
+/**********/\r
+\r
+/****s* Access Layer/ib_ci_op_t\r
+* NAME\r
+*      ib_ci_op_t\r
+*\r
+* DESCRIPTION\r
+*      A structure used for vendor specific CA interface communication.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_ci_op\r
+{\r
+       IN              uint32_t                        command;\r
+       IN      OUT     void*                           p_buf OPTIONAL;\r
+       IN              uint32_t                        buf_size;\r
+       IN      OUT     uint32_t                        num_bytes_ret;\r
+       IN      OUT     int32_t                         status;\r
+\r
+}      ib_ci_op_t;\r
+/*\r
+* FIELDS\r
+*      command\r
+*              A command code that is understood by the verbs provider.\r
+*\r
+*      p_buf\r
+*              A reference to a buffer containing vendor specific data.  The verbs\r
+*              provider must not access pointers in the p_buf between user-mode and\r
+*              kernel-mode.  Any pointers embedded in the p_buf are invalidated by\r
+*              the user-mode/kernel-mode transition.\r
+*\r
+*      buf_size\r
+*              The size of the buffer in bytes.\r
+*\r
+*      num_bytes_ret\r
+*              The size in bytes of the vendor specific data returned in the buffer.\r
+*              This field is set by the verbs provider.  The verbs provider should\r
+*              verify that the buffer size is sufficient to hold the data being\r
+*              returned.\r
+*\r
+*      status\r
+*              The completion status from the verbs provider.  This field should be\r
+*              initialize to indicate an error to allow detection and cleanup in\r
+*              case a communication error occurs between user-mode and kernel-mode.\r
+*\r
+* NOTES\r
+*      This structure is provided to allow the exchange of vendor specific\r
+*      data between the originator and the verbs provider.  Users of this\r
+*      structure are expected to know the format of data in the p_buf based\r
+*      on the structure command field or the usage context.\r
+*****/\r
+\r
+END_C_DECLS\r
+\r
+#endif /* ndef WIN */\r
+#if defined( __WIN__ )\r
+    #include <iba/ib_types_extended.h>\r
+#endif\r
+\r
+#endif /* __IB_TYPES_H__ */\r
+\r
+\r
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/iba/ib_types_extended.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/iba/ib_types_extended.h
new file mode 100644 (file)
index 0000000..af81fde
--- /dev/null
@@ -0,0 +1,2809 @@
+/*\r
+ * Copyright (c) 2004,2005 Voltaire, Inc. All rights reserved.   \r
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.   \r
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.   \r
+ * Portions Copyright (c) 2008 Microsoft Corporation.  All rights reserved.\r
+ *  \r
+ * This software is available to you under the OpenIB.org BSD license  \r
+ * below:  \r
+ *  \r
+ *     Redistribution and use in source and binary forms, with or  \r
+ *     without modification, are permitted provided that the following  \r
+ *     conditions are met:  \r
+ *  \r
+ *      - Redistributions of source code must retain the above  \r
+ *        copyright notice, this list of conditions and the following  \r
+ *        disclaimer.  \r
+ *  \r
+ *      - Redistributions in binary form must reproduce the above  \r
+ *        copyright notice, this list of conditions and the following  \r
+ *        disclaimer in the documentation and/or other materials  \r
+ *        provided with the distribution.  \r
+ *  \r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,  \r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF   \r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND           \r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS  \r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN  \r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN  \r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  \r
+ * SOFTWARE.  \r
+ *  \r
+ * $Id: ib_types_extended.h 2165 2009-05-12 13:05:24Z leonidk $\r
+ */\r
+\r
+\r
+#if !defined(__IB_TYPES_EXTENDED_H__)\r
+#define __IB_TYPES_EXTENDED_H__\r
+\r
+\r
+#if defined( WIN32 )\r
+       #if defined( EXPORT_AL_SYMBOLS )\r
+               #define AL_EXPORT       __declspec(dllexport)\r
+       #else\r
+               #define AL_EXPORT       __declspec(dllimport)\r
+       #endif\r
+\r
+       #ifdef CL_KERNEL\r
+               #define AL_API\r
+               #define AL_INLINE       static inline\r
+       #else\r
+               #define AL_API          __stdcall\r
+               #define AL_INLINE       static  inline\r
+       #endif  /* CL_KERNEL */\r
+#else\r
+       #define AL_EXPORT       extern\r
+       #define AL_INLINE       static inline\r
+       #define AL_API\r
+       #define __ptr64\r
+#endif\r
+\r
+/*\r
+ *     Defines the size of user available data in communication management MADs\r
+ */\r
+#define IB_REQ_PDATA_SIZE                                      92\r
+#define IB_MRA_PDATA_SIZE                                      222\r
+#define IB_REJ_PDATA_SIZE                                      148\r
+#define IB_REP_PDATA_SIZE                                      196\r
+#define IB_RTU_PDATA_SIZE                                      224\r
+#define IB_LAP_PDATA_SIZE                                      168\r
+#define IB_APR_PDATA_SIZE                                      148\r
+#define IB_DREQ_PDATA_SIZE                                     220\r
+#define IB_DREP_PDATA_SIZE                                     224\r
+#define IB_SIDR_REQ_PDATA_SIZE                         216\r
+#define IB_SIDR_REP_PDATA_SIZE                         136\r
+\r
+/* following v1 ver1.2 p901 */\r
+#define IB_PATH_RECORD_RATE_5_GBS               5\r
+#define IB_PATH_RECORD_RATE_20_GBS              6\r
+#define IB_PATH_RECORD_RATE_40_GBS              7\r
+#define IB_PATH_RECORD_RATE_60_GBS              8\r
+#define IB_PATH_RECORD_RATE_80_GBS              9\r
+#define IB_PATH_RECORD_RATE_120_GBS             10\r
+\r
+\r
+\r
+typedef struct _ib_srq*                ib_srq_handle_t ; \r
+\r
+/*\r
+ *     The following definitions are shared between the Access Layer and VPD\r
+ */\r
+\r
+\r
+\r
+/****d* Access Layer/ib_api_status_t\r
+* NAME\r
+*      ib_api_status_t\r
+*\r
+* DESCRIPTION\r
+*      Function return codes indicating the success or failure of an API call.\r
+*      Note that success is indicated by the return value IB_SUCCESS, which\r
+*      is always zero.\r
+*\r
+* NOTES\r
+*      IB_VERBS_PROCESSING_DONE is used by UVP library to terminate a verbs call\r
+*      in the pre-ioctl step itself.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_api_status_t\r
+{\r
+       IB_SUCCESS,\r
+       IB_INSUFFICIENT_RESOURCES,\r
+       IB_INSUFFICIENT_MEMORY,\r
+       IB_INVALID_PARAMETER,\r
+       IB_INVALID_SETTING,\r
+       IB_NOT_FOUND,\r
+       IB_TIMEOUT,\r
+       IB_CANCELED,\r
+       IB_INTERRUPTED,\r
+       IB_INVALID_PERMISSION,\r
+       IB_UNSUPPORTED,\r
+       IB_OVERFLOW,\r
+       IB_MAX_MCAST_QPS_REACHED,\r
+       IB_INVALID_QP_STATE,\r
+       IB_INVALID_APM_STATE,\r
+       IB_INVALID_PORT_STATE,\r
+       IB_INVALID_STATE,\r
+       IB_RESOURCE_BUSY,\r
+       IB_INVALID_PKEY,\r
+       IB_INVALID_LKEY,\r
+       IB_INVALID_RKEY,\r
+       IB_INVALID_MAX_WRS,\r
+       IB_INVALID_MAX_SGE,\r
+       IB_INVALID_CQ_SIZE,\r
+       IB_INVALID_SRQ_SIZE,\r
+       IB_INVALID_SERVICE_TYPE,\r
+       IB_INVALID_GID,\r
+       IB_INVALID_LID,\r
+       IB_INVALID_GUID,\r
+       IB_INVALID_GUID_MASK,\r
+       IB_INVALID_CA_HANDLE,\r
+       IB_INVALID_AV_HANDLE,\r
+       IB_INVALID_CQ_HANDLE,\r
+       IB_INVALID_QP_HANDLE,\r
+       IB_INVALID_SRQ_HANDLE,\r
+       IB_INVALID_PD_HANDLE,\r
+       IB_INVALID_MR_HANDLE,\r
+       IB_INVALID_FMR_HANDLE,\r
+       IB_INVALID_MW_HANDLE,\r
+       IB_INVALID_MCAST_HANDLE,\r
+       IB_INVALID_CALLBACK,\r
+       IB_INVALID_AL_HANDLE,                                   /* InfiniBand Access Layer */\r
+       IB_INVALID_HANDLE,                                              /* InfiniBand Access Layer */\r
+       IB_ERROR,                                                               /* InfiniBand Access Layer */\r
+       IB_REMOTE_ERROR,                                                /* Infiniband Access Layer */\r
+       IB_VERBS_PROCESSING_DONE,                               /* See Notes above                 */\r
+       IB_INVALID_WR_TYPE,\r
+       IB_QP_IN_TIMEWAIT,\r
+       IB_EE_IN_TIMEWAIT,\r
+       IB_INVALID_PORT,\r
+       IB_NOT_DONE,\r
+       IB_INVALID_INDEX,\r
+       IB_NO_MATCH,\r
+       IB_PENDING,\r
+       IB_UNKNOWN_ERROR                                                /* ALWAYS LAST ENUM VALUE! */\r
+\r
+}      ib_api_status_t;\r
+/*****/\r
+\r
+\r
+\r
+/****f* IBA Base: Types/ib_get_err_str\r
+* NAME\r
+*      ib_get_err_str\r
+*\r
+* DESCRIPTION\r
+*      Returns a string for the specified status value.\r
+*\r
+* SYNOPSIS\r
+*/\r
+AL_EXPORT const char* AL_API\r
+ib_get_err_str(\r
+       IN                              ib_api_status_t                         status );\r
+/*\r
+* PARAMETERS\r
+*      status\r
+*              [in] status value\r
+*\r
+* RETURN VALUES\r
+*      Pointer to the status description string.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****d* Verbs/ib_async_event_t\r
+* NAME\r
+*      ib_async_event_t -- Async event types\r
+*\r
+* DESCRIPTION\r
+*      This type indicates the reason the async callback was called.\r
+*      The context in the ib_event_rec_t indicates the resource context\r
+*      that associated with the callback.  For example, for IB_AE_CQ_ERROR\r
+*      the context provided during the ib_create_cq is returned in the event.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_async_event_t\r
+{\r
+       IB_AE_SQ_ERROR = 1,\r
+       IB_AE_SQ_DRAINED,\r
+       IB_AE_RQ_ERROR,\r
+       IB_AE_CQ_ERROR,\r
+       IB_AE_QP_FATAL,\r
+       IB_AE_QP_COMM,\r
+       IB_AE_QP_APM,\r
+       IB_AE_LOCAL_FATAL,\r
+       IB_AE_PKEY_TRAP,\r
+       IB_AE_QKEY_TRAP,\r
+       IB_AE_MKEY_TRAP,\r
+       IB_AE_PORT_TRAP,\r
+       IB_AE_SYSIMG_GUID_TRAP,\r
+       IB_AE_BUF_OVERRUN,\r
+       IB_AE_LINK_INTEGRITY,\r
+       IB_AE_FLOW_CTRL_ERROR,\r
+       IB_AE_BKEY_TRAP,\r
+       IB_AE_QP_APM_ERROR,\r
+       IB_AE_WQ_REQ_ERROR,\r
+       IB_AE_WQ_ACCESS_ERROR,\r
+       IB_AE_PORT_ACTIVE,\r
+       IB_AE_PORT_DOWN,\r
+       IB_AE_CLIENT_REREGISTER,\r
+       IB_AE_SRQ_LIMIT_REACHED,\r
+       IB_AE_SRQ_CATAS_ERROR,\r
+       IB_AE_SRQ_QP_LAST_WQE_REACHED,\r
+       IB_AE_RESET_DRIVER,\r
+       IB_AE_RESET_CLIENT,\r
+       IB_AE_RESET_END,\r
+       IB_AE_RESET_FAILED,\r
+       IB_AE_LID_CHANGE,\r
+       IB_AE_PKEY_CHANGE,\r
+       IB_AE_SM_CHANGE,\r
+       IB_AE_GID_CHANGE,\r
+       IB_AE_UNKNOWN           /* ALWAYS LAST ENUM VALUE */\r
+\r
+}      ib_async_event_t;\r
+/*\r
+* VALUES\r
+*      IB_AE_SQ_ERROR\r
+*              An error occurred when accessing the send queue of the QP.\r
+*              This event is optional.\r
+*\r
+*      IB_AE_SQ_DRAINED\r
+*              The send queue of the specified QP has completed the outstanding\r
+*              messages in progress when the state change was requested and, if\r
+*              applicable, has received all acknowledgements for those messages.\r
+*\r
+*      IB_AE_RQ_ERROR\r
+*              An error occurred when accessing the receive queue of the QP.\r
+*              This event is optional.\r
+*\r
+*      IB_AE_CQ_ERROR\r
+*              An error occurred when writing an entry to the CQ.\r
+*\r
+*      IB_AE_QP_FATAL\r
+*              A catastrophic error occurred while accessing or processing the\r
+*              work queue that prevents reporting of completions.\r
+*\r
+*      IB_AE_QP_COMM\r
+*              The first packet has arrived for the receive work queue where the\r
+*              QP is still in the RTR state.\r
+*\r
+*      IB_AE_QP_APM\r
+*              If alternate path migration is supported, this event indicates that\r
+*              the QP connection has migrated to the alternate path.\r
+*\r
+*      IB_AE_LOCAL_FATAL\r
+*              A catastrophic HCA error occurred which cannot be attributed to any\r
+*              resource; behavior is indeterminate.\r
+*\r
+*      IB_AE_PKEY_TRAP\r
+*              A PKEY violation was detected.  This event is optional.\r
+*\r
+*      IB_AE_QKEY_TRAP\r
+*              A QKEY violation was detected.  This event is optional.\r
+*\r
+*      IB_AE_MKEY_TRAP\r
+*              An MKEY violation was detected.  This event is optional.\r
+*\r
+*      IB_AE_PORT_TRAP\r
+*              A port capability change was detected.  This event is optional.\r
+*\r
+*      IB_AE_SYSIMG_GUID_TRAP\r
+*              If the system image GUID is supported, this event indicates that the\r
+*              system image GUID of this HCA has been changed.  This event is\r
+*              optional.\r
+*\r
+*      IB_AE_BUF_OVERRUN\r
+*              The number of consecutive flow control update periods with at least\r
+*              one overrun error in each period has exceeded the threshold specified\r
+*              in the port info attributes.  This event is optional.\r
+*\r
+*      IB_AE_LINK_INTEGRITY\r
+*              The detection of excessively frequent local physical errors has\r
+*              exceeded the threshold specified in the port info attributes.  This\r
+*              event is optional.\r
+*\r
+*      IB_AE_FLOW_CTRL_ERROR\r
+*              An HCA watchdog timer monitoring the arrival of flow control updates\r
+*              has expired without receiving an update.  This event is optional.\r
+*\r
+*      IB_AE_BKEY_TRAP\r
+*              An BKEY violation was detected.  This event is optional.\r
+*\r
+*      IB_AE_QP_APM_ERROR\r
+*              If alternate path migration is supported, this event indicates that\r
+*              an incoming path migration request to this QP was not accepted.\r
+*\r
+*      IB_AE_WQ_REQ_ERROR\r
+*              An OpCode violation was detected at the responder.\r
+*\r
+*      IB_AE_WQ_ACCESS_ERROR\r
+*              An access violation was detected at the responder.\r
+*\r
+*      IB_AE_PORT_ACTIVE\r
+*              If the port active event is supported, this event is generated\r
+*              when the link becomes active: IB_LINK_ACTIVE.\r
+*\r
+*      IB_AE_PORT_DOWN\r
+*              The link is declared unavailable: IB_LINK_INIT, IB_LINK_ARMED,\r
+*              IB_LINK_DOWN.\r
+*\r
+*      IB_AE_CLIENT_REREGISTER\r
+*              The SM idicate to client to reregister its SA records.\r
+*\r
+*      IB_AE_SRQ_LIMIT_REACHED\r
+*              Reached SRQ low watermark\r
+*\r
+*      IB_AE_SRQ_CATAS_ERROR\r
+*              An error occurred while processing or accessing the SRQ that prevents\r
+*              dequeuing a WQE from the SRQ and reporting of receive completions.\r
+*\r
+*      IB_AE_SRQ_QP_LAST_WQE_REACHED\r
+*              An event,  issued for a QP, associated with a shared receive queue, when\r
+*                      a CQE is generated for the last WQE, or\r
+*                      the QP gets in the Error State and there are no more WQEs on the RQ.\r
+*\r
+*      IB_AE_UNKNOWN\r
+*              An unknown error occurred which cannot be attributed to any\r
+*              resource; behavior is indeterminate.\r
+*\r
+*****/\r
+\r
+\r
+\r
+/****f* IBA Base: Types/ib_get_async_event_str\r
+* NAME\r
+*      ib_get_async_event_str\r
+*\r
+* DESCRIPTION\r
+*      Returns a string for the specified asynchronous event.\r
+*\r
+* SYNOPSIS\r
+*/\r
+AL_EXPORT const char* AL_API\r
+ib_get_async_event_str(\r
+       IN                              ib_async_event_t                        event );\r
+/*\r
+* PARAMETERS\r
+*      event\r
+*              [in] event value\r
+*\r
+* RETURN VALUES\r
+*      Pointer to the asynchronous event description string.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+\r
+/****s* Verbs/ib_event_rec_t\r
+* NAME\r
+*      ib_event_rec_t -- Async event notification record\r
+*\r
+* DESCRIPTION\r
+*      When an async event callback is made, this structure is passed to indicate\r
+*      the type of event, the source of event that caused it, and the context\r
+*      associated with this event.\r
+*\r
+*      context -- Context of the resource that caused the event.\r
+*              -- ca_context if this is a port/adapter event.\r
+*              -- qp_context if the source is a QP event\r
+*              -- cq_context if the source is a CQ event.\r
+*              -- ee_context if the source is an EE event.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_event_rec\r
+{\r
+       TO_LONG_PTR(void*,              context);\r
+       ib_async_event_t                type;\r
+\r
+       /* HCA vendor specific event information. */\r
+       uint64_t                                vendor_specific;\r
+       uint8_t                                 port_number;\r
+\r
+}      ib_event_rec_t;\r
+/*******/\r
+\r
+\r
+/****d* Access Layer/ib_atomic_t\r
+* NAME\r
+*      ib_atomic_t\r
+*\r
+* DESCRIPTION\r
+*      Indicates atomicity levels supported by an adapter.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_atomic_t\r
+{\r
+       IB_ATOMIC_NONE,\r
+       IB_ATOMIC_LOCAL,\r
+       IB_ATOMIC_GLOBAL\r
+\r
+}      ib_atomic_t;\r
+/*\r
+* VALUES\r
+*      IB_ATOMIC_NONE\r
+*              Atomic operations not supported.\r
+*\r
+*      IB_ATOMIC_LOCAL\r
+*              Atomic operations guaranteed between QPs of a single CA.\r
+*\r
+*      IB_ATOMIC_GLOBAL\r
+*              Atomic operations are guaranteed between CA and any other entity\r
+*              in the system.\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_port_cap_t\r
+* NAME\r
+*      ib_port_cap_t\r
+*\r
+* DESCRIPTION\r
+*      Indicates which management agents are currently available on the specified\r
+*      port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_port_cap\r
+{\r
+       boolean_t               cm;\r
+       boolean_t               snmp;\r
+       boolean_t               dev_mgmt;\r
+       boolean_t               vend;\r
+       boolean_t               sm;\r
+       boolean_t               sm_disable;\r
+       boolean_t               qkey_ctr;\r
+       boolean_t               pkey_ctr;\r
+       boolean_t               notice;\r
+       boolean_t               trap;\r
+       boolean_t               apm;\r
+       boolean_t               slmap;\r
+       boolean_t               pkey_nvram;\r
+       boolean_t               mkey_nvram;\r
+       boolean_t               sysguid;\r
+       boolean_t               dr_notice;\r
+       boolean_t               boot_mgmt;\r
+       boolean_t               capm_notice;\r
+       boolean_t               reinit;\r
+       boolean_t               ledinfo;\r
+       boolean_t               port_active;\r
+       boolean_t               ipd;\r
+       boolean_t               pkey_switch_ext_port;\r
+       boolean_t               bm;\r
+       boolean_t               link_rtl;\r
+       boolean_t               client_reregister;      \r
+\r
+}      ib_port_cap_t;\r
+/*****/\r
+\r
+\r
+/****d* Access Layer/ib_init_type_t\r
+* NAME\r
+*      ib_init_type_t\r
+*\r
+* DESCRIPTION\r
+*      If supported by the HCA, the type of initialization requested by\r
+*      this port before SM moves it to the active or armed state.  If the\r
+*      SM implements reinitialization, it shall set these bits to indicate\r
+*      the type of initialization performed prior to activating the port.\r
+*      Otherwise, these bits shall be set to 0.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint8_t                                        ib_init_type_t;\r
+#define IB_INIT_TYPE_NO_LOAD                           0x01\r
+#define IB_INIT_TYPE_PRESERVE_CONTENT          0x02\r
+#define IB_INIT_TYPE_PRESERVE_PRESENCE         0x04\r
+#define IB_INIT_TYPE_DO_NOT_RESUSCITATE                0x08\r
+/*****/\r
+\r
+\r
+/****s* Access Layer/ib_port_attr_mod_t\r
+* NAME\r
+*      ib_port_attr_mod_t\r
+*\r
+* DESCRIPTION\r
+*      Port attributes that may be modified.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_port_attr_mod\r
+{\r
+       ib_port_cap_t                   cap;\r
+       uint16_t                                pkey_ctr;\r
+       uint16_t                                qkey_ctr;\r
+\r
+       ib_init_type_t                  init_type;\r
+       ib_net64_t                              system_image_guid;\r
+\r
+}      ib_port_attr_mod_t;\r
+/*\r
+* SEE ALSO\r
+*      ib_port_cap_t\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_port_attr_t\r
+* NAME\r
+*      ib_port_attr_t\r
+*\r
+* DESCRIPTION\r
+*      Information about a port on a given channel adapter.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_port_attr\r
+{\r
+       ib_net64_t                              port_guid;\r
+       uint8_t                                 port_num;\r
+       uint8_t                                 mtu;\r
+       uint64_t                                max_msg_size;\r
+       ib_net16_t                              lid;\r
+       uint8_t                                 lmc;\r
+\r
+       /*\r
+        * LinkWidthSupported as defined in PortInfo.  Required to calculate\r
+        * inter-packet delay (a.k.a. static rate).\r
+        */\r
+       uint8_t                                 link_width_supported;\r
+\r
+       uint16_t                                max_vls;\r
+\r
+       ib_net16_t                              sm_lid;\r
+       uint8_t                                 sm_sl;\r
+       uint8_t                                 link_state;\r
+\r
+       ib_init_type_t                  init_type_reply;        /* Optional */\r
+\r
+       /*\r
+        * subnet_timeout:\r
+        * The maximum expected subnet propagation delay to reach any port on\r
+        * the subnet.  This value also determines the rate at which traps can\r
+        * be generated from this node.\r
+        *\r
+        * timeout = 4.096 microseconds * 2^subnet_timeout\r
+        */\r
+       uint8_t                                 subnet_timeout;\r
+       uint8_t                                 active_speed;\r
+       uint8_t                                 phys_state;\r
+\r
+       ib_port_cap_t                   cap;\r
+       uint16_t                                pkey_ctr;\r
+       uint16_t                                qkey_ctr;\r
+\r
+       uint16_t                                num_gids;\r
+       uint16_t                                num_pkeys;\r
+       /*\r
+        * Pointers at the end of the structure to allow doing a simple\r
+        * memory comparison of contents up to the first pointer.\r
+        */\r
+       TO_LONG_PTR(ib_gid_t*,  p_gid_table);\r
+       TO_LONG_PTR(ib_net16_t*,p_pkey_table);\r
+\r
+}      ib_port_attr_t;\r
+/*\r
+* SEE ALSO\r
+*      uint8_t, ib_port_cap_t, ib_link_states_t\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_ca_attr_t\r
+* NAME\r
+*      ib_ca_attr_t\r
+*\r
+* DESCRIPTION\r
+*      Information about a channel adapter.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_ca_attr\r
+{\r
+       ib_net64_t                              ca_guid;\r
+\r
+       uint32_t                                vend_id;\r
+       uint16_t                                dev_id;\r
+       uint16_t                                revision;\r
+       uint64_t                                fw_ver;\r
+\r
+       /*\r
+        * Total size of the ca attributes in bytes\r
+        */\r
+       uint32_t                                size;\r
+       uint32_t                                max_qps;\r
+       uint32_t                                max_wrs;\r
+\r
+       uint32_t                                max_sges;\r
+       uint32_t                                max_rd_sges;\r
+\r
+       uint32_t                                max_cqs;\r
+       uint32_t                                max_cqes;\r
+\r
+       uint32_t                                max_pds;\r
+\r
+       uint32_t                                init_regions;\r
+       uint64_t                                init_region_size;\r
+\r
+       uint32_t                                init_windows;\r
+       uint64_t                                max_addr_handles;\r
+\r
+       uint32_t                                max_partitions;\r
+\r
+       ib_atomic_t                             atomicity;\r
+\r
+       uint8_t                                 max_qp_resp_res;\r
+       uint8_t                                 max_resp_res;\r
+\r
+       uint8_t                                 max_qp_init_depth;\r
+\r
+       uint32_t                                max_ipv6_qps;\r
+       uint32_t                                max_ether_qps;\r
+\r
+       uint32_t                                max_mcast_grps;\r
+       uint32_t                                max_mcast_qps;\r
+       uint32_t                                max_qps_per_mcast_grp;\r
+       uint32_t                                max_fmr;\r
+       uint32_t                                max_map_per_fmr;\r
+       uint32_t                                max_srq;\r
+       uint32_t                                max_srq_wrs;\r
+       uint32_t                                max_srq_sges;\r
+\r
+       /*\r
+        * local_ack_delay:\r
+        * Specifies the maximum time interval between the local CA receiving\r
+        * a message and the transmission of the associated ACK or NAK.\r
+        *\r
+        * timeout = 4.096 microseconds * 2^local_ack_delay\r
+        */\r
+       uint8_t                                 local_ack_delay;\r
+\r
+       boolean_t                               bad_pkey_ctr_support;\r
+       boolean_t                               bad_qkey_ctr_support;\r
+       boolean_t                               raw_mcast_support;\r
+       boolean_t                               apm_support;\r
+       boolean_t                               av_port_check;\r
+       boolean_t                               change_primary_port;\r
+       boolean_t                               modify_wr_depth;\r
+       boolean_t                               modify_srq_depth;\r
+       boolean_t                               current_qp_state_support;\r
+       boolean_t                               shutdown_port_capability;\r
+       boolean_t                               init_type_support;\r
+       boolean_t                               port_active_event_support;\r
+       boolean_t                               system_image_guid_support;\r
+       boolean_t                               hw_agents;\r
+       boolean_t                               ipoib_csum;\r
+       \r
+       ib_net64_t                              system_image_guid;\r
+\r
+       uint32_t                                num_page_sizes;\r
+       uint8_t                                 num_ports;\r
+\r
+       TO_LONG_PTR(uint32_t*,  p_page_size);\r
+       TO_LONG_PTR(ib_port_attr_t*, p_port_attr);\r
+\r
+}      ib_ca_attr_t;\r
+/*\r
+* FIELDS\r
+*      ca_guid\r
+*              GUID for this adapter.\r
+*\r
+*      vend_id\r
+*              IEEE vendor ID for this adapter\r
+*\r
+*      dev_id\r
+*              Device ID of this adapter. (typically from PCI device ID)\r
+*\r
+*      revision\r
+*              Revision ID of this adapter\r
+*\r
+*      fw_ver\r
+*              Device Firmware version.\r
+*\r
+*      size\r
+*              Total size in bytes for the HCA attributes.  This size includes total\r
+*              size required for all the variable members of the structure.  If a\r
+*              vendor requires to pass vendor specific fields beyond this structure,\r
+*              the HCA vendor can choose to report a larger size.  If a vendor is\r
+*              reporting extended vendor specific features, they should also provide\r
+*              appropriate access functions to aid with the required interpretation.\r
+*\r
+*      max_qps\r
+*              Maximum number of QP's supported by this HCA.\r
+*\r
+*      max_wrs\r
+*              Maximum number of work requests supported by this HCA.\r
+*\r
+*      max_sges\r
+*              Maximum number of scatter gather elements supported per work request.\r
+*\r
+*      max_rd_sges\r
+*              Maximum number of scatter gather elements supported for READ work\r
+*              requests for a Reliable Datagram QP.  This value must be zero if RD\r
+*              service is not supported.\r
+*\r
+*      max_cqs\r
+*              Maximum number of Completion Queues supported.\r
+*\r
+*      max_cqes\r
+*              Maximum number of CQ elements supported per CQ.\r
+*\r
+*      max_pds\r
+*              Maximum number of protection domains supported.\r
+*\r
+*      init_regions\r
+*              Initial number of memory regions supported.  These are only informative\r
+*              values.  HCA vendors can extended and grow these limits on demand.\r
+*\r
+*      init_region_size\r
+*              Initial limit on the size of the registered memory region.\r
+*\r
+*      init_windows\r
+*              Initial number of window entries supported.\r
+*\r
+*      max_addr_handles\r
+*              Maximum number of address handles supported.\r
+*\r
+*      max_partitions\r
+*              Maximum number of partitions supported.\r
+*\r
+*      atomicity\r
+*              Indicates level of atomic operations supported by this HCA.\r
+*\r
+*      max_qp_resp_res\r
+*              Maximum limit on number of responder resources for incomming RDMA\r
+*              operations on QPs.\r
+*\r
+*      max_fmr\r
+*              Maximum number of Fast Memory Regions supported.\r
+*\r
+*      max_map_per_fmr\r
+*              Maximum number of mappings, supported by a Fast Memory Region.\r
+*\r
+*      max_srq\r
+*              Maximum number of Shared Receive Queues supported.\r
+*\r
+*      max_srq_wrs\r
+*              Maximum number of work requests supported by this SRQ.\r
+*\r
+*      max_srq_sges\r
+*              Maximum number of scatter gather elements supported per work request on SRQ.\r
+*\r
+*      max_resp_res\r
+*              Maximum number of responder resources per HCA, with this HCA used as\r
+*              the target.\r
+*\r
+*      max_qp_init_depth\r
+*              Maximimum initiator depth per QP for initiating RDMA reads and\r
+*              atomic operations.\r
+*\r
+*      max_ipv6_qps\r
+*      max_ether_qps\r
+*              Maximum number of IPV6 and raw ether QP's supported by this HCA.\r
+*\r
+*      max_mcast_grps\r
+*              Maximum number of multicast groups supported.\r
+*\r
+*      max_mcast_qps\r
+*              Maximum number of QP's that can support multicast operations.\r
+*\r
+*      max_qps_per_mcast_grp\r
+*              Maximum number of multicast QP's per multicast group.\r
+*\r
+*      local_ack_delay\r
+*              Specifies the maximum time interval between the local CA receiving\r
+*              a message and the transmission of the associated ACK or NAK.\r
+*              timeout = 4.096 microseconds * 2^local_ack_delay\r
+*\r
+*      bad_pkey_ctr_support\r
+*      bad_qkey_ctr_support\r
+*              Indicates support for the bad pkey and qkey counters.\r
+*\r
+*      raw_mcast_support\r
+*              Indicates support for raw packet multicast.\r
+*\r
+*      apm_support\r
+*              Indicates support for Automatic Path Migration.\r
+*\r
+*      av_port_check\r
+*              Indicates ability to check port number in address handles.\r
+*\r
+*      change_primary_port\r
+*              Indicates ability to change primary port for a QP during a\r
+*              SQD->RTS transition.\r
+*\r
+*      modify_wr_depth\r
+*              Indicates ability to modify QP depth during a modify QP operation.\r
+*              Check the verb specification for permitted states.\r
+*\r
+*      modify_srq_depth\r
+*              Indicates ability to modify SRQ depth during a modify SRQ operation.\r
+*              Check the verb specification for permitted states.\r
+*\r
+*      current_qp_state_support\r
+*              Indicates ability of the HCA to support the current QP state modifier\r
+*              during a modify QP operation.\r
+*\r
+*      shutdown_port_capability\r
+*              Shutdown port capability support indicator.\r
+*\r
+*      init_type_support\r
+*              Indicates init_type_reply and ability to set init_type is supported.\r
+*\r
+*      port_active_event_support\r
+*              Port active event support indicator.\r
+*\r
+*      system_image_guid_support\r
+*              System image GUID support indicator.\r
+*\r
+*      hw_agents\r
+*              Indicates SMA is implemented in HW.\r
+*\r
+*      system_image_guid\r
+*              Optional system image GUID.  This field is valid only if the\r
+*              system_image_guid_support flag is set.\r
+*\r
+*      num_page_sizes\r
+*              Indicates support for different page sizes supported by the HCA.\r
+*              The variable size array can be obtained from p_page_size.\r
+*\r
+*      num_ports\r
+*              Number of physical ports supported on this HCA.\r
+*\r
+*      p_page_size\r
+*              Array holding different page size supported.\r
+*\r
+*      p_port_attr\r
+*              Array holding port attributes.\r
+*\r
+* NOTES\r
+*      This structure contains the attributes of a channel adapter.  Users must\r
+*      call ib_copy_ca_attr to copy the contents of this structure to a new\r
+*      memory region.\r
+*\r
+* SEE ALSO\r
+*      ib_port_attr_t, ib_atomic_t, ib_copy_ca_attr\r
+*****/\r
+\r
+/****f* Access layer/ib_copy_ca_attr\r
+* NAME\r
+*      ib_copy_ca_attr\r
+*\r
+* DESCRIPTION\r
+*      Copies CA attributes.\r
+*\r
+* SYNOPSIS\r
+*/\r
+AL_EXPORT ib_ca_attr_t* AL_API\r
+ib_copy_ca_attr(\r
+       IN                              ib_ca_attr_t* const             p_dest,\r
+       IN              const   ib_ca_attr_t* const             p_src );\r
+/*\r
+* PARAMETERS\r
+*      p_dest\r
+*              Pointer to the buffer that is the destination of the copy.\r
+*\r
+*      p_src\r
+*              Pointer to the CA attributes to copy.\r
+*\r
+* RETURN VALUE\r
+*      Pointer to the copied CA attributes.\r
+*\r
+* NOTES\r
+*      The buffer pointed to by the p_dest parameter must be at least the size\r
+*      specified in the size field of the buffer pointed to by p_src.\r
+*\r
+* SEE ALSO\r
+*      ib_ca_attr_t, ib_dup_ca_attr, ib_free_ca_attr\r
+*****/\r
+\r
+\r
+/****d* Access Layer/ib_pd_type_t\r
+* NAME\r
+*      ib_pd_type_t\r
+*\r
+* DESCRIPTION\r
+*      Indicates the type of protection domain being allocated.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_pd_type\r
+{\r
+       IB_PDT_NORMAL,\r
+       IB_PDT_ALIAS,\r
+       IB_PDT_SQP,\r
+       IB_PDT_UD\r
+\r
+}      ib_pd_type_t;\r
+/*\r
+* VALUES\r
+*      IB_PDT_NORMAL\r
+*              Protection domain for all non-aliased QPs.\r
+*\r
+*      IB_PDT_ALIAS\r
+*              Protection domain for IB_QPT_QP0_ALIAS and IB_QPT_QP1_ALIAS QPs.\r
+*\r
+*      IB_PDT_SQP\r
+*              Protection domain for special queue pair usage.\r
+*\r
+*      IB_PDT_UD\r
+*              Protection domain for UD queue pair usage.\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_av_attr_t\r
+* NAME\r
+*      ib_av_attr_t\r
+*\r
+* DESCRIPTION\r
+*      IBA address vector.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_av_attr\r
+{\r
+       uint8_t                                 port_num;\r
+\r
+       uint8_t                                 sl;\r
+       ib_net16_t                              dlid;\r
+\r
+       boolean_t                               grh_valid;\r
+       ib_grh_t                                grh;\r
+       uint8_t                                 static_rate;\r
+       uint8_t                                 path_bits;\r
+\r
+       struct _av_conn\r
+       {\r
+               uint8_t                         path_mtu;\r
+               uint8_t                         local_ack_timeout;\r
+               uint8_t                         seq_err_retry_cnt;\r
+               uint8_t                         rnr_retry_cnt;\r
+\r
+       }       conn;\r
+\r
+}      ib_av_attr_t;\r
+/*\r
+* SEE ALSO\r
+*      ib_gid_t\r
+*****/\r
+\r
+\r
+/****d* Access Layer/ib_qp_type_t\r
+* NAME\r
+*      ib_qp_type_t\r
+*\r
+* DESCRIPTION\r
+*      Indicates the type of queue pair being created.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_qp_type\r
+{\r
+       IB_QPT_RELIABLE_CONN    = 0,            /* Matches CM REQ transport type */\r
+       IB_QPT_UNRELIABLE_CONN  = 1,            /* Matches CM REQ transport type */\r
+       IB_QPT_RELIABLE_DGRM    = 2,    /* Matches CM REQ transport type */\r
+       IB_QPT_UNRELIABLE_DGRM,\r
+       IB_QPT_QP0,\r
+       IB_QPT_QP1,\r
+       IB_QPT_RAW_IPV6,\r
+       IB_QPT_RAW_ETHER,\r
+       IB_QPT_MAD,                                                             /* InfiniBand Access Layer */\r
+       IB_QPT_QP0_ALIAS,                                               /* InfiniBand Access Layer */\r
+       IB_QPT_QP1_ALIAS,                                               /* InfiniBand Access Layer */\r
+       IB_QPT_UNKNOWN\r
+}      ib_qp_type_t;\r
+/*\r
+* VALUES\r
+*      IB_QPT_RELIABLE_CONN\r
+*              Reliable, connected queue pair.\r
+*\r
+*      IB_QPT_UNRELIABLE_CONN\r
+*              Unreliable, connected queue pair.\r
+*\r
+*      IB_QPT_RELIABLE_DGRM\r
+*              Reliable, datagram queue pair.\r
+*\r
+*      IB_QPT_UNRELIABLE_DGRM\r
+*              Unreliable, datagram queue pair.\r
+*\r
+*      IB_QPT_QP0\r
+*              Queue pair 0.\r
+*\r
+*      IB_QPT_QP1\r
+*              Queue pair 1.\r
+*\r
+*      IB_QPT_RAW_DGRM\r
+*              Raw datagram queue pair.\r
+*\r
+*      IB_QPT_RAW_IPV6\r
+*              Raw IP version 6 queue pair.\r
+*\r
+*      IB_QPT_RAW_ETHER\r
+*              Raw Ethernet queue pair.\r
+*\r
+*      IB_QPT_MAD\r
+*              Unreliable, datagram queue pair that will send and receive management\r
+*              datagrams with assistance from the access layer.\r
+*\r
+*      IB_QPT_QP0_ALIAS\r
+*              Alias to queue pair 0.  Aliased QPs can only be created on an aliased\r
+*              protection domain.\r
+*\r
+*      IB_QPT_QP1_ALIAS\r
+*              Alias to queue pair 1.  Aliased QPs can only be created on an aliased\r
+*              protection domain.\r
+*****/\r
+\r
+\r
+/****f* IBA Base: Types/ib_get_qp_type_str\r
+* NAME\r
+*      ib_get_qp_type_str\r
+*\r
+* DESCRIPTION\r
+*      Returns a string for the specified QP type\r
+*\r
+* SYNOPSIS\r
+*/\r
+AL_EXPORT const char* AL_API\r
+ib_get_qp_type_str(\r
+       IN                              uint8_t                                         qp_type );\r
+\r
+/*\r
+* PARAMETERS\r
+*      qp_type\r
+*              [in] Encoded QP type as defined in the\r
+QP attribute.\r
+\r
+* RETURN VALUES\r
+*      Pointer to the QP type string.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_qp_type_t\r
+*********/\r
+\r
+/****d* Access Layer/ib_access_t\r
+* NAME\r
+*      ib_access_t\r
+*\r
+* DESCRIPTION\r
+*      Indicates the type of access is permitted on resources such as QPs,\r
+*      memory regions and memory windows.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t                               ib_access_t;\r
+#define IB_AC_RDMA_READ                        0x00000001\r
+#define IB_AC_RDMA_WRITE               0x00000002\r
+#define IB_AC_ATOMIC                   0x00000004\r
+#define IB_AC_LOCAL_WRITE              0x00000008\r
+#define IB_AC_MW_BIND                  0x00000010\r
+/*\r
+* NOTES\r
+*      Users may combine access rights using a bit-wise or operation to specify\r
+*      additional access.  For example: IB_AC_RDMA_READ | IB_AC_RDMA_WRITE grants\r
+*      RDMA read and write access.\r
+*****/\r
+\r
+\r
+/****d* Access Layer/ib_qp_state_t\r
+* NAME\r
+*      ib_qp_state_t\r
+*\r
+* DESCRIPTION\r
+*      Indicates or sets the state of a queue pair.  The current state of a queue\r
+*      pair is returned through the ib_qp_query call and set via the\r
+*      ib_qp_modify call.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t                               ib_qp_state_t;\r
+#define IB_QPS_RESET                   0x00000001\r
+#define IB_QPS_INIT                            0x00000002\r
+#define IB_QPS_RTR                             0x00000004\r
+#define IB_QPS_RTS                             0x00000008\r
+#define IB_QPS_SQD                             0x00000010\r
+#define IB_QPS_SQD_DRAINING            0x00000030\r
+#define IB_QPS_SQD_DRAINED             0x00000050\r
+#define IB_QPS_SQERR                   0x00000080\r
+#define IB_QPS_ERROR                   0x00000100\r
+#define IB_QPS_TIME_WAIT               0xDEAD0000      /* InfiniBand Access Layer */\r
+/*****/\r
+\r
+\r
+/****d* Access Layer/ib_apm_state_t\r
+* NAME\r
+*      ib_apm_state_t\r
+*\r
+* DESCRIPTION\r
+*      The current automatic path migration state of a queue pair\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_apm_state\r
+{\r
+       IB_APM_MIGRATED = 1,\r
+       IB_APM_REARM,\r
+       IB_APM_ARMED\r
+\r
+}      ib_apm_state_t;\r
+/*****/\r
+\r
+/****d* Access Layer/ib_srq_attr_mask_t\r
+* NAME\r
+*      ib_srq_attr_mask_t\r
+*\r
+* DESCRIPTION\r
+*      Indicates valid fields in ib_srq_attr_t structure\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_srq_attr_mask {\r
+       IB_SRQ_MAX_WR   = 1 << 0,\r
+       IB_SRQ_LIMIT    = 1 << 1,\r
+} ib_srq_attr_mask_t;\r
+/*****/\r
+\r
+\r
+/****s* Access Layer/ib_srq_attr_t\r
+* NAME\r
+*      ib_srq_attr_t\r
+*\r
+* DESCRIPTION\r
+*      Attributes used to initialize a shared queue pair at creation time.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_srq_attr {\r
+       uint32_t                                max_wr;\r
+       uint32_t                                max_sge;\r
+       uint32_t                                srq_limit;\r
+} ib_srq_attr_t;\r
+/*\r
+* FIELDS\r
+*      max_wr\r
+*              Specifies the max number of work request on SRQ.\r
+*\r
+*      max_sge\r
+*              Specifies the max number of scatter/gather elements in one work request.\r
+*\r
+*      srq_limit\r
+*              Specifies the low water mark for SRQ.\r
+*\r
+* SEE ALSO\r
+*      ib_qp_type_t, ib_srq_attr_mask_t\r
+*****/\r
+\r
+\r
+\r
+/****s* Access Layer/ib_qp_create_t\r
+* NAME\r
+*      ib_qp_create_t\r
+*\r
+* DESCRIPTION\r
+*      Attributes used to initialize a queue pair at creation time.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_qp_create\r
+{\r
+       ib_qp_type_t                    qp_type;\r
+\r
+       uint32_t                                sq_max_inline;\r
+       uint32_t                                sq_depth;\r
+       uint32_t                                rq_depth;\r
+       uint32_t                                sq_sge;\r
+       uint32_t                                rq_sge;\r
+\r
+       TO_LONG_PTR(ib_cq_handle_t, h_sq_cq);\r
+       TO_LONG_PTR(ib_cq_handle_t, h_rq_cq);\r
+       TO_LONG_PTR(ib_srq_handle_t, h_srq);\r
+\r
+       boolean_t                               sq_signaled;\r
+\r
+}      ib_qp_create_t;\r
+/*\r
+* FIELDS\r
+*      type\r
+*              Specifies the type of queue pair to create.\r
+*\r
+*      sq_max_inline\r
+*              Maximum payload that can be inlined directly in a WQE, eliminating\r
+*              protection checks and additional DMA operations.\r
+*\r
+*      sq_depth\r
+*              Indicates the requested maximum number of work requests that may be\r
+*              outstanding on the queue pair's send queue.  This value must be less\r
+*              than or equal to the maximum reported by the channel adapter associated\r
+*              with the queue pair.\r
+*\r
+*      rq_depth\r
+*              Indicates the requested maximum number of work requests that may be\r
+*              outstanding on the queue pair's receive queue.  This value must be less\r
+*              than or equal to the maximum reported by the channel adapter associated\r
+*              with the queue pair.\r
+*\r
+*      sq_sge\r
+*              Indicates the maximum number scatter-gather elements that may be\r
+*              given in a send work request.  This value must be less\r
+*              than or equal to the maximum reported by the channel adapter associated\r
+*              with the queue pair.\r
+*\r
+*      rq_sge\r
+*              Indicates the maximum number scatter-gather elements that may be\r
+*              given in a receive work request.  This value must be less\r
+*              than or equal to the maximum reported by the channel adapter associated\r
+*              with the queue pair.\r
+*\r
+*      h_sq_cq\r
+*              A handle to the completion queue that will be used to report send work\r
+*              request completions.  This handle must be NULL if the type is\r
+*              IB_QPT_MAD, IB_QPT_QP0_ALIAS, or IB_QPT_QP1_ALIAS.\r
+*\r
+*      h_rq_cq\r
+*              A handle to the completion queue that will be used to report receive\r
+*              work request completions.  This handle must be NULL if the type is\r
+*              IB_QPT_MAD, IB_QPT_QP0_ALIAS, or IB_QPT_QP1_ALIAS.\r
+*\r
+*      h_srq\r
+*              A handle to an SRQ to get receive completions via. Must be coded NULL \r
+*              when QP is not associated with SRQ\r
+*\r
+*      sq_signaled\r
+*              A flag that is used to indicate whether the queue pair will signal\r
+*              an event upon completion of a send work request.  If set to\r
+*              TRUE, send work requests will always generate a completion\r
+*              event.  If set to FALSE, a completion event will only be\r
+*              generated if the send_opt field of the send work request has the\r
+*              IB_SEND_OPT_SIGNALED flag set.\r
+*\r
+* SEE ALSO\r
+*      ib_qp_type_t, ib_qp_attr_t\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_qp_attr_t\r
+* NAME\r
+*      ib_qp_attr_t\r
+*\r
+* DESCRIPTION\r
+*      Queue pair attributes returned through ib_query_qp.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_qp_attr\r
+{\r
+       TO_LONG_PTR(ib_pd_handle_t, h_pd);\r
+       ib_qp_type_t                    qp_type;\r
+       ib_access_t                             access_ctrl;\r
+       uint16_t                                pkey_index;\r
+\r
+       uint32_t                                sq_max_inline;\r
+       uint32_t                                sq_depth;\r
+       uint32_t                                rq_depth;\r
+       uint32_t                                sq_sge;\r
+       uint32_t                                rq_sge;\r
+       uint8_t                                 init_depth;\r
+       uint8_t                                 resp_res;\r
+\r
+       TO_LONG_PTR(ib_cq_handle_t, h_sq_cq);\r
+       TO_LONG_PTR(ib_cq_handle_t, h_rq_cq);\r
+       TO_LONG_PTR(ib_srq_handle_t,h_srq);\r
+\r
+       boolean_t                               sq_signaled;\r
+\r
+       ib_qp_state_t                   state;\r
+       ib_net32_t                              num;\r
+       ib_net32_t                              dest_num;\r
+       ib_net32_t                              qkey;\r
+\r
+       ib_net32_t                              sq_psn;\r
+       ib_net32_t                              rq_psn;\r
+\r
+       uint8_t                                 primary_port;\r
+       uint8_t                                 alternate_port;\r
+       ib_av_attr_t                    primary_av;\r
+       ib_av_attr_t                    alternate_av;\r
+       ib_apm_state_t                  apm_state;\r
+\r
+}      ib_qp_attr_t;\r
+/*\r
+* FIELDS\r
+*      h_pd\r
+*              This is a handle to a protection domain associated with the QP.\r
+*\r
+*      sq_max_inline\r
+*              Maximum payload that can be inlined directly in a WQE, eliminating\r
+*              protection checks and additional DMA operations.\r
+*\r
+* NOTES\r
+*      Other fields are defined by the Infiniband specification.\r
+*\r
+* SEE ALSO\r
+*      ib_qp_type_t, ib_access_t, ib_qp_state_t, ib_av_attr_t, ib_apm_state_t\r
+*****/\r
+\r
+\r
+/****d* Access Layer/ib_qp_opts_t\r
+* NAME\r
+*      ib_qp_opts_t\r
+*\r
+* DESCRIPTION\r
+*      Optional fields supplied in the modify QP operation.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t                               ib_qp_opts_t;\r
+#define IB_MOD_QP_ALTERNATE_AV         0x00000001\r
+#define IB_MOD_QP_PKEY                         0x00000002\r
+#define IB_MOD_QP_APM_STATE                    0x00000004\r
+#define IB_MOD_QP_PRIMARY_AV           0x00000008\r
+#define IB_MOD_QP_RNR_NAK_TIMEOUT      0x00000010\r
+#define IB_MOD_QP_RESP_RES                     0x00000020\r
+#define IB_MOD_QP_INIT_DEPTH           0x00000040\r
+#define IB_MOD_QP_PRIMARY_PORT         0x00000080\r
+#define IB_MOD_QP_ACCESS_CTRL          0x00000100\r
+#define IB_MOD_QP_QKEY                         0x00000200\r
+#define IB_MOD_QP_SQ_DEPTH                     0x00000400\r
+#define IB_MOD_QP_RQ_DEPTH                     0x00000800\r
+#define IB_MOD_QP_CURRENT_STATE                0x00001000\r
+#define IB_MOD_QP_RETRY_CNT                    0x00002000\r
+#define IB_MOD_QP_LOCAL_ACK_TIMEOUT    0x00004000\r
+#define IB_MOD_QP_RNR_RETRY_CNT                0x00008000\r
+\r
+/*\r
+* SEE ALSO\r
+*      ib_qp_mod_t\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_qp_mod_t\r
+* NAME\r
+*      ib_qp_mod_t\r
+*\r
+* DESCRIPTION\r
+*      Information needed to change the state of a queue pair through the\r
+*      ib_modify_qp call.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_qp_mod\r
+{\r
+       ib_qp_state_t                           req_state;\r
+\r
+       union _qp_state\r
+       {\r
+               struct _qp_init\r
+               {\r
+                       uint8_t                         primary_port;\r
+                       ib_net32_t                      qkey;\r
+                       uint16_t                        pkey_index;\r
+                       ib_access_t                     access_ctrl;\r
+\r
+               }       init;\r
+\r
+               struct _qp_rtr\r
+               {\r
+                       ib_net32_t                      rq_psn;\r
+                       ib_net32_t                      dest_qp;\r
+                       ib_av_attr_t            primary_av;\r
+                       uint8_t                         resp_res;\r
+                       uint8_t                         rnr_nak_timeout;\r
+\r
+                       ib_qp_opts_t            opts;\r
+                       ib_av_attr_t            alternate_av;\r
+                       ib_net32_t                      qkey;\r
+                       uint16_t                        pkey_index;\r
+                       ib_access_t                     access_ctrl;\r
+                       uint32_t                        sq_depth;\r
+                       uint32_t                        rq_depth;\r
+\r
+               }       rtr;\r
+\r
+               struct _qp_rts\r
+               {\r
+                       ib_net32_t                      sq_psn;\r
+                       uint8_t                         retry_cnt;\r
+                       uint8_t                         rnr_retry_cnt;\r
+                       uint8_t                         local_ack_timeout;\r
+                       uint8_t                         init_depth;\r
+\r
+                       ib_qp_opts_t            opts;\r
+                       uint8_t                         rnr_nak_timeout;\r
+                       ib_qp_state_t           current_state;\r
+                       ib_net32_t                      qkey;\r
+                       ib_access_t                     access_ctrl;\r
+                       uint8_t                         resp_res;\r
+\r
+                       ib_av_attr_t            primary_av;\r
+                       ib_av_attr_t            alternate_av;\r
+\r
+                       uint32_t                        sq_depth;\r
+                       uint32_t                        rq_depth;\r
+\r
+                       ib_apm_state_t          apm_state;\r
+                       uint8_t                         primary_port;\r
+                       uint16_t                        pkey_index;\r
+\r
+               }       rts;\r
+\r
+               struct _qp_sqd\r
+               {\r
+                       boolean_t                       sqd_event;\r
+\r
+               }       sqd;\r
+\r
+       }       state;\r
+\r
+}      ib_qp_mod_t;\r
+/*\r
+* SEE ALSO\r
+*      ib_qp_state_t, ib_access_t, ib_av_attr_t, ib_apm_state_t\r
+*****/\r
+\r
+\r
+/****d* Access Layer/ib_wr_type_t\r
+* NAME\r
+*      ib_wr_type_t\r
+*\r
+* DESCRIPTION\r
+*      Identifies the type of work request posted to a queue pair.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_wr_type_t\r
+{\r
+       WR_SEND,\r
+       WR_RDMA_WRITE,\r
+       WR_RDMA_READ,\r
+       WR_COMPARE_SWAP,\r
+       WR_FETCH_ADD,\r
+       WR_LSO,\r
+       WR_UNKNOWN\r
+\r
+}      ib_wr_type_t;\r
+/*****/\r
+\r
+\r
+/****f* IBA Base: Types/ib_get_wr_type_str\r
+* NAME\r
+*      ib_get_wr_type_str\r
+*\r
+* DESCRIPTION\r
+*      Returns a string for the specified work request type\r
+*\r
+* SYNOPSIS\r
+*/\r
+AL_EXPORT const char* AL_API\r
+ib_get_wr_type_str(\r
+       IN                              uint8_t                                         wr_type );\r
+\r
+/*\r
+* PARAMETERS\r
+*      wr_type\r
+*              [in] Encoded work request type as defined in the\r
+work request attribute.\r
+\r
+* RETURN VALUES\r
+*      Pointer to the work request type string.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_wr_type_t\r
+*********/\r
+\r
+\r
+/****s* Access Layer/ib_local_ds_t\r
+* NAME\r
+*      ib_local_ds_t\r
+*\r
+* DESCRIPTION\r
+*      Local data segment information referenced by send and receive work\r
+*      requests.  This is used to specify local data buffers used as part of a\r
+*      work request.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_local_ds\r
+{\r
+       uint64_t                                vaddr;\r
+       uint32_t                                length;\r
+       uint32_t                                lkey;\r
+\r
+}      ib_local_ds_t;\r
+/*****/\r
+\r
+\r
+/****d* Access Layer/ib_send_opt_t\r
+* NAME\r
+*      ib_send_opt_t\r
+*\r
+* DESCRIPTION\r
+*      Optional flags used when posting send work requests.  These flags\r
+*      indicate specific processing for the send operation.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t                                       ib_send_opt_t;\r
+#define IB_SEND_OPT_IMMEDIATE          0x00000001\r
+#define IB_SEND_OPT_FENCE                      0x00000002\r
+#define IB_SEND_OPT_SIGNALED           0x00000004\r
+#define IB_SEND_OPT_SOLICITED          0x00000008\r
+#define IB_SEND_OPT_INLINE                     0x00000010\r
+#define IB_SEND_OPT_LOCAL                      0x00000020\r
+#define IB_SEND_OPT_TX_IP_CSUM         0x00000040\r
+#define IB_SEND_OPT_TX_TCP_UDP_CSUM    0x00000080\r
+\r
+#define IB_SEND_OPT_VEND_MASK          0xFFFF0000\r
+/*\r
+* VALUES\r
+*      The following flags determine the behavior of a work request when\r
+*      posted to the send side.\r
+*\r
+*      IB_SEND_OPT_IMMEDIATE\r
+*              Send immediate data with the given request.\r
+*\r
+*      IB_SEND_OPT_FENCE\r
+*              The operation is fenced.  Complete all pending send operations\r
+*              before processing this request.\r
+*\r
+*      IB_SEND_OPT_SIGNALED\r
+*              If the queue pair is configured for signaled completion, then\r
+*              generate a completion queue entry when this request completes.\r
+*\r
+*      IB_SEND_OPT_SOLICITED\r
+*              Set the solicited bit on the last packet of this request.\r
+*\r
+*      IB_SEND_OPT_INLINE\r
+*              Indicates that the requested send data should be copied into a VPD\r
+*              owned data buffer.  This flag permits the user to issue send operations\r
+*              without first needing to register the buffer(s) associated with the\r
+*              send operation.  Verb providers that support this operation may place\r
+*              vendor specific restrictions on the size of send operation that may\r
+*              be performed as inline.\r
+*\r
+*\r
+*      IB_SEND_OPT_LOCAL\r
+*              Indicates that a sent MAD request should be given to the local VPD for\r
+*              processing.  MADs sent using this option are not placed on the wire.\r
+*              This send option is only valid for MAD send operations.\r
+*\r
+*\r
+*      IB_SEND_OPT_VEND_MASK\r
+*              This mask indicates bits reserved in the send options that may be used\r
+*              by the verbs provider to indicate vendor specific options.  Bits set\r
+*              in this area of the send options are ignored by the Access Layer, but\r
+*              may have specific meaning to the underlying VPD.\r
+*\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_send_wr_t\r
+* NAME\r
+*      ib_send_wr_t\r
+*\r
+* DESCRIPTION\r
+*      Information used to submit a work request to the send queue of a queue\r
+*      pair.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_send_wr\r
+{\r
+       uint64_t                                        wr_id;\r
+       struct _ib_send_wr*                     p_next;\r
+       ib_local_ds_t*                          ds_array;\r
+       uint32_t                                        num_ds;\r
+       ib_wr_type_t                            wr_type;\r
+       ib_send_opt_t                           send_opt;\r
+       ib_net32_t                                      immediate_data;\r
+\r
+       union\r
+       {\r
+               union _send_dgrm\r
+               {\r
+                       struct _send_ud\r
+                       {\r
+                               ib_av_handle_t  h_av; \r
+                               ib_net32_t              remote_qp;\r
+                               ib_net32_t              remote_qkey;\r
+                               void*                   rsvd;\r
+                               uint16_t                pkey_index;\r
+                               void*                   header;\r
+                               int                             hlen;\r
+                               int                             mss;\r
+                       }       ud;\r
+\r
+                       struct _send_rd\r
+                       {\r
+                               ib_net32_t              remote_qp;\r
+                               ib_net32_t              remote_qkey;\r
+                               ib_net32_t              eecn;\r
+\r
+                       }       rd;\r
+\r
+                       struct _send_raw_ether\r
+                       {\r
+                               ib_net16_t              dest_lid;\r
+                               uint8_t                 path_bits;\r
+                               uint8_t                 sl;\r
+                               uint8_t                 max_static_rate;\r
+                               ib_net16_t              ether_type;\r
+       \r
+                       }       raw_ether;\r
+\r
+                       struct _send_raw_ipv6\r
+                       {\r
+                               ib_net16_t              dest_lid;\r
+                               uint8_t                 path_bits;\r
+                               uint8_t                 sl;\r
+                               uint8_t                 max_static_rate;\r
+       \r
+                       }       raw_ipv6;\r
+       \r
+               }       dgrm;\r
+\r
+               struct _send_remote_ops\r
+               {\r
+                       uint64_t                        vaddr;\r
+                       net32_t                         rkey;\r
+\r
+                       ib_net64_t                      atomic1;\r
+                       ib_net64_t                      atomic2;\r
+       \r
+               }       remote_ops;\r
+       };\r
+}      ib_send_wr_t;\r
+/*\r
+* FIELDS\r
+*      p_next\r
+*              A pointer used to chain work requests together.  This permits multiple\r
+*              work requests to be posted to a queue pair through a single function\r
+*              call.  This value is set to NULL to mark the end of the chain.\r
+*\r
+*      wr_id\r
+*              A 64-bit work request identifier that is returned to the consumer\r
+*              as part of the work completion.\r
+*\r
+*      wr_type\r
+*              The type of work request being submitted to the send queue.\r
+*\r
+*      send_opt\r
+*              Optional send control parameters.\r
+*\r
+*      num_ds\r
+*              Number of local data segments specified by this work request.\r
+*\r
+*      ds_array\r
+*              A reference to an array of local data segments used by the send\r
+*              operation.\r
+*\r
+*      immediate_data\r
+*              32-bit field sent as part of a message send or RDMA write operation.\r
+*              This field is only valid if the send_opt flag IB_SEND_OPT_IMMEDIATE\r
+*              has been set.\r
+*\r
+*      dgrm.ud.remote_qp\r
+*              Identifies the destination queue pair of an unreliable datagram send\r
+*              operation.\r
+*\r
+*      dgrm.ud.remote_qkey\r
+*              The qkey for the destination queue pair.\r
+*\r
+*      dgrm.ud.h_av\r
+*              An address vector that specifies the path information used to route\r
+*              the outbound datagram to the destination queue pair.\r
+*\r
+*      dgrm.ud.pkey_index\r
+*              The pkey index for this send work request.  This is valid only\r
+*              for IB_QPT_QP1 and IB_QPT_QP1_ALIAS QP types.  The work request\r
+*              is posted to using this pkey index build the GMP's BTH instead\r
+*              of the QP's pkey.\r
+*\r
+*      dgrm.ud.rsvd\r
+*              Reserved for use by the Access Layer.\r
+*\r
+*      dgrm.raw_ether.dest_lid\r
+*              The destination LID that will receive this raw ether send.\r
+*\r
+*      dgrm.raw_ether.path_bits\r
+*              path bits...\r
+*\r
+*      dgrm.raw_ether.sl\r
+*              service level...\r
+*\r
+*      dgrm.raw_ether.max_static_rate\r
+*              static rate...\r
+*\r
+*      dgrm.raw_ether.ether_type\r
+*              ether type...\r
+*\r
+*      dgrm.raw_ipv6.dest_lid\r
+*              The destination LID that will receive this raw ether send.\r
+*\r
+*      dgrm.raw_ipv6.path_bits\r
+*              path bits...\r
+*\r
+*      dgrm.raw_ipv6.sl\r
+*              service level...\r
+*\r
+*      dgrm.raw_ipv6.max_static_rate\r
+*              static rate...\r
+*\r
+*      remote_ops.vaddr\r
+*              The registered virtual memory address of the remote memory to access\r
+*              with an RDMA or atomic operation.\r
+*\r
+*      remote_ops.rkey\r
+*              The rkey associated with the specified remote vaddr. This data must\r
+*              be presented exactly as obtained from the remote node. No swapping\r
+*              of data must be performed.\r
+*\r
+*      atomic1\r
+*              The first operand for an atomic operation.\r
+*\r
+*      atomic2\r
+*              The second operand for an atomic operation.\r
+*\r
+* NOTES\r
+*      The format of data sent over the fabric is user-defined and is considered\r
+*      opaque to the access layer.  The sole exception to this are MADs posted\r
+*      to a MAD QP service.  MADs are expected to match the format defined by\r
+*      the Infiniband specification and must be in network-byte order when posted\r
+*      to the MAD QP service.\r
+*\r
+* SEE ALSO\r
+*      ib_wr_type_t, ib_local_ds_t, ib_send_opt_t\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_recv_wr_t\r
+* NAME\r
+*      ib_recv_wr_t\r
+*\r
+* DESCRIPTION\r
+*      Information used to submit a work request to the receive queue of a queue\r
+*      pair.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_recv_wr\r
+{\r
+       TO_LONG_PTR(struct _ib_recv_wr*, p_next);\r
+       uint64_t                                        wr_id;\r
+       uint32_t                                        num_ds;\r
+       TO_LONG_PTR(ib_local_ds_t*,     ds_array);\r
+\r
+}      ib_recv_wr_t;\r
+/*\r
+* FIELDS\r
+*      p_next\r
+*              A pointer used to chain work requests together.  This permits multiple\r
+*              work requests to be posted to a queue pair through a single function\r
+*              call.  This value is set to NULL to mark the end of the chain.\r
+*\r
+*      wr_id\r
+*              A 64-bit work request identifier that is returned to the consumer\r
+*              as part of the work completion.\r
+*\r
+*      num_ds\r
+*              Number of local data segments specified by this work request.\r
+*\r
+*      ds_array\r
+*              A reference to an array of local data segments used by the send\r
+*              operation.\r
+*\r
+* SEE ALSO\r
+*      ib_local_ds_t\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_bind_wr_t\r
+* NAME\r
+*      ib_bind_wr_t\r
+*\r
+* DESCRIPTION\r
+*      Information used to submit a memory window bind work request to the send\r
+*      queue of a queue pair.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_bind_wr\r
+{\r
+       uint64_t                                wr_id;\r
+       ib_send_opt_t                   send_opt;\r
+\r
+       TO_LONG_PTR(ib_mr_handle_t, h_mr);\r
+       ib_access_t                             access_ctrl;\r
+       net32_t                                 current_rkey;\r
+\r
+       ib_local_ds_t                   local_ds;\r
+\r
+}      ib_bind_wr_t;\r
+/*\r
+* FIELDS\r
+*      wr_id\r
+*              A 64-bit work request identifier that is returned to the consumer\r
+*              as part of the work completion.\r
+*\r
+*      send_opt\r
+*              Optional send control parameters.\r
+*\r
+*      h_mr\r
+*              Handle to the memory region to which this window is being bound.\r
+*\r
+*      access_ctrl\r
+*              Access rights for this memory window.\r
+*\r
+*      current_rkey\r
+*              The current rkey assigned to this window for remote access.\r
+*\r
+*      local_ds\r
+*              A reference to a local data segment used by the bind operation.\r
+*\r
+* SEE ALSO\r
+*      ib_send_opt_t, ib_access_t, ib_local_ds_t\r
+*****/\r
+\r
+\r
+/****d* Access Layer/ib_wc_status_t\r
+* NAME\r
+*      ib_wc_status_t\r
+*\r
+* DESCRIPTION\r
+*      Indicates the status of a completed work request.  These VALUES are\r
+*      returned to the user when retrieving completions.  Note that success is\r
+*      identified as IB_WCS_SUCCESS, which is always zero.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_wc_status_t\r
+{\r
+       IB_WCS_SUCCESS,\r
+       IB_WCS_LOCAL_LEN_ERR,\r
+       IB_WCS_LOCAL_OP_ERR,\r
+       IB_WCS_LOCAL_PROTECTION_ERR,\r
+       IB_WCS_WR_FLUSHED_ERR,\r
+       IB_WCS_MEM_WINDOW_BIND_ERR,\r
+       IB_WCS_REM_ACCESS_ERR,\r
+       IB_WCS_REM_OP_ERR,\r
+       IB_WCS_RNR_RETRY_ERR,\r
+       IB_WCS_TIMEOUT_RETRY_ERR,\r
+       IB_WCS_REM_INVALID_REQ_ERR,\r
+       IB_WCS_BAD_RESP_ERR,\r
+       IB_WCS_LOCAL_ACCESS_ERR,\r
+       IB_WCS_GENERAL_ERR,\r
+       IB_WCS_UNMATCHED_RESPONSE,                      /* InfiniBand Access Layer */\r
+       IB_WCS_CANCELED,                                        /* InfiniBand Access Layer */\r
+       IB_WCS_REM_ABORT_ERR,\r
+       IB_WCS_UNKNOWN                                          /* Must be last. */\r
+\r
+}      ib_wc_status_t;\r
+\r
+/*\r
+* VALUES\r
+*      IB_WCS_SUCCESS\r
+*              Work request completed successfully.\r
+*\r
+*      IB_WCS_MAD\r
+*              The completed work request was associated with a managmenet datagram\r
+*              that requires post processing.  The MAD will be returned to the user\r
+*              through a callback once all post processing has completed.\r
+*\r
+*      IB_WCS_LOCAL_LEN_ERR\r
+*              Generated for a work request posted to the send queue when the\r
+*              total of the data segment lengths exceeds the message length of the\r
+*              channel.  Generated for a work request posted to the receive queue when\r
+*              the total of the data segment lengths is too small for a\r
+*              valid incoming message.\r
+*\r
+*      IB_WCS_LOCAL_OP_ERR\r
+*              An internal QP consistency error was generated while processing this\r
+*              work request.  This may indicate that the QP was in an incorrect state\r
+*              for the requested operation.\r
+*\r
+*      IB_WCS_LOCAL_PROTECTION_ERR\r
+*              The data segments of the locally posted work request did not refer to\r
+*              a valid memory region.  The memory may not have been properly\r
+*              registered for the requested operation.\r
+*\r
+*      IB_WCS_WR_FLUSHED_ERR\r
+*              The work request was flushed from the QP before being completed.\r
+*\r
+*      IB_WCS_MEM_WINDOW_BIND_ERR\r
+*              A memory window bind operation failed due to insufficient access\r
+*              rights.\r
+*\r
+*      IB_WCS_REM_ACCESS_ERR,\r
+*              A protection error was detected at the remote node for a RDMA or atomic\r
+*              operation.\r
+*\r
+*      IB_WCS_REM_OP_ERR,\r
+*              The operation could not be successfully completed at the remote node.\r
+*              This may indicate that the remote QP was in an invalid state or\r
+*              contained an invalid work request.\r
+*\r
+*      IB_WCS_RNR_RETRY_ERR,\r
+*              The RNR retry count was exceeded while trying to send this message.\r
+*\r
+*      IB_WCS_TIMEOUT_RETRY_ERR\r
+*              The local transport timeout counter expired while trying to send this\r
+*              message.\r
+*\r
+*      IB_WCS_REM_INVALID_REQ_ERR,\r
+*              The remote node detected an invalid message on the channel.  This error\r
+*              is usually a result of one of the following:\r
+*                      - The operation was not supported on receive queue.\r
+*                      - There was insufficient buffers to receive a new RDMA request.\r
+*                      - There was insufficient buffers to receive a new atomic operation.\r
+*                      - An RDMA request was larger than 2^31 bytes.\r
+*\r
+*      IB_WCS_BAD_RESP_ERR,\r
+*              An unexpected transport layer opcode was returned\r
+*              by the responder.\r
+*\r
+*      IB_WCS_LOCAL_ACCESS_ERR,\r
+*              A protection error occurred on a local data buffer\r
+*              during the processing of a RDMA Write with Immediate Data \r
+*              operation sent from the remote node.\r
+*\r
+*      IB_WCS_REM_ABORT_ERR,\r
+*              The operation was aborted (e.g., For UD QPs associated with an SRQ, \r
+*              the responder aborted the operation).\r
+*\r
+*      IB_WCS_REM_ABORT_ERR,\r
+*              The operation was aborted (e.g., For UD QPs associated with an SRQ, \r
+*              the responder aborted the operation).\r
+*\r
+*      IB_WCS_UNMATCHED_RESPONSE\r
+*              A response MAD was received for which there was no matching send.  The\r
+*              send operation may have been canceled by the user or may have timed\r
+*              out.\r
+*\r
+*      IB_WCS_CANCELED\r
+*              The completed work request was canceled by the user.\r
+ *\r
+ *     IB_WCS_GENERAL_ERR,\r
+ *             Any other error\r
+ *\r
+*****/\r
+\r
+\r
+\r
+/****f* IBA Base: Types/ib_get_wc_status_str\r
+* NAME\r
+*      ib_get_wc_status_str\r
+*\r
+* DESCRIPTION\r
+*      Returns a string for the specified work completion status.\r
+*\r
+* SYNOPSIS\r
+*/\r
+AL_EXPORT const char* AL_API\r
+ib_get_wc_status_str(\r
+       IN                              ib_wc_status_t                          wc_status );\r
+/*\r
+* PARAMETERS\r
+*      wc_status\r
+*              [in] work completion status value\r
+*\r
+* RETURN VALUES\r
+*      Pointer to the work completion status description string.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+\r
+/****d* Access Layer/ib_wc_type_t\r
+* NAME\r
+*      ib_wc_type_t\r
+*\r
+* DESCRIPTION\r
+*      Indicates the type of work completion.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_wc_type_t\r
+{\r
+       IB_WC_SEND,\r
+       IB_WC_RDMA_WRITE,\r
+       IB_WC_RDMA_READ,\r
+       IB_WC_COMPARE_SWAP,\r
+       IB_WC_FETCH_ADD,\r
+       IB_WC_MW_BIND,\r
+       IB_WC_UNKNOWN1,\r
+       IB_WC_RECV = (1 << 7),\r
+       IB_WC_RECV_RDMA_WRITE,\r
+       IB_WR_LSO,\r
+       IB_WC_UNKNOWN2\r
+\r
+}      ib_wc_type_t;\r
+/*****/\r
+\r
+\r
+/****f* IBA Base: Types/ib_get_wc_type_str\r
+* NAME\r
+*      ib_get_wc_type_str\r
+*\r
+* DESCRIPTION\r
+*      Returns a string for the specified work completion type.\r
+*\r
+* SYNOPSIS\r
+*/\r
+AL_EXPORT const char* AL_API\r
+ib_get_wc_type_str(\r
+       IN                              ib_wc_type_t                            wc_type );\r
+/*\r
+* PARAMETERS\r
+*      wc_type\r
+*              [in] work completion type value\r
+*\r
+* RETURN VALUES\r
+*      Pointer to the work completion type description string.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+\r
+/****d* Access Layer/ib_recv_opt_t\r
+* NAME\r
+*      ib_recv_opt_t\r
+*\r
+* DESCRIPTION\r
+*      Indicates optional fields valid in a receive work completion.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t                                       ib_recv_opt_t;\r
+#define        IB_RECV_OPT_IMMEDIATE           0x00000001\r
+#define IB_RECV_OPT_FORWARD                    0x00000002\r
+#define IB_RECV_OPT_GRH_VALID          0x00000004\r
+#define IB_RECV_OPT_VEND_MASK          0xFFFF0000\r
+/*\r
+* VALUES\r
+*      IB_RECV_OPT_IMMEDIATE\r
+*              Indicates that immediate data is valid for this work completion.\r
+*\r
+*      IB_RECV_OPT_FORWARD\r
+*              Indicates that the received trap should be forwarded to the SM.\r
+*\r
+*      IB_RECV_OPT_GRH_VALID\r
+*              Indicates presence of the global route header. When set, the first\r
+*              40 bytes received are the GRH.\r
+*\r
+*      IB_RECV_OPT_VEND_MASK\r
+*              This mask indicates bits reserved in the receive options that may be\r
+*              used by the verbs provider to indicate vendor specific options.  Bits\r
+*              set in this area of the receive options are ignored by the Access Layer,\r
+*              but may have specific meaning to the underlying VPD.\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_wc_t\r
+* NAME\r
+*      ib_wc_t\r
+*\r
+* DESCRIPTION\r
+*      Work completion information.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_wc\r
+{\r
+       TO_LONG_PTR(struct _ib_wc*, p_next);\r
+       uint64_t                                wr_id;\r
+       ib_wc_type_t                    wc_type;\r
+\r
+       uint32_t                                length;\r
+       uint64_t                                vendor_specific;\r
+       ib_wc_status_t                  status;\r
+\r
+       union _wc_recv\r
+       {\r
+               struct _wc_conn\r
+               {\r
+                       ib_recv_opt_t   recv_opt;\r
+                       ib_net32_t              immediate_data;\r
+\r
+               }       conn;\r
+\r
+               struct _wc_ud\r
+               {\r
+                       ib_recv_opt_t   recv_opt;\r
+                       ib_net32_t              immediate_data;\r
+                       ib_net32_t              remote_qp;\r
+                       uint16_t                pkey_index;\r
+                       ib_net16_t              remote_lid;\r
+                       uint8_t                 remote_sl;\r
+                       uint8_t                 path_bits;\r
+                       uint8_t                 csum_ok;\r
+\r
+               }       ud;\r
+\r
+               struct _wc_rd\r
+               {\r
+                       ib_net32_t      remote_eecn;\r
+                       ib_net32_t      remote_qp;\r
+                       ib_net16_t      remote_lid;\r
+                       uint8_t         remote_sl;\r
+                       uint32_t        free_cnt;\r
+\r
+               }       rd;\r
+\r
+               struct _wc_raw_ipv6\r
+               {\r
+                       ib_net16_t              remote_lid;\r
+                       uint8_t                 remote_sl;\r
+                       uint8_t                 path_bits;\r
+\r
+               }       raw_ipv6;\r
+\r
+               struct _wc_raw_ether\r
+               {\r
+                       ib_net16_t              remote_lid;\r
+                       uint8_t                 remote_sl;\r
+                       uint8_t                 path_bits;\r
+                       ib_net16_t              ether_type;\r
+\r
+               }       raw_ether;\r
+\r
+       }       recv;\r
+\r
+}      ib_wc_t;\r
+/*\r
+* FIELDS\r
+*      p_next\r
+*              A pointer used to chain work completions.  This permits multiple\r
+*              work completions to be retrieved from a completion queue through a\r
+*              single function call.  This value is set to NULL to mark the end of\r
+*              the chain.\r
+*\r
+*      wr_id\r
+*              The 64-bit work request identifier that was specified when posting the\r
+*              work request.\r
+*\r
+*      wc_type\r
+*              Indicates the type of work completion.\r
+*\r
+*\r
+*      length\r
+*              The total length of the data sent or received with the work request.\r
+*\r
+*      status\r
+*              The result of the work request.\r
+*\r
+*      vendor_specific\r
+*              HCA vendor specific information returned as part of the completion.\r
+*\r
+*      recv.conn.recv_opt\r
+*              Indicates optional fields valid as part of a work request that\r
+*              completed on a connected (reliable or unreliable) queue pair.\r
+*\r
+*      recv.conn.immediate_data\r
+*              32-bit field received as part of an inbound message on a connected\r
+*              queue pair.  This field is only valid if the recv_opt flag\r
+*              IB_RECV_OPT_IMMEDIATE has been set.\r
+*\r
+*      recv.ud.recv_opt\r
+*              Indicates optional fields valid as part of a work request that\r
+*              completed on an unreliable datagram queue pair.\r
+*\r
+*      recv.ud.immediate_data\r
+*              32-bit field received as part of an inbound message on a unreliable\r
+*              datagram queue pair.  This field is only valid if the recv_opt flag\r
+*              IB_RECV_OPT_IMMEDIATE has been set.\r
+*\r
+*      recv.ud.remote_qp\r
+*              Identifies the source queue pair of a received datagram.\r
+*\r
+*      recv.ud.pkey_index\r
+*              The pkey index for the source queue pair. This is valid only for\r
+*              GSI type QP's.\r
+*\r
+*      recv.ud.remote_lid\r
+*              The source LID of the received datagram.\r
+*\r
+*      recv.ud.remote_sl\r
+*              The service level used by the source of the received datagram.\r
+*\r
+*      recv.ud.path_bits\r
+*              path bits...\r
+*\r
+*      recv.rd.remote_eecn\r
+*              The remote end-to-end context number that sent the received message.\r
+*\r
+*      recv.rd.remote_qp\r
+*              Identifies the source queue pair of a received message.\r
+*\r
+*      recv.rd.remote_lid\r
+*              The source LID of the received message.\r
+*\r
+*      recv.rd.remote_sl\r
+*              The service level used by the source of the received message.\r
+*\r
+*      recv.rd.free_cnt\r
+*              The number of available entries in the completion queue.  Reliable\r
+*              datagrams may complete out of order, so this field may be used to\r
+*              determine the number of additional completions that may occur.\r
+*\r
+*      recv.raw_ipv6.remote_lid\r
+*              The source LID of the received message.\r
+*\r
+*      recv.raw_ipv6.remote_sl\r
+*              The service level used by the source of the received message.\r
+*\r
+*      recv.raw_ipv6.path_bits\r
+*              path bits...\r
+*\r
+*      recv.raw_ether.remote_lid\r
+*              The source LID of the received message.\r
+*\r
+*      recv.raw_ether.remote_sl\r
+*              The service level used by the source of the received message.\r
+*\r
+*      recv.raw_ether.path_bits\r
+*              path bits...\r
+*\r
+*      recv.raw_ether.ether_type\r
+*              ether type...\r
+* NOTES\r
+*      When the work request completes with error, the only values that the\r
+*      consumer can depend on are the wr_id field, and the status of the\r
+*      operation.\r
+*\r
+*      If the consumer is using the same CQ for completions from more than\r
+*      one type of QP (i.e Reliable Connected, Datagram etc), then the consumer\r
+*      must have additional information to decide what fields of the union are\r
+*      valid.\r
+* SEE ALSO\r
+*      ib_wc_type_t, ib_qp_type_t, ib_wc_status_t, ib_recv_opt_t\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_mr_create_t\r
+* NAME\r
+*      ib_mr_create_t\r
+*\r
+* DESCRIPTION\r
+*      Information required to create a registered memory region.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_mr_create\r
+{\r
+       TO_LONG_PTR(void*,              vaddr);\r
+       uint64_t                                length;\r
+       ib_access_t                             access_ctrl;\r
+\r
+}      ib_mr_create_t;\r
+/*\r
+* FIELDS\r
+*      vaddr\r
+*              Starting virtual address of the region being registered.\r
+*\r
+*      length\r
+*              Length of the buffer to register.\r
+*\r
+*      access_ctrl\r
+*              Access rights of the registered region.\r
+*\r
+* SEE ALSO\r
+*      ib_access_t\r
+*****/\r
+\r
+#ifdef CL_KERNEL\r
+\r
+/****s* Access Layer/mlnx_fmr_create_t\r
+* NAME\r
+*      mlnx_fmr_create_t\r
+*\r
+* DESCRIPTION\r
+*      Information required to create a Mellanox fast memory region.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _mlnx_fmr_create\r
+{\r
+       int                                     max_pages;\r
+       int                                     max_maps;\r
+       uint8_t                         page_size;\r
+       ib_access_t                     access_ctrl;\r
+\r
+}      mlnx_fmr_create_t;\r
+/*\r
+* FIELDS\r
+*      max_pages\r
+*              max pages in the region.\r
+*\r
+*      max_maps\r
+*              max times, the region can be mapped before remapping.\r
+*\r
+*      page_size\r
+*              log2 of the page size (e.g. 12 for 4KB).\r
+*\r
+*      access_ctrl\r
+*              Access rights of the registered region.\r
+*\r
+* NOTES\r
+*      This is a Mellanox specific extension to verbs.\r
+*\r
+* SEE ALSO\r
+*      ib_access_t\r
+*****/\r
+\r
+\r
+/****s* Access Layer/mlnx_fmr_pool_create_t\r
+* NAME\r
+*      mlnx_fmr_pool_create_t\r
+*\r
+* DESCRIPTION\r
+*      Information required to create a Mellanox fast memory region pool.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _mlnx_fmr_pool_create\r
+{\r
+       int                             max_pages_per_fmr;\r
+       uint8_t                 page_size;      /* really - page_shift, log2 of page_size */\r
+       enum ib_access_flags    access_ctrl;\r
+       int                             pool_size;\r
+       int                             dirty_watermark;\r
+       void                    (*flush_function)(mlnx_fmr_pool_handle_t h_pool, void *arg);\r
+       void                            *flush_arg;\r
+       boolean_t                       cache;\r
+}      mlnx_fmr_pool_create_t;\r
+/*\r
+* FIELDS\r
+*      max_pages\r
+*              max pages in the region.\r
+*\r
+*      max_maps\r
+*              max times, the region can be mapped before remapping.\r
+*\r
+*      page_size\r
+*              log2 of the page size (e.g. 12 for 4KB).\r
+*\r
+*      access_ctrl\r
+*              Access rights of the registered region.\r
+*\r
+* NOTES\r
+*      This is a Mellanox specific extension to verbs.\r
+*\r
+* SEE ALSO\r
+*      ib_access_t\r
+*****/\r
+#endif\r
+\r
+/****s* Access Layer/ib_phys_range_t\r
+* NAME\r
+*      ib_phys_range_t\r
+*\r
+* DESCRIPTION\r
+*      Information describing a physical memory range.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_phys_range\r
+{\r
+       uint64_t                                base_addr;\r
+       uint64_t                                size;\r
+\r
+}      ib_phys_range_t;\r
+/*\r
+* FIELDS\r
+*      base_addr\r
+*              Physical address of the base of the memory range.\r
+*\r
+*      size\r
+*              size, in bytes, of the memory range.\r
+*\r
+* NOTES\r
+*      The base address must be start and end on an HCA-supported page boundary.\r
+*\r
+* SEE ALSO\r
+*      ib_phys_create_t\r
+*********/\r
+\r
+\r
+/****s* Access Layer/ib_phys_create_t\r
+* NAME\r
+*      ib_phys_create_t\r
+*\r
+* DESCRIPTION\r
+*      Information required to create a physical memory region.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_phys_create\r
+{\r
+       uint64_t                                        length;\r
+       uint32_t                                        num_ranges;\r
+       ib_phys_range_t*                        range_array;\r
+       uint32_t                                        buf_offset;\r
+       uint32_t                                        hca_page_size;\r
+       ib_access_t                                     access_ctrl;\r
+\r
+}      ib_phys_create_t;\r
+/*\r
+* FIELDS\r
+*      length\r
+*              The length of the memory region in bytes.\r
+*\r
+*      num_ranges\r
+*              Number of ib_phys_range structures listed in the specified range array.\r
+*\r
+*      range_array\r
+*              An array of ib_phys_range structures to be registered as a single memory\r
+*              region.\r
+*\r
+*      buf_offset\r
+*              The offset into the first physical memory range of the specified memory\r
+*              region on which to start the virtual address.\r
+*\r
+*      hca_page_size\r
+*              The HCA page size to use to register the memory.\r
+*\r
+*      access_ctrl\r
+*              Access rights of the registered region.\r
+*\r
+* SEE ALSO\r
+*      ib_access_t\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_mr_attr_t\r
+* NAME\r
+*      ib_mr_attr_t\r
+*\r
+* DESCRIPTION\r
+*      Attributes of a registered memory region.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_mr_attr\r
+{\r
+       TO_LONG_PTR(ib_pd_handle_t, h_pd);\r
+       uint64_t                                local_lb;\r
+       uint64_t                                local_ub;\r
+       uint64_t                                remote_lb;\r
+       uint64_t                                remote_ub;\r
+       ib_access_t                             access_ctrl;\r
+       net32_t                                 lkey;\r
+       net32_t                                 rkey;\r
+\r
+}      ib_mr_attr_t;\r
+/*\r
+* DESCRIPTION\r
+*      h_pd\r
+*              Handle to the protection domain for this memory region.\r
+*\r
+*      local_lb\r
+*              The virtual address of the lower bound of protection for local\r
+*              memory access.  This is always a 64-bit quantity to support registering\r
+*              more than 4GB of memory on 32-bit systems with PAE.\r
+*\r
+*      local_ub\r
+*              The virtual address of the upper bound of protection for local\r
+*              memory access.  This is always a 64-bit quantity to support registering\r
+*              more than 4GB of memory on 32-bit systems with PAE.\r
+*\r
+*      remote_lb\r
+*              The virtual address of the lower bound of protection for remote\r
+*              memory access.  This is always a 64-bit quantity to support registering\r
+*              more than 4GB of memory on 32-bit systems with PAE.\r
+*\r
+*      remote_ub\r
+*              The virtual address of the upper bound of protection for remote\r
+*              memory access.  This is always a 64-bit quantity to support registering\r
+*              more than 4GB of memory on 32-bit systems with PAE.\r
+*\r
+*      access_ctrl\r
+*              Access rights for the specified memory region.\r
+*\r
+*      lkey\r
+*              The lkey associated with this memory region.\r
+*\r
+*      rkey\r
+*              The rkey associated with this memory region.\r
+*\r
+* NOTES\r
+*      The remote_lb, remote_ub, and rkey are only valid if remote memory access\r
+*      is enabled for this memory region.\r
+*\r
+* SEE ALSO\r
+*      ib_access_t\r
+*****/\r
+\r
+\r
+/****d* Access Layer/ib_ca_mod_t\r
+* NAME\r
+*      ib_ca_mod_t -- Modify port attributes and error counters\r
+*\r
+* DESCRIPTION\r
+*      Specifies modifications to the port attributes of a channel adapter.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t                                                       ib_ca_mod_t;\r
+#define IB_CA_MOD_IS_CM_SUPPORTED                      0x00000001\r
+#define IB_CA_MOD_IS_SNMP_SUPPORTED                    0x00000002\r
+#define        IB_CA_MOD_IS_DEV_MGMT_SUPPORTED         0x00000004\r
+#define        IB_CA_MOD_IS_VEND_SUPPORTED                     0x00000008\r
+#define        IB_CA_MOD_IS_SM                                         0x00000010\r
+#define IB_CA_MOD_IS_SM_DISABLED                       0x00000020\r
+#define IB_CA_MOD_QKEY_CTR                                     0x00000040\r
+#define IB_CA_MOD_PKEY_CTR                                     0x00000080\r
+#define IB_CA_MOD_IS_NOTICE_SUPPORTED          0x00000100\r
+#define IB_CA_MOD_IS_TRAP_SUPPORTED                    0x00000200\r
+#define IB_CA_MOD_IS_APM_SUPPORTED                     0x00000400\r
+#define IB_CA_MOD_IS_SLMAP_SUPPORTED           0x00000800\r
+#define IB_CA_MOD_IS_PKEY_NVRAM_SUPPORTED      0x00001000\r
+#define IB_CA_MOD_IS_MKEY_NVRAM_SUPPORTED      0x00002000\r
+#define IB_CA_MOD_IS_SYSGUID_SUPPORTED         0x00004000\r
+#define IB_CA_MOD_IS_DR_NOTICE_SUPPORTED       0x00008000\r
+#define IB_CA_MOD_IS_BOOT_MGMT_SUPPORTED       0x00010000\r
+#define IB_CA_MOD_IS_CAPM_NOTICE_SUPPORTED     0x00020000\r
+#define IB_CA_MOD_IS_REINIT_SUPORTED           0x00040000\r
+#define IB_CA_MOD_IS_LEDINFO_SUPPORTED         0x00080000\r
+#define IB_CA_MOD_SHUTDOWN_PORT                                0x00100000\r
+#define IB_CA_MOD_INIT_TYPE_VALUE                      0x00200000\r
+#define IB_CA_MOD_SYSTEM_IMAGE_GUID                    0x00400000\r
+#define IB_CA_MOD_IS_CLIENT_REREGISTER_SUPPORTED       0x00800000\r
+#define IB_CA_MOD_RESERVED_MASK                                0xFF000000\r
+/*\r
+* VALUES\r
+*      IB_CA_MOD_IS_CM_SUPPORTED\r
+*              Indicates if there is a communication manager accessible through\r
+*              the port.\r
+*\r
+*      IB_CA_MOD_IS_SNMP_SUPPORTED\r
+*              Indicates if there is an SNMP agent accessible through the port.\r
+*\r
+*      IB_CA_MOD_IS_DEV_MGMT_SUPPORTED\r
+*              Indicates if there is a device management agent accessible\r
+*              through the port.\r
+*\r
+*      IB_CA_MOD_IS_VEND_SUPPORTED\r
+*              Indicates if there is a vendor supported agent accessible\r
+*              through the port.\r
+*\r
+*      IB_CA_MOD_IS_SM\r
+*              Indicates if there is a subnet manager accessible through\r
+*              the port.\r
+*\r
+*      IB_CA_MOD_IS_SM_DISABLED\r
+*              Indicates if the port has been disabled for configuration by the\r
+*              subnet manager.\r
+*\r
+*      IB_CA_MOD_QKEY_CTR\r
+*              Used to reset the qkey violation counter associated with the\r
+*              port.\r
+*\r
+*      IB_CA_MOD_PKEY_CTR\r
+*              Used to reset the pkey violation counter associated with the\r
+*              port.\r
+*\r
+*      IB_CA_MOD_IS_NOTICE_SUPPORTED\r
+*              Indicates that this CA supports ability to generate Notices for\r
+*              Port State changes. (only applicable to switches)\r
+*\r
+*      IB_CA_MOD_IS_TRAP_SUPPORTED\r
+*              Indicates that this management port supports ability to generate\r
+*              trap messages. (only applicable to switches)\r
+*\r
+*      IB_CA_MOD_IS_APM_SUPPORTED\r
+*              Indicates that this port is capable of performing Automatic\r
+*              Path Migration.\r
+*\r
+*      IB_CA_MOD_IS_SLMAP_SUPPORTED\r
+*              Indicates this port supports SLMAP capability.\r
+*\r
+*      IB_CA_MOD_IS_PKEY_NVRAM_SUPPORTED\r
+*              Indicates that PKEY is supported in NVRAM\r
+*\r
+*      IB_CA_MOD_IS_MKEY_NVRAM_SUPPORTED\r
+*              Indicates that MKEY is supported in NVRAM\r
+*\r
+*      IB_CA_MOD_IS_SYSGUID_SUPPORTED\r
+*              Indicates System Image GUID support.\r
+*\r
+*      IB_CA_MOD_IS_DR_NOTICE_SUPPORTED\r
+*              Indicate support for generating Direct Routed Notices\r
+*\r
+*      IB_CA_MOD_IS_BOOT_MGMT_SUPPORTED\r
+*              Indicates support for Boot Management\r
+*\r
+*      IB_CA_MOD_IS_CAPM_NOTICE_SUPPORTED\r
+*              Indicates capability to generate notices for changes to CAPMASK\r
+*\r
+*      IB_CA_MOD_IS_REINIT_SUPORTED\r
+*              Indicates type of node init supported. Refer to Chapter 14 for\r
+*              Initialization actions.\r
+*\r
+*      IB_CA_MOD_IS_LEDINFO_SUPPORTED\r
+*              Indicates support for LED info.\r
+*\r
+*      IB_CA_MOD_SHUTDOWN_PORT\r
+*              Used to modify the port active indicator.\r
+*\r
+*      IB_CA_MOD_INIT_TYPE_VALUE\r
+*              Used to modify the init_type value for the port.\r
+*\r
+*      IB_CA_MOD_SYSTEM_IMAGE_GUID\r
+*              Used to modify the system image GUID for the port.\r
+*\r
+*      IB_CA_MOD_IS_CLIENT_REREGISTER_SUPPORTED\r
+*              Used to modify the system image GUID for the port.\r
+*\r
+*      IB_CA_MOD_RESERVED_MASK\r
+*              Mask of all the reserved bits.  If any of these bits are set\r
+*              ib_modify_ca will return IB_INVALID_PARAMETER.\r
+*****/\r
+\r
+\r
+/****d* Access Layer/ib_mr_mod_t\r
+* NAME\r
+*      ib_mr_mod_t\r
+*\r
+* DESCRIPTION\r
+*      Mask used to specify which attributes of a registered memory region are\r
+*      being modified.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t                                               ib_mr_mod_t;\r
+#define IB_MR_MOD_ADDR                                 0x00000001\r
+#define IB_MR_MOD_PD                                   0x00000002\r
+#define IB_MR_MOD_ACCESS                               0x00000004\r
+/*\r
+* PARAMETERS\r
+*      IB_MEM_MOD_ADDR\r
+*              The address of the memory region is being modified.\r
+*\r
+*      IB_MEM_MOD_PD\r
+*              The protection domain associated with the memory region is being\r
+*              modified.\r
+*\r
+*      IB_MEM_MOD_ACCESS\r
+*              The access rights the memory region are being modified.\r
+*****/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_STATE_INIT\r
+* NAME\r
+*      IB_SMINFO_STATE_INIT\r
+*\r
+* DESCRIPTION\r
+*      Encoded state value used in the SMInfo attribute.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_STATE_INIT                                   4\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_HANDOVER\r
+* NAME\r
+*      IB_SMINFO_ATTR_MOD_HANDOVER\r
+*\r
+* DESCRIPTION\r
+*      Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_ATTR_MOD_HANDOVER            (CL_NTOH32(0x000001))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_ACKNOWLEDGE\r
+* NAME\r
+*      IB_SMINFO_ATTR_MOD_ACKNOWLEDGE\r
+*\r
+* DESCRIPTION\r
+*      Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_ATTR_MOD_ACKNOWLEDGE         (CL_NTOH32(0x000002))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_DISABLE\r
+* NAME\r
+*      IB_SMINFO_ATTR_MOD_DISABLE\r
+*\r
+* DESCRIPTION\r
+*      Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_ATTR_MOD_DISABLE                     (CL_NTOH32(0x000003))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_STANDBY\r
+* NAME\r
+*      IB_SMINFO_ATTR_MOD_STANDBY\r
+*\r
+* DESCRIPTION\r
+*      Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_ATTR_MOD_STANDBY                     (CL_NTOH32(0x000004))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_DISCOVER\r
+* NAME\r
+*      IB_SMINFO_ATTR_MOD_DISCOVER\r
+*\r
+* DESCRIPTION\r
+*      Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_ATTR_MOD_DISCOVER                    (CL_NTOH32(0x000005))\r
+/**********/\r
+\r
+/****s* Access Layer/ib_ci_op_t\r
+* NAME\r
+*      ib_ci_op_t\r
+*\r
+* DESCRIPTION\r
+*      A structure used for vendor specific CA interface communication.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_ci_op\r
+{\r
+       IN                              uint32_t                                        command;\r
+       IN                              uint32_t                                        buf_size;\r
+       IN                              uint32_t                                        buf_info;\r
+       IN      OUT                     int32_t                                         status;\r
+       IN      OUT                     TO_LONG_PTR(void*,                      p_buf) OPTIONAL; // Do not put it last in the structure, because of memory alignment\r
+               OUT                     uint32_t                                        num_bytes_ret;\r
+       \r
+\r
+}      ib_ci_op_t;\r
+/*\r
+* FIELDS\r
+*      command\r
+*              A command code that is understood by the verbs provider.\r
+*\r
+*      status\r
+*              The completion status from the verbs provider.  This field should be\r
+*              initialize to indicate an error to allow detection and cleanup in\r
+*              case a communication error occurs between user-mode and kernel-mode.\r
+*\r
+*      buf_size\r
+*              The size of the buffer in bytes.\r
+*\r
+*      buf_info\r
+*              Additional buffer information\r
+*\r
+*      p_buf\r
+*              A reference to a buffer containing vendor specific data.  The verbs\r
+*              provider must not access pointers in the p_buf between user-mode and\r
+*              kernel-mode.  Any pointers embedded in the p_buf are invalidated by\r
+*              the user-mode/kernel-mode transition.\r
+*\r
+*      num_bytes_ret\r
+*              The size in bytes of the vendor specific data returned in the buffer.\r
+*              This field is set by the verbs provider.  The verbs provider should\r
+*              verify that the buffer size is sufficient to hold the data being\r
+*              returned.\r
+*\r
+* NOTES\r
+*      This structure is provided to allow the exchange of vendor specific\r
+*      data between the originator and the verbs provider.  Users of this\r
+*      structure are expected to know the format of data in the p_buf based\r
+*      on the structure command field or the usage context.\r
+*****/\r
+\r
+\r
+#endif // __IB_TYPES_EXTENDED_H__\r
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/cl_dispatcher.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/cl_dispatcher.h
new file mode 100644 (file)
index 0000000..b402ef5
--- /dev/null
@@ -0,0 +1,673 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: cl_dispatcher.h 474 2006-08-31 08:57:19Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of dispatcher abstraction.
+ * 
+ * Environment:
+ *     All
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _CL_DISPATCHER_H_
+#define _CL_DISPATCHER_H_
+
+
+#include <complib/cl_atomic.h>
+#include <complib/cl_threadpool.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_qpool.h>
+#include <complib/cl_spinlock.h>
+#include <complib/cl_ptr_vector.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* Component Library/Dispatcher
+* NAME
+*      Dispatcher
+*
+* DESCRIPTION
+*      The Dispatcher provides a facility for message routing to
+*      asynchronous worker threads.
+*
+*      The Dispatcher functions operate on a cl_dispatcher_t structure
+*      which should be treated as opaque and should be manipulated
+*      only through the provided functions.
+*
+* SEE ALSO
+*      Structures:
+*              cl_dispatcher_t
+*
+*      Initialization/Destruction:
+*              cl_disp_construct, cl_disp_init, cl_disp_shutdown, cl_disp_destroy
+*
+*      Manipulation:
+*              cl_disp_post, cl_disp_reset, cl_disp_wait_on
+*********/
+
+
+/****s* Component Library: Dispatcher/cl_disp_msgid_t
+* NAME
+*      cl_disp_msgid_t
+*
+* DESCRIPTION
+*      Defines the type of dispatcher messages.
+*
+* SYNOPSIS
+*/
+typedef uint32_t cl_disp_msgid_t;
+/**********/
+
+
+/****s* Component Library: Dispatcher/CL_DISP_MSGID_NONE
+* NAME
+*      CL_DISP_MSGID_NONE
+*
+* DESCRIPTION
+*      Defines a message value that means "no message".
+*      This value is used during registration by Dispatcher clients
+*      that do not wish to receive messages.
+*
+*      No Dispatcher message is allowed to have this value.
+*
+* SYNOPSIS
+*/
+#define CL_DISP_MSGID_NONE     0xFFFFFFFF
+/**********/
+
+/****s* Component Library: Dispatcher/CL_DISP_INVALID_HANDLE
+* NAME
+*      CL_DISP_INVALID_HANDLE
+*
+* DESCRIPTION
+*      Defines the value of an invalid Dispatcher registration handle.
+*
+* SYNOPSIS
+*/
+#define CL_DISP_INVALID_HANDLE ((cl_disp_reg_handle_t)0)
+/*********/
+
+/****f* Component Library: Dispatcher/cl_pfn_msgrcv_cb_t
+* NAME
+*      cl_pfn_msgrcv_cb_t
+*
+* DESCRIPTION
+*      This typedef defines the prototype for client functions invoked
+*      by the Dispatcher.  The Dispatcher calls the corresponding
+*      client function when delivering a message to the client.
+*
+*      The client function must be reentrant if the user creates a
+*      Dispatcher with more than one worker thread.
+*
+* SYNOPSIS
+*/
+typedef void 
+(*cl_pfn_msgrcv_cb_t)(
+       IN      void*                           context,
+       IN      void*                           p_data );
+/*
+* PARAMETERS
+*      context
+*              [in] Client specific context specified in a call to
+*              cl_disp_register
+*
+*      p_data
+*              [in] Pointer to the client specific data payload
+*              of this message.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      This typedef provides a function prototype reference for
+*      the function provided by Dispatcher clients as a parameter
+*      to the cl_disp_register function.
+*
+* SEE ALSO
+*      Dispatcher, cl_disp_register
+*********/
+
+
+/****f* Component Library: Dispatcher/cl_pfn_msgdone_cb_t
+* NAME
+*      cl_pfn_msgdone_cb_t
+*
+* DESCRIPTION
+*      This typedef defines the prototype for client functions invoked
+*      by the Dispatcher.  The Dispatcher calls the corresponding
+*      client function after completing delivery of a message.
+*
+*      The client function must be reentrant if the user creates a
+*      Dispatcher with more than one worker thread.
+*
+* SYNOPSIS
+*/
+typedef void 
+(*cl_pfn_msgdone_cb_t)(
+       IN      void*                           context,
+       IN      void*                           p_data );
+/*
+* PARAMETERS
+*      context
+*              [in] Client specific context specified in a call to
+*              cl_disp_post
+*
+*      p_data
+*              [in] Pointer to the client specific data payload
+*              of this message.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      This typedef provides a function prototype reference for
+*      the function provided by Dispatcher clients as a parameter
+*      to the cl_disp_post function.
+*
+* SEE ALSO
+*      Dispatcher, cl_disp_post
+*********/
+
+
+/****s* Component Library: Dispatcher/cl_dispatcher_t
+* NAME
+*      cl_dispatcher_t
+*
+* DESCRIPTION
+*      Dispatcher structure.
+*
+*      The Dispatcher is thread safe.
+*
+*      The cl_dispatcher_t structure should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_dispatcher
+{
+  cl_spinlock_t      lock;
+  cl_ptr_vector_t    reg_vec;
+  cl_qlist_t         reg_list;
+  cl_thread_pool_t   worker_threads;
+  cl_qlist_t         msg_fifo;
+  cl_qpool_t         msg_pool;
+  uint64_t           last_msg_queue_time_us;
+} cl_dispatcher_t;
+/*
+* FIELDS
+*      reg_vec
+*              Vector of registration info objects.  Indexed by message msg_id.
+*
+*      lock
+*              Spinlock to guard internal structures.
+*
+*      msg_fifo
+*              FIFO of messages being processed by the Dispatcher.  New
+*              messages are posted to the tail of the FIFO.  Worker threads
+*              pull messages from the front.
+*
+*      worker_threads
+*              Thread pool of worker threads to dispose of posted messages.
+*
+*      msg_pool
+*              Pool of message objects to be processed through the FIFO.
+*
+*      reg_count
+*              Count of the number of registrants.
+*
+*      state
+*              Indicates the state of the object.
+* 
+*       last_msg_queue_time_us
+*               The time that the last message spent in the Q in usec
+*      
+* SEE ALSO
+*      Dispatcher
+*********/
+
+
+/****s* Component Library: Dispatcher/cl_disp_reg_info_t
+* NAME
+*      cl_disp_reg_info_t
+*
+* DESCRIPTION
+*      Defines the dispatcher registration object structure.
+*
+*      The cl_disp_reg_info_t structure is for internal use by the
+*      Dispatcher only.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_disp_reg_info
+{
+       cl_list_item_t                  list_item;
+       cl_pfn_msgrcv_cb_t              pfn_rcv_callback;
+       const void                              *context;
+       atomic32_t                              ref_cnt;
+       cl_disp_msgid_t                 msg_id;
+       cl_dispatcher_t                 *p_disp;
+
+} cl_disp_reg_info_t;
+/*
+* FIELDS
+*      pfn_rcv_callback
+*              Client's message receive callback.
+*
+*      context
+*              Client's context for message receive callback.
+*
+*      rcv_thread_count
+*              Number of threads currently in the receive callback.
+*
+*      msg_done_thread_count
+*              Number of threads currently in the message done callback.
+*
+*      state
+*              State of this registration object.
+*                      DISP_REGSTATE_INIT: initialized and inactive
+*                      DISP_REGSTATE_ACTIVE: in active use
+*                      DISP_REGSTATE_UNREGPEND: unregistration is pending
+*
+*      msg_id
+*              Dispatcher message msg_id value for this registration object.
+*
+*      p_disp
+*              Pointer to parent Dispatcher.
+*
+* SEE ALSO
+*********/
+
+
+/****s* Component Library: Dispatcher/cl_disp_msg_t
+* NAME
+*      cl_disp_msg_t
+*
+* DESCRIPTION
+*      Defines the dispatcher message structure.
+*
+*      The cl_disp_msg_t structure is for internal use by the
+*      Dispatcher only.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_disp_msg
+{
+  cl_pool_item_t         item;
+  const void            *p_data;
+  cl_disp_reg_info_t    *p_src_reg;
+  cl_disp_reg_info_t    *p_dest_reg;
+  cl_pfn_msgdone_cb_t    pfn_xmt_callback;
+  uint64_t               in_time;
+  const void            *context;
+} cl_disp_msg_t;
+/*
+* FIELDS
+*      item
+*              List & Pool linkage.  Must be first element in the structure!!
+*
+*      msg_id
+*              The message's numberic ID value.
+*
+*      p_data
+*              Pointer to the data payload for this message.  The payload
+*              is opaque to the Dispatcher.
+*
+*      p_reg_info
+*              Pointer to the registration info of the sender.
+*
+*      pfn_xmt_callback
+*              Client's message done callback.
+*
+*       in_time 
+*               The absolute time the message was inserted into the queue
+*
+*      context
+*              Client's message done callback context.
+*              
+* SEE ALSO
+*********/
+
+
+/****s* Component Library: Dispatcher/cl_disp_reg_info_t
+* NAME
+*      cl_disp_reg_info_t
+*
+* DESCRIPTION
+*      Defines the Dispatcher registration handle.  This handle
+*      should be treated as opaque by the client.
+*
+* SYNOPSIS
+*/
+typedef const struct _cl_disp_reg_info *cl_disp_reg_handle_t;
+/**********/
+
+
+/****f* Component Library: Dispatcher/cl_disp_construct
+* NAME
+*      cl_disp_construct
+*
+* DESCRIPTION
+*      This function constructs a Dispatcher object.
+*
+* SYNOPSIS
+*/
+void
+cl_disp_construct(
+       IN      cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_disp
+*              [in] Pointer to a Dispatcher.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling cl_disp_init and cl_disp_destroy.
+*
+* SEE ALSO
+*      Dispatcher, cl_disp_init, cl_disp_destroy
+*********/
+
+
+/****f* Component Library: Dispatcher/cl_disp_init
+* NAME
+*      cl_disp_init
+*
+* DESCRIPTION
+*      This function initializes a Dispatcher object.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_disp_init(
+       IN      cl_dispatcher_t* const  p_disp,
+       IN      const uint32_t                  thread_count,
+    IN const char* const               name );
+/*
+* PARAMETERS
+*      p_disp
+*              [in] Pointer to a Dispatcher.
+*
+*      thread_count
+*              [in] The number of worker threads to create in this Dispatcher.
+*              A value of 0 causes the Dispatcher to create one worker thread
+*              per CPU in the system.  When the Dispatcher is created with
+*              only one thread, the Dispatcher guarantees to deliver posted
+*              messages in order.  When the Dispatcher is created with more
+*              than one thread, messages may be delivered out of order.
+*
+*      name
+*              [in] Name to associate with the threads.  The name may be up to 16
+*              characters, including a terminating null character.  All threads
+*              created in the Dispatcher have the same name.
+*
+* RETURN VALUE
+*      CL_SUCCESS if the operation is successful.
+*
+* SEE ALSO
+*      Dispatcher, cl_disp_destoy, cl_disp_register, cl_disp_unregister, 
+*      cl_disp_post
+*********/
+
+/****f* Component Library: Dispatcher/cl_disp_shutdown
+* NAME
+*      cl_disp_shutdown
+*
+* DESCRIPTION
+*      This function shutdown a Dispatcher object. So it unreg all messages and
+*  clears the fifo and waits for the threads to exit
+*
+* SYNOPSIS
+*/
+void
+cl_disp_shutdown(
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_disp
+*              [in] Pointer to a Dispatcher.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      This function does not returns until all worker threads
+*      have exited client callback functions and been successfully
+*      shutdowned.
+*
+* SEE ALSO
+*      Dispatcher, cl_disp_construct, cl_disp_init
+*********/
+
+/****f* Component Library: Dispatcher/cl_disp_destroy
+* NAME
+*      cl_disp_destroy
+*
+* DESCRIPTION
+*      This function destroys a Dispatcher object.
+*
+* SYNOPSIS
+*/
+void
+cl_disp_destroy(
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_disp
+*              [in] Pointer to a Dispatcher.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* SEE ALSO
+*      Dispatcher, cl_disp_construct, cl_disp_init
+*********/
+
+
+/****f* Component Library: Dispatcher/cl_disp_register
+* NAME
+*      cl_disp_register
+*
+* DESCRIPTION
+*      This function registers a client with a Dispatcher object.
+*
+* SYNOPSIS
+*/
+cl_disp_reg_handle_t
+cl_disp_register(
+       IN cl_dispatcher_t* const p_disp,
+       IN const cl_disp_msgid_t msg_id,
+       IN cl_pfn_msgrcv_cb_t pfn_callback OPTIONAL,
+       IN const void* const context );
+/*
+* PARAMETERS
+*      p_disp
+*              [in] Pointer to a Dispatcher.
+*
+*      msg_id
+*              [in] Numberic message ID for which the client is registering.
+*              If the client does not wish to receive any messages,
+*              (a send-only client) then the caller should set this value
+*              to CL_DISP_MSGID_NONE.  For efficiency, numeric message msg_id
+*              values should start with 0 and should be contiguous, or nearly so.
+*
+*      pfn_callback
+*              [in] Message receive callback.  The Dispatcher calls this
+*              function after receiving a posted message with the
+*              appropriate message msg_id value.  Send-only clients may specify
+*              NULL for this value.
+*
+*      context
+*              [in] Client context value passed to the cl_pfn_msgrcv_cb_t
+*              function.
+*
+* RETURN VALUE
+*      On success a Dispatcher registration handle.
+*      CL_CL_DISP_INVALID_HANDLE otherwise.
+*
+* SEE ALSO
+*      Dispatcher, cl_disp_unregister, cl_disp_post
+*********/
+
+
+/****f* Component Library: Dispatcher/cl_disp_unregister
+* NAME
+*      cl_disp_unregister
+*
+* DESCRIPTION
+*      This function unregisters a client from a Dispatcher.
+*
+* SYNOPSIS
+*/
+void
+cl_disp_unregister(
+       IN const cl_disp_reg_handle_t handle );
+/*
+* PARAMETERS
+*      handle
+*              [in] cl_disp_reg_handle_t value return by cl_disp_register.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      This function will not return until worker threads have exited
+*      the callback functions for this client.  Do not invoke this
+*      function from a callback.
+*
+* SEE ALSO
+*      Dispatcher, cl_disp_register
+*********/
+
+
+/****f* Component Library: Dispatcher/cl_disp_post
+* NAME
+*      cl_disp_post
+*
+* DESCRIPTION
+*      This function posts a message to a Dispatcher object.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_disp_post(
+       IN const cl_disp_reg_handle_t handle,
+       IN const cl_disp_msgid_t msg_id,
+       IN const void* const p_data,
+       IN cl_pfn_msgdone_cb_t pfn_callback OPTIONAL,
+       IN const void* const context );
+/*
+* PARAMETERS
+*      handle
+*              [in] cl_disp_reg_handle_t value return by cl_disp_register.
+*
+*      msg_id
+*              [in] Numeric message msg_id value associated with this message.
+*
+*      p_data
+*              [in] Data payload for this message.
+*
+*      pfn_callback
+*              [in] Pointer to a cl_pfn_msgdone_cb_t function.
+*              The Dispatcher calls this function after the message has been
+*              processed by the recipient.
+*              The caller may pass NULL for this value, which indicates no
+*              message done callback is necessary.
+*
+*      context
+*              [in] Client context value passed to the cl_pfn_msgdone_cb_t
+*              function.
+*      
+* RETURN VALUE
+*      CL_SUCCESS if the message was successfully queued in the Dispatcher.
+*
+* NOTES
+*      The caller must not modify the memory pointed to by p_data until
+*      the Dispatcher call the pfn_callback function.
+*
+* SEE ALSO
+*      Dispatcher
+*********/
+
+/****f* Component Library: Dispatcher/cl_disp_get_queue_status
+* NAME
+*      cl_disp_get_queue_status
+*
+* DESCRIPTION
+*      This function posts a message to a Dispatcher object.
+*
+* SYNOPSIS
+*/
+void
+cl_disp_get_queue_status(
+  IN const cl_disp_reg_handle_t handle,
+  OUT uint32_t *p_num_queued_msgs,
+  OUT uint64_t *p_last_msg_queue_time_ms);
+/*
+* PARAMETERS
+*   handle
+*     [in] cl_disp_reg_handle_t value return by cl_disp_register.
+*
+*   p_last_msg_queue_time_ms
+*     [out] pointer to a variable to hold the time the last popped up message 
+*           spent in the queue 
+*
+*   p_num_queued_msgs
+*     [out] number of messages in the queue
+*
+* RETURN VALUE
+*      Thr time the last popped up message stayed in the queue, in msec
+*
+* NOTES
+*      Extarnel Locking is not required.
+*
+* SEE ALSO
+*      Dispatcher
+*********/
+
+END_C_DECLS
+
+#endif /* !defined(_CL_DISPATCHER_H_) */
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/cl_event_wheel.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/cl_event_wheel.h
new file mode 100644 (file)
index 0000000..2972c71
--- /dev/null
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: cl_event_wheel.h 474 2006-08-31 08:57:19Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of event wheel abstraction.
+ * 
+ * Environment:
+ *     All
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _CL_EVENT_WHEEL_H_
+#define _CL_EVENT_WHEEL_H_
+
+#include <complib/cl_atomic.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_timer.h>
+#include <complib/cl_spinlock.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* Component Library/Event_Wheel
+* NAME
+*      Event_Wheel
+*
+* DESCRIPTION
+*      The Event_Wheel provides a facility for registering delayed events
+*      and getting called once they timeout.
+*
+*      The Event_Wheel functions operate on a cl_event_wheel_t structure
+*      which should be treated as opaque and should be manipulated
+*      only through the provided functions.
+*
+* SEE ALSO
+*      Structures:
+*              cl_event_wheel_t
+*
+*      Initialization/Destruction:
+*              cl_event_wheel_construct, cl_event_wheel_init, cl_event_wheel_destroy
+*
+*      Manipulation:
+*              cl_event_wheel_reg, cl_event_wheel_unreg
+*
+*********/
+
+/****f* Component Library: Event_Wheel/cl_pfn_event_aged_cb_t
+* NAME
+*      cl_pfn_event_aged_cb_t
+*
+* DESCRIPTION
+*      This typedef defines the prototype for client functions invoked
+*      by the Event_Wheel.  The Event_Wheel calls the corresponding
+*      client function when the specific item has aged.
+*
+* SYNOPSIS
+*/
+typedef uint64_t
+(*cl_pfn_event_aged_cb_t)(
+  IN  uint64_t       key,
+  IN  uint32_t       num_regs,
+  IN   void*                           context);
+/*
+* PARAMETERS
+*  key
+*     [in] The key used for registering the item in the call to
+*     cl_event_wheel_reg
+*
+*  num_regs
+*     [in] The number of times this event was registered (pushed in time).
+*
+*      context
+*              [in] Client specific context specified in a call to
+*              cl_event_wheel_reg
+*
+* RETURN VALUE
+*      This function returns the abosolute time the event should fire in [usec].
+*  If lower then current time means the event should be unregistered
+*  immediatly.
+*
+* NOTES
+*      This typedef provides a function prototype reference for
+*      the function provided by Event_Wheel clients as a parameter
+*      to the cl_event_wheel_reg function.
+*
+* SEE ALSO
+*      Event_Wheel, cl_event_wheel_reg
+*********/
+
+/****s* Component Library: Event_Wheel/cl_event_wheel_t
+* NAME
+*      cl_event_wheel_t
+*
+* DESCRIPTION
+*      Event_Wheel structure.
+*
+*      The Event_Wheel is thread safe.
+*
+*      The cl_event_wheel_t structure should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_event_wheel
+{
+  cl_spinlock_t                   lock;
+  cl_spinlock_t           *p_external_lock;
+    
+  cl_qmap_t                events_map;
+  boolean_t                closing;
+  cl_qlist_t               events_wheel;
+  cl_timer_t               timer;
+  osm_log_t                *p_log;
+} cl_event_wheel_t;
+/*
+* FIELDS
+*      lock
+*              Spinlock to guard internal structures.
+*
+*       p_external_lock
+*               Reference to external spinlock to guard internal structures
+*               if the event wheel is part of a larger object protected by its own lock
+*
+*      events_map
+*              A Map holding all registered event items by their key.
+*
+*  closing 
+*     A flag indicating the event wheel is closing. This means that
+*     callbacks that are called when closing == TRUE should just be ignored.
+*
+*      events_wheel
+*              A list of the events sorted by expiration time.
+*
+*      timer
+*              The timer scheduling event time propagation.
+*
+*  p_log
+*     Pointer to opensm log object.
+*
+* SEE ALSO
+*      Event_Wheel
+*********/
+
+/****s* Component Library: Event_Wheel/cl_event_wheel_reg_info_t
+* NAME
+*      cl_event_wheel_reg_info_t
+*
+* DESCRIPTION
+*      Defines the event_wheel registration object structure.
+*
+*      The cl_event_wheel_reg_info_t structure is for internal use by the
+*      Event_Wheel only.
+*
+* SYNOPSIS
+*/
+typedef struct _cl_event_wheel_reg_info
+{
+  cl_map_item_t          map_item;
+  cl_list_item_t                        list_item;
+  uint64_t               key;
+  cl_pfn_event_aged_cb_t pfn_aged_callback;
+  uint64_t               aging_time;
+  uint32_t               num_regs;
+  void                                *context;
+  cl_event_wheel_t              *p_event_wheel;
+} cl_event_wheel_reg_info_t;
+/*
+* FIELDS
+*  map_item 
+*     The map item of this event 
+*
+*  list_item
+*     The sorted by aging time list item
+*
+*  key
+*     The key by which one can find the event
+*
+*      pfn_aged_callback
+*              The clients Event-Aged callback
+*
+*  aging_time
+*     The delta time [msec] for which the event should age.
+*
+*  num_regs
+*     The number of times the same event (key) was registered
+*
+*      context
+*              Client's context for event-aged callback.
+*
+*      p_event_wheel
+*              Pointer to this event wheel object
+*
+* SEE ALSO
+*********/
+
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_construct
+* NAME
+*      cl_event_wheel_construct
+*
+* DESCRIPTION
+*      This function constructs a Event_Wheel object.
+*
+* SYNOPSIS
+*/
+void
+cl_event_wheel_construct(
+       IN      cl_event_wheel_t* const p_event_wheel );
+/*
+* PARAMETERS
+*      p_event_wheel
+*              [in] Pointer to a Event_Wheel.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling cl_event_wheel_init and cl_event_wheel_destroy.
+*
+* SEE ALSO
+*      Event_Wheel, cl_event_wheel_init, cl_event_wheel_destroy
+*********/
+
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_init
+* NAME
+*      cl_event_wheel_init
+*
+* DESCRIPTION
+*      This function initializes a Event_Wheel object.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_event_wheel_init(
+  IN   cl_event_wheel_t* const p_event_wheel,
+  IN    osm_log_t               *p_log);
+
+/*
+* PARAMETERS
+*      p_event_wheel
+*              [in] Pointer to a Event_Wheel.
+*
+*  p_log
+*     [in] Pointer to opensm log object to be used for logging
+*
+* RETURN VALUE
+*      CL_SUCCESS if the operation is successful.
+*
+* SEE ALSO
+*      Event_Wheel, cl_event_wheel_destoy, cl_event_wheel_reg, cl_event_wheel_unreg
+*      
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_init
+* NAME
+*      cl_event_wheel_init
+*
+* DESCRIPTION
+*      This function initializes a Event_Wheel object.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_event_wheel_init_ex(
+  IN   cl_event_wheel_t* const p_event_wheel,
+  IN    osm_log_t               *p_log,
+  IN    cl_spinlock_t           *p_external_lock);
+
+/*
+* PARAMETERS
+*  p_event_wheel
+*     [in] Pointer to a Event_Wheel.
+*
+*  p_log
+*     [in] Pointer to opensm log object to be used for logging
+*
+*  p_external_lock
+*     [in] Reference to external spinlock to guard internal structures
+*          if the event wheel is part of a larger object protected by its own lock
+*
+* RETURN VALUE
+*      CL_SUCCESS if the operation is successful.
+*
+* SEE ALSO
+*      Event_Wheel, cl_event_wheel_destoy, cl_event_wheel_reg, cl_event_wheel_unreg
+*      
+*********/
+
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_destroy
+* NAME
+*      cl_event_wheel_destroy
+*
+* DESCRIPTION
+*      This function destroys a Event_Wheel object.
+*
+* SYNOPSIS
+*/
+void
+cl_event_wheel_destroy(
+       IN cl_event_wheel_t* const p_event_wheel );
+/*
+* PARAMETERS
+*      p_event_wheel
+*              [in] Pointer to a Event_Wheel.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      This function does not returns until all client callback functions
+*  been successfully finished.
+*
+* SEE ALSO
+*      Event_Wheel, cl_event_wheel_construct, cl_event_wheel_init
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_dump
+* NAME
+*      cl_event_wheel_dump
+*
+* DESCRIPTION
+*      This function dumps the details of an Event_Whell object.
+*
+* SYNOPSIS
+*/
+void
+cl_event_wheel_dump(
+       IN cl_event_wheel_t* const p_event_wheel );
+/*
+* PARAMETERS
+*      p_event_wheel
+*              [in] Pointer to a Event_Wheel.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Note that this function should be called inside a lock of the event wheel!
+*  It doesn't aquire the lock by itself. 
+*
+* SEE ALSO
+*      Event_Wheel, cl_event_wheel_construct, cl_event_wheel_init
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_reg
+* NAME
+*      cl_event_wheel_reg
+*
+* DESCRIPTION
+*      This function registers a client with a Event_Wheel object.
+*
+* SYNOPSIS
+*/
+cl_status_t
+cl_event_wheel_reg(
+       IN cl_event_wheel_t* const p_event_wheel,
+       IN const uint64_t          key,
+       IN const uint64_t          aging_time_usec,
+       IN cl_pfn_event_aged_cb_t  pfn_callback,
+       IN void* const context );
+/*
+* PARAMETERS
+*      p_event_wheel
+*              [in] Pointer to a Event_Wheel.
+*
+*      key
+*              [in] The specifc Key by which events are registered.
+*
+*  aging_time_usec
+*     [in] The absolute time this event should age in usec
+*
+*      pfn_callback
+*              [in] Event Aging callback.  The Event_Wheel calls this
+*              function after the time the event has registed for has come.
+*
+*      context
+*              [in] Client context value passed to the cl_pfn_event_aged_cb_t
+*              function.
+*
+* RETURN VALUE
+*      On success a Event_Wheel CL_SUCCESS or CL_ERROR otherwise.
+*
+* SEE ALSO
+*      Event_Wheel, cl_event_wheel_unreg
+*********/
+
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_unreg
+* NAME
+*      cl_event_wheel_unreg
+*
+* DESCRIPTION
+*      This function unregisters a client event from a Event_Wheel.
+*
+* SYNOPSIS
+*/
+void
+cl_event_wheel_unreg(
+  IN cl_event_wheel_t* const p_event_wheel,
+  IN uint64_t key );
+/*
+* PARAMETERS
+*      p_event_wheel
+*              [in] Pointer to a Event_Wheel.
+*
+*      key
+*              [in] The key used for registering the event
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*  After the event has aged it is automatically removed from 
+*  the event wheel. So it should only be invoked when the need arises
+*  to remove existing events before they age.
+*
+* SEE ALSO
+*      Event_Wheel, cl_event_wheel_reg
+*********/
+
+/****f* Component Library: Event_Wheel/cl_event_wheel_num_regs
+* NAME
+*      cl_event_wheel_num_regs
+*
+* DESCRIPTION
+*      This function returns the number of times an event was registered.
+*
+* SYNOPSIS
+*/
+uint32_t 
+cl_event_wheel_num_regs(
+  IN cl_event_wheel_t* const p_event_wheel,
+  IN uint64_t key );
+/*
+* PARAMETERS
+*      p_event_wheel
+*              [in] Pointer to a Event_Wheel.
+*
+*      key
+*              [in] The key used for registering the event
+*
+* RETURN VALUE
+*      The number of times the event was registered.
+*  0 if never registered or eventually aged.
+*
+* SEE ALSO
+*      Event_Wheel, cl_event_wheel_reg, cl_event_wheel_unreg
+*********/
+
+END_C_DECLS
+
+#endif /* !defined(_CL_EVENT_WHEEL_H_) */
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_attrib_req.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_attrib_req.h
new file mode 100644 (file)
index 0000000..80c29b9
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_attrib_req.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_ATTRIB_REQ_H_
+#define _OSM_ATTRIB_REQ_H_
+
+#include <opensm/osm_path.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/*
+ * Abstract:
+ *     Declaration of the attribute request object.  This object
+ *  encapsulates information needed by the generic request controller
+ *  to request an attribute from a node.
+ *     These objects are part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+/****h* OpenSM/Attribute Request
+* NAME
+*      Attribute Request
+*
+* DESCRIPTION
+*      The Attribute Request structure encapsulates 
+*   encapsulates information needed by the generic request controller
+*   to request an attribute from a node.
+*
+*      This structure allows direct access to member variables.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Attribute Request/osm_attrib_req_t
+* NAME
+*      osm_attrib_req_t
+*
+* DESCRIPTION
+*      Attribute request structure.
+*
+*      This structure allows direct access to member variables.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_attrib_req
+{
+       uint16_t                                attrib_id;
+       uint32_t                                attrib_mod;
+       osm_madw_context_t              context;
+       osm_dr_path_t                   path;
+       cl_disp_msgid_t                 err_msg;
+
+} osm_attrib_req_t;
+/*
+* FIELDS
+*      attrib_id
+*              Attribute ID for this request.
+*
+*      attrib_mod
+*              Attribute modifier for this request.
+*
+*      context
+*              Context to insert in outbound mad wrapper context.
+*
+*      path
+*              The directed route path to the node.
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif         /* _OSM_ATTRIB_REQ_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_base.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_base.h
new file mode 100644 (file)
index 0000000..8aa3bd1
--- /dev/null
@@ -0,0 +1,823 @@
+/*\r
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.\r
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.\r
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: osm_base.h 1927 2009-02-04 15:20:41Z tzachid $\r
+ */\r
+\r
+\r
+/*\r
+ * Abstract:\r
+ *     Basic OpenSM definitions and structures.\r
+ *     This object represents an OpenSM "base class".\r
+ *     This object is part of the OpenSM family of objects.\r
+ *\r
+ * Environment:\r
+ *     Linux User Mode\r
+ *\r
+ * $Revision: 1.15 $\r
+ */\r
+\r
+#ifndef _OSM_BASE_H_\r
+#define _OSM_BASE_H_\r
+\r
+#ifdef __WIN__\r
+#include <vendor/winosm_common.h>\r
+#define OSM_CDECL __cdecl\r
+#else\r
+#define OSM_CDECL\r
+#endif\r
+\r
+#include <complib/cl_types.h>\r
+\r
+#ifdef __cplusplus\r
+#  define BEGIN_C_DECLS extern "C" {\r
+#  define END_C_DECLS   }\r
+#else /* !__cplusplus */\r
+#  define BEGIN_C_DECLS\r
+#  define END_C_DECLS\r
+#endif /* __cplusplus */\r
+\r
+BEGIN_C_DECLS\r
+\r
+/****h* OpenSM/Constants\r
+* NAME\r
+*      Constants\r
+*\r
+* DESCRIPTION\r
+*      The following constants are used throughout the OpenSM.\r
+*\r
+* AUTHOR\r
+*      Steve King, Intel\r
+*\r
+*********/\r
+\r
+/****h* OpenSM/Base\r
+* NAME\r
+*      Base\r
+*\r
+* DESCRIPTION\r
+*      The Base object encapsulates basic information needed by the\r
+*      OpenSM to manage objects.  Each OpenSM object includes the\r
+*      Base object as the first member.\r
+*\r
+*      This object should be treated as opaque and should be\r
+*      manipulated only through the provided functions.\r
+*\r
+* AUTHOR\r
+*      Steve King, Intel\r
+*\r
+*********/\r
+\r
+/****s* OpenSM: Base/OSM_DEFAULT_M_KEY\r
+* NAME\r
+*      OSM_DEFAULT_M_KEY\r
+*\r
+* DESCRIPTION\r
+*      Managment key value used by the OpenSM.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_M_KEY 0\r
+/********/\r
+\r
+/****s* OpenSM: Base/OSM_DEFAULT_SM_KEY\r
+* NAME\r
+*      OSM_DEFAULT_SM_KEY\r
+*\r
+* DESCRIPTION\r
+*      Subnet Manager key value used by the OpenSM.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_SM_KEY 1\r
+/********/\r
+\r
+/****s* OpenSM: Base/OSM_DEFAULT_SA_KEY\r
+* NAME\r
+*       OSM_DEFAULT_SA_KEY\r
+*\r
+* DESCRIPTION\r
+*       Subnet Adminstration key value.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_SA_KEY OSM_DEFAULT_SM_KEY\r
+/********/\r
+\r
+/****s* OpenSM: Base/OSM_DEFAULT_LMC\r
+* NAME\r
+*      OSM_DEFAULT_LMC\r
+*\r
+* DESCRIPTION\r
+*      Default LMC value used by the OpenSM.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_LMC 0\r
+/********/\r
+\r
+/****s* OpenSM: Base/OSM_DEFAULT_MAX_OP_VLS\r
+* NAME\r
+*      OSM_DEFAULT_MAX_OP_VLS\r
+*\r
+* DESCRIPTION\r
+*      Default Maximal Operational VLs to be initialized on \r
+*  the link ports PortInfo by the OpenSM.\r
+*  Default value provides backward compatibility.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_MAX_OP_VLS 5\r
+/********/\r
+\r
+/****s* OpenSM: Base/OSM_DEFAULT_SL\r
+* NAME\r
+*      OSM_DEFAULT_SL\r
+*\r
+* DESCRIPTION\r
+*      Default SL value used by the OpenSM.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_SL 0\r
+/********/\r
+\r
+/****s* OpenSM: Base/OSM_DEFAULT_SM_PRIORITY\r
+* NAME\r
+*      OSM_DEFAULT_SM_PRIORITY\r
+*\r
+* DESCRIPTION\r
+*      Default SM priority value used by the OpenSM,\r
+*      as defined in the SMInfo attribute.  0 is the lowest priority.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_SM_PRIORITY 1\r
+/********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_TMP_DIR\r
+* NAME\r
+*      OSM_DEFAULT_TMP_DIR\r
+*\r
+* DESCRIPTION\r
+*      Specifies the default temporary directory for the log file,\r
+*  osm-subnet.lst, and other log files.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#ifdef __WIN__\r
+#define OSM_DEFAULT_TMP_DIR GetOsmTempPath()\r
+#else\r
+#define OSM_DEFAULT_TMP_DIR "/var/log/"\r
+#endif\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_CACHE_DIR\r
+* NAME\r
+*      OSM_DEFAULT_CACHE_DIR\r
+*\r
+* DESCRIPTION\r
+*      Specifies the default cache directory for the db files.\r
+*      Note that the directory must appear with "/" ("\\" for windows) at the end.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#ifdef __WIN__\r
+#define OSM_DEFAULT_CACHE_DIR GetOsmCachePath()\r
+#else\r
+#define OSM_DEFAULT_CACHE_DIR "/var/cache/osm/"\r
+#endif\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_LOG_FILE\r
+* NAME\r
+*      OSM_DEFAULT_LOG_FILE\r
+*\r
+* DESCRIPTION\r
+*      Specifies the default log file name\r
+*\r
+* SYNOPSIS\r
+*/\r
+#ifdef __WIN__\r
+#define OSM_DEFAULT_LOG_FILE strcat(GetOsmTempPath(), "osm.log")\r
+#else\r
+#define OSM_DEFAULT_LOG_FILE "/var/log/osm.log"\r
+#endif\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_PARTITION_CONFIG_FILE\r
+* NAME\r
+*      OSM_DEFAULT_PARTITION_CONFIG_FILE\r
+*\r
+* DESCRIPTION\r
+*      Specifies the default partition config file name\r
+*\r
+* SYNOPSIS\r
+*/\r
+#ifdef __WIN__\r
+#define OSM_DEFAULT_PARTITION_CONFIG_FILE strcat(GetOsmCachePath(), "osm-partitions.conf")\r
+#else\r
+#define OSM_DEFAULT_PARTITION_CONFIG_FILE "/etc/osm-partitions.conf"\r
+#endif\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_SWEEP_INTERVAL_SECS\r
+* NAME\r
+*      OSM_DEFAULT_SWEEP_INTERVAL_SECS\r
+*\r
+* DESCRIPTION\r
+*      Specifies the default number of seconds between subnet sweeps.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_SWEEP_INTERVAL_SECS 10\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC\r
+* NAME\r
+*      OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC\r
+*\r
+* DESCRIPTION\r
+*      Specifies the default transaction timeout in milliseconds.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC 200\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_SUBNET_TIMEOUT\r
+* NAME\r
+*      OSM_DEFAULT_SUBNET_TIMEOUT\r
+*\r
+* DESCRIPTION\r
+*      Specifies the default transaction timeout.\r
+*      timeout time = 4us * 2^timeout.\r
+*  We use here ~1sec.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_SUBNET_TIMEOUT 0x12\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_SWITCH_PACKET_LIFE\r
+* NAME\r
+*      OSM_DEFAULT_SWITCH_PACKET_LIFE\r
+*\r
+* DESCRIPTION\r
+*      Specifies the default max life time for a pcket on the switch.\r
+*      timeout time = 4us * 2^timeout.\r
+*  We use here the value of ~1sec\r
+*  A Value > 19dec disables this mechanism.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_SWITCH_PACKET_LIFE 0x12\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_HEAD_OF_QUEUE_LIFE\r
+* NAME\r
+*      OSM_DEFAULT_HEAD_OF_QUEUE_LIFE\r
+*\r
+* DESCRIPTION\r
+*      Sets the time a packet can live in the head of the VL Queue\r
+*  We use here the value of ~1sec\r
+*  A Value > 19dec disables this mechanism.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_HEAD_OF_QUEUE_LIFE 0x12\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE\r
+* NAME\r
+*      OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE\r
+*\r
+* DESCRIPTION\r
+*      Sets the time a packet can live in the head of the VL Queue\r
+*  of a port that drives a CA port.\r
+*  We use here the value of ~130usec\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE 0xC\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_VL_STALL_COUNT\r
+* NAME\r
+*      OSM_DEFAULT_LEAF_VL_COUNT\r
+*\r
+* DESCRIPTION\r
+*      Sets the number of consecutive head of queue life time drops that \r
+*  puts the VL into stalled state. In stalled state, the port is supposed\r
+*  to drop everything for 8*(head of queue lifetime) \r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_VL_STALL_COUNT 0x7\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_LEAF_VL_STALL_COUNT\r
+* NAME\r
+*      OSM_DEFAULT_LEAF_VL_STALL_COUNT\r
+*\r
+* DESCRIPTION\r
+*      Sets the number of consecutive head of queue life time drops that \r
+*  puts the VL into stalled state. In stalled state, the port is supposed\r
+*  to drop everything for 8*(head of queue lifetime). This value is for\r
+*  switch ports driving a CA port.\r
+*  We use the value of 1 here - so any drop due to HOQ means stalling the VL\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_LEAF_VL_STALL_COUNT 0x1\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT\r
+* NAME\r
+*      OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT\r
+*\r
+* DESCRIPTION\r
+*      Specifies the default timeout for ignoring same trap.\r
+*      timeout time = 5000000us\r
+*  We use here ~5sec.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT 5000000\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_UNHEALTHY_TIMEOUT\r
+* NAME\r
+*      OSM_DEFAULT_UNHEALTHY_TIMEOUT\r
+*\r
+* DESCRIPTION\r
+*      Specifies the default timeout for setting port as unhealthy.\r
+*      timeout time = 60000000us\r
+*  We use here ~60sec.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_UNHEALTHY_TIMEOUT 60000000\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_ERROR_THRESHOLD\r
+* NAME\r
+*      OSM_DEFAULT_ERROR_THRESHOLD\r
+*\r
+* DESCRIPTION\r
+*      Specifies default link error threshold to be set by SubnMgt(Set.PortInfo).\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_ERROR_THRESHOLD 0x08\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_SMP_MAX_ON_WIRE\r
+* NAME\r
+*      OSM_DEFAULT_SMP_MAX_ON_WIRE\r
+*\r
+* DESCRIPTION\r
+*      Specifies the default number of VL15 SMP MADs allowed on \r
+*      the wire at any one time.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_SMP_MAX_ON_WIRE 4\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP0_RCV_SIZE\r
+* NAME\r
+*      OSM_SM_DEFAULT_QP0_RCV_SIZE\r
+*\r
+* DESCRIPTION\r
+*      Specifies the default size (in MADs) of the QP0 receive queue\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_SM_DEFAULT_QP0_RCV_SIZE 256\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP0_SEND_SIZE\r
+* NAME\r
+*      OSM_SM_DEFAULT_QP0_SEND_SIZE\r
+*\r
+* DESCRIPTION\r
+*      Specifies the default size (in MADs) of the QP0 send queue\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_SM_DEFAULT_QP0_SEND_SIZE 256\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP1_RCV_SIZE\r
+* NAME\r
+*   OSM_SM_DEFAULT_QP1_RCV_SIZE\r
+*\r
+* DESCRIPTION\r
+*   Specifies the default size (in MADs) of the QP1 receive queue\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_SM_DEFAULT_QP1_RCV_SIZE 256\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP1_SEND_SIZE\r
+* NAME\r
+*   OSM_SM_DEFAULT_QP1_SEND_SIZE\r
+*\r
+* DESCRIPTION\r
+*   Specifies the default size (in MADs) of the QP1 send queue\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_SM_DEFAULT_QP1_SEND_SIZE 256\r
+\r
+\r
+/****d* OpenSM: Base/OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS\r
+* NAME\r
+*   OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS\r
+*\r
+* DESCRIPTION\r
+*   Specifies the polling timeout (in miliseconds) - the timeout\r
+*   between one poll to another.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS 10000\r
+/**********/\r
+\r
+/****d* OpenSM: Base/OSM_SM_DEFAULT_POLLING_RETRY_NUMBER\r
+* NAME\r
+*   OSM_SM_DEFAULT_POLLING_RETRY_NUMBER\r
+*\r
+* DESCRIPTION\r
+*   Specifies the number of polling retries before the SM goes back\r
+*   to DISCOVERY stage. So the default total time for handoff is 40 sec.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_SM_DEFAULT_POLLING_RETRY_NUMBER 4\r
+/**********/\r
+\r
+/****d* OpenSM: Base/OSM_NO_PATH\r
+* NAME\r
+*      OSM_NO_PATH\r
+*\r
+* DESCRIPTION\r
+*      Value indicating there is no path to the given LID.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_NO_PATH                    0xFF\r
+/**********/\r
+\r
+/****d* OpenSM: Base/osm_thread_state_t\r
+* NAME\r
+*      osm_thread_state_t\r
+*\r
+* DESCRIPTION\r
+*      Enumerates the possible states of worker threads, such\r
+*      as the subnet sweeper.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _osm_thread_state\r
+{\r
+       OSM_THREAD_STATE_NONE = 0,\r
+       OSM_THREAD_STATE_INIT,\r
+       OSM_THREAD_STATE_RUN,\r
+       OSM_THREAD_STATE_EXIT\r
+\r
+} osm_thread_state_t;\r
+/***********/\r
+\r
+/*\r
+ * OSM_CAP are from Table 117 and C15-0.1.7 Table 186\r
+ */\r
+\r
+/****d* OpenSM: Base/OSM_CAP_IS_TRAP_SUP\r
+* Name\r
+*      OSM_CAP_IS_SUBN_TRAP_SUP\r
+*\r
+* DESCRIPTION\r
+*      Management class generates Trap() MADs\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_CAP_IS_SUBN_TRAP_SUP (1 << 0)\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_CAP_IS_GET_SET_NOTICE_SUP\r
+* Name\r
+*      OSM_CAP_IS_GET_SET_NOTICE_SUP\r
+*\r
+* DESCRIPTION\r
+*       Management class supports Get/Set(Notice)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_CAP_IS_SUBN_GET_SET_NOTICE_SUP (1 << 1)\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_CAP_IS_SUBN_OPT_RECS_SUP\r
+* Name\r
+*      OSM_CAP_IS_SUBN_OPT_RECS_SUP\r
+*\r
+* DESCRIPTION\r
+*      Support all optional attributes except:\r
+*  MCMemberRecord, TraceRecord, MultiPathRecord\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_CAP_IS_SUBN_OPT_RECS_SUP (1 << 8)\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_CAP_IS_UD_MCAST_SUP\r
+* Name\r
+*      OSM_CAP_IS_UD_MCAST_SUP\r
+*\r
+* DESCRIPTION\r
+*      Multicast is supported \r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_CAP_IS_UD_MCAST_SUP (1 << 9)\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_CAP_IS_MULTIPATH_SUP\r
+* Name\r
+*      OSM_CAP_IS_MULTIPATH_SUP\r
+*\r
+* DESCRIPTION\r
+*      MultiPathRecord and TraceRecord are supported\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_CAP_IS_MULTIPATH_SUP (1 << 10)\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_CAP_IS_REINIT_SUP\r
+* Name\r
+*      OSM_CAP_IS_REINIT_SUP\r
+*\r
+* DESCRIPTION\r
+*      SM/SA supports re-initialization supported\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_CAP_IS_REINIT_SUP (1 << 11)\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED\r
+* Name\r
+*      OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED\r
+*\r
+* DESCRIPTION\r
+*      SM/SA supports enhanced SA PortInfoRecord searches per 1.2 Errata:\r
+*  ClassPortInfo:CapabilityMask.IsPortInfoCapMaskMatchSupported is 1, \r
+*  then the AttributeModifier of the SubnAdmGet() and SubnAdmGetTable() \r
+*  methods affects the matching behavior on the PortInfo:CapabilityMask \r
+*  component. If the high-order bit (bit 31) of the AttributeModifier \r
+*  is set to 1, matching on the CapabilityMask component will not be an \r
+*  exact bitwise match as described in <ref to 15.4.4>.  Instead, \r
+*  matching will only be performed on those bits which are set to 1 in \r
+*  the PortInfo:CapabilityMask embedded in the query. \r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED (1 << 13)\r
+/***********/\r
+\r
+/****d* OpenSM: Base/osm_sm_state_t\r
+* NAME\r
+*      osm_sm_state_t\r
+*\r
+* DESCRIPTION\r
+*      Enumerates the possible states of the SM object.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _osm_sm_state\r
+{\r
+       OSM_SM_STATE_NO_STATE = 0,\r
+       OSM_SM_STATE_INIT,\r
+       OSM_SM_STATE_IDLE,\r
+       OSM_SM_STATE_SWEEP_LIGHT,\r
+       OSM_SM_STATE_SWEEP_LIGHT_WAIT,\r
+       OSM_SM_STATE_SWEEP_HEAVY_SELF,\r
+       OSM_SM_STATE_SWEEP_HEAVY_SUBNET,\r
+       OSM_SM_STATE_SET_SM_UCAST_LID,\r
+       OSM_SM_STATE_SET_SM_UCAST_LID_WAIT,\r
+       OSM_SM_STATE_SET_SM_UCAST_LID_DONE,\r
+       OSM_SM_STATE_SET_SUBNET_UCAST_LIDS,\r
+       OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_WAIT,\r
+       OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_DONE,\r
+       OSM_SM_STATE_SET_UCAST_TABLES,\r
+       OSM_SM_STATE_SET_UCAST_TABLES_WAIT,\r
+       OSM_SM_STATE_SET_UCAST_TABLES_DONE,\r
+       OSM_SM_STATE_SET_MCAST_TABLES,\r
+       OSM_SM_STATE_SET_MCAST_TABLES_WAIT,\r
+       OSM_SM_STATE_SET_MCAST_TABLES_DONE,\r
+       OSM_SM_STATE_SET_LINK_PORTS,\r
+       OSM_SM_STATE_SET_LINK_PORTS_WAIT,\r
+       OSM_SM_STATE_SET_LINK_PORTS_DONE,\r
+       OSM_SM_STATE_SET_ARMED,\r
+       OSM_SM_STATE_SET_ARMED_WAIT,\r
+       OSM_SM_STATE_SET_ARMED_DONE,\r
+       OSM_SM_STATE_SET_ACTIVE,\r
+       OSM_SM_STATE_SET_ACTIVE_WAIT,\r
+       OSM_SM_STATE_LOST_NEGOTIATION,\r
+       OSM_SM_STATE_STANDBY,\r
+       OSM_SM_STATE_SUBNET_UP,\r
+       OSM_SM_STATE_PROCESS_REQUEST,\r
+       OSM_SM_STATE_PROCESS_REQUEST_WAIT,\r
+       OSM_SM_STATE_PROCESS_REQUEST_DONE,\r
+       OSM_SM_STATE_MASTER_OR_HIGHER_SM_DETECTED,\r
+       OSM_SM_STATE_SET_PKEY,\r
+       OSM_SM_STATE_SET_PKEY_WAIT,\r
+       OSM_SM_STATE_SET_PKEY_DONE,\r
+       OSM_SM_STATE_MAX\r
+} osm_sm_state_t;\r
+/***********/\r
+\r
+/****d* OpenSM: Base/osm_signal_t\r
+* NAME\r
+*      osm_signal_t\r
+*\r
+* DESCRIPTION\r
+*      Enumerates the possible signal codes used by the OSM managers\r
+*      This cannot be an enum type, since conversion to and from\r
+*      integral types is necessary when passing signals through\r
+*      the dispatcher.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_SIGNAL_NONE                                                        0\r
+#define OSM_SIGNAL_SWEEP                                               1\r
+#define OSM_SIGNAL_CHANGE_DETECTED                             2\r
+#define OSM_SIGNAL_NO_PENDING_TRANSACTIONS             3\r
+#define OSM_SIGNAL_DONE                                                        4\r
+#define OSM_SIGNAL_DONE_PENDING                                        5\r
+#define OSM_SIGNAL_LOST_SM_NEGOTIATION                 6\r
+#define OSM_SIGNAL_LIGHT_SWEEP_FAIL                            7\r
+#define OSM_SIGNAL_IDLE_TIME_PROCESS                   8\r
+#define OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST   9\r
+#define OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED                10\r
+#define OSM_SIGNAL_EXIT_STBY                11\r
+#define OSM_SIGNAL_MAX                                                 12\r
+\r
+typedef uintn_t osm_signal_t;\r
+/***********/\r
+\r
+/****d* OpenSM: Base/osm_state_mgr_mode_t\r
+* NAME\r
+*       osm_state_mgr_mode_t\r
+*\r
+* DESCRIPTION\r
+*      Enumerates the possible state progressing codes used by the OSM \r
+*      state manager.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _osm_state_mgr_mode\r
+{\r
+  OSM_STATE_STEP_CONTINUOUS = 0,\r
+  OSM_STATE_STEP_TAKE_ONE,\r
+  OSM_STATE_STEP_BREAK\r
+} osm_state_mgr_mode_t;\r
+/*\r
+* OSM_STATE_STEP_CONTINUOUS \r
+*    normal automatic progress mode\r
+*\r
+* OSM_STATE_STEP_TAKE_ONE \r
+*    Do one step \r
+*\r
+* OSM_STATE_STEP_BREAK\r
+*    Stop before taking next step (the while loop in the state \r
+*    manager automatically change to this state).\r
+*\r
+**********/\r
+\r
+/****d* OpenSM: Base/osm_sm_signal_t\r
+* NAME\r
+*      osm_sm_signal_t\r
+*\r
+* DESCRIPTION\r
+*      Enumerates the possible signals used by the OSM_SM_MGR\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _osm_sm_signal\r
+{\r
+  OSM_SM_SIGNAL_INIT = 0,\r
+  OSM_SM_SIGNAL_DISCOVERY_COMPLETED,\r
+  OSM_SM_SIGNAL_POLLING_TIMEOUT,\r
+  OSM_SM_SIGNAL_DISCOVER,\r
+  OSM_SM_SIGNAL_DISABLE,\r
+  OSM_SM_SIGNAL_HANDOVER,\r
+  OSM_SM_SIGNAL_HANDOVER_SENT,\r
+  OSM_SM_SIGNAL_ACKNOWLEDGE,\r
+  OSM_SM_SIGNAL_STANDBY,\r
+  OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED,\r
+  OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED_DONE,\r
+  OSM_SM_SIGNAL_WAIT_FOR_HANDOVER,\r
+  OSM_SM_SIGNAL_MAX\r
+\r
+} osm_sm_signal_t;\r
+/***********/\r
+\r
+/****d* OpenSM/osm_mcast_req_type_t\r
+* NAME\r
+*      osm_mcast_req_type_t\r
+*\r
+* DESCRIPTION\r
+*      Enumerates the possible signals used by the OSM_MCAST_REQUEST\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _osm_mcast_req_type\r
+{\r
+  OSM_MCAST_REQ_TYPE_CREATE,\r
+  OSM_MCAST_REQ_TYPE_JOIN,\r
+  OSM_MCAST_REQ_TYPE_LEAVE,\r
+  OSM_MCAST_REQ_TYPE_SUBNET_CHANGE\r
+\r
+}      osm_mcast_req_type_t;\r
+/***********/\r
+\r
+/****s* OpenSM: Base/MAX_UPDN_GUID_FILE_LINE_LENGTH\r
+* NAME\r
+*      MAX_UPDN_GUID_FILE_LINE_LENGTH\r
+*\r
+* DESCRIPTION\r
+*      The maximum line number when reading updn guid file\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define MAX_UPDN_GUID_FILE_LINE_LENGTH 120\r
+/**********/\r
+\r
+/****s* OpenSM: Base/VendorOUIs\r
+* NAME\r
+*      VendorOUIs\r
+*\r
+* DESCRIPTION\r
+*      Known device vendor ID and GUID OUIs\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_VENDOR_ID_INTEL         0x00D0B7\r
+#define OSM_VENDOR_ID_MELLANOX      0x0002C9\r
+#define OSM_VENDOR_ID_REDSWITCH     0x000617\r
+#define OSM_VENDOR_ID_SILVERSTORM   0x00066A\r
+#define OSM_VENDOR_ID_TOPSPIN       0x0005AD\r
+#define OSM_VENDOR_ID_FUJITSU       0x00E000\r
+#define OSM_VENDOR_ID_FUJITSU2      0x000B5D\r
+#define OSM_VENDOR_ID_VOLTAIRE      0x0008F1\r
+#define OSM_VENDOR_ID_YOTTAYOTTA    0x000453\r
+#define OSM_VENDOR_ID_PATHSCALE     0x001175\r
+#define OSM_VENDOR_ID_IBM           0x000255\r
+#define OSM_VENDOR_ID_DIVERGENET    0x00084E\r
+#define OSM_VENDOR_ID_FLEXTRONICS   0x000B8C\r
+#define OSM_VENDOR_ID_AGILENT       0x0030D3\r
+#define OSM_VENDOR_ID_OBSIDIAN      0x001777\r
+#define OSM_VENDOR_ID_BAYMICRO      0x000BC1\r
+#define OSM_VENDOR_ID_LSILOGIC      0x00A0B8\r
+#define OSM_VENDOR_ID_DDN           0x0001FF\r
+#define OSM_VENDOR_ID_PANTA         0x001393\r
+#define OSM_VENDOR_ID_HP            0x001708\r
+#define OSM_VENDOR_ID_RIOWORKS      0x005045\r
+\r
+/**********/\r
+\r
+END_C_DECLS\r
+\r
+#endif /* _OSM_BASE_H_ */\r
+\r
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_console.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_console.h
new file mode 100644 (file)
index 0000000..4dfcb13
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_console.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_CONSOLE_H_
+#define _OSM_CONSOLE_H_
+
+#include <opensm/osm_base.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_opensm.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+void osm_console(osm_opensm_t *p_osm);
+void osm_console_prompt(void);
+
+END_C_DECLS
+
+#endif /* _OSM_CONSOLE_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_db.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_db.h
new file mode 100644 (file)
index 0000000..3f1f928
--- /dev/null
@@ -0,0 +1,455 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_db.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_DB_H_
+#define _OSM_DB_H_
+
+/*
+ * Abstract:
+ * Declaration of the DB interface.
+ *
+ * $Revision: 1.4 $
+ */
+
+#include <complib/cl_list.h>
+#include <complib/cl_spinlock.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Database
+* NAME
+*      Database
+*
+* DESCRIPTION
+*      The OpenSM database interface provide the means to restore persistat
+*  data, query, modify, delete and evemtually commit it back to the
+*  persistent media. 
+*
+*  The interface is defined such that it can is not "data dependant":
+*  All keys and data items are texts.
+*
+*      The DB implementation should be thread safe, thus callers do not need to
+*  provide serialization.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Eitan Zahavi, Mellanox Technologies LTD
+*
+*********/
+
+/****s* OpenSM: Database/osm_db_domain_t
+* NAME
+*      osm_db_domain_t
+*
+* DESCRIPTION
+*      A domain of the database. Can be viewed as a database table.
+*
+*      The osm_db_domain_t object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_db_domain {
+  struct _osm_db     *p_db;
+  void               *p_domain_imp;
+} osm_db_domain_t;
+/*
+* FIELDS
+*      p_db
+*              Pointer to the parent database object.
+*
+*      p_domain_imp
+*              Pointer to the db implementation object 
+*
+* SEE ALSO
+* osm_db_t
+*********/
+
+/****s* OpenSM: Database/osm_db_t
+* NAME
+*      osm_db_t
+*
+* DESCRIPTION
+*      The main database object.
+*
+*      The osm_db_t object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_db
+{
+  void        *p_db_imp;
+  osm_log_t   *p_log;  
+  cl_list_t    domains;
+} osm_db_t;
+/*
+* FIELDS
+*      p_db_imp
+*              Pointer to the database implementation object
+*
+*      p_log 
+*              Pointer to the OSM logging facility
+*
+*  domains
+*     List of initialize domains
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Database/osm_db_construct
+* NAME
+*      osm_db_construct
+*
+* DESCRIPTION
+*      Construct a database.
+*
+* SYNOPSIS
+*/
+void
+osm_db_construct(
+   IN osm_db_t* const p_db );
+/*
+* PARAMETERS
+*      p_db
+*              [in] Pointer to the database object to custruct
+*
+* RETURN VALUES
+*      NONE
+*
+* SEE ALSO
+*      Database, osm_db_init, osm_db_destroy
+*********/
+
+/****f* OpenSM: Database/osm_db_destroy
+* NAME
+*      osm_db_destroy
+*
+* DESCRIPTION
+*      Destroys the osm_db_t structure.
+*
+* SYNOPSIS
+*/
+void
+osm_db_destroy(
+       IN osm_db_t* const p_db );
+/*
+* PARAMETERS
+*      p_db
+*              [in] Pointer to osm_db_t structure to destroy
+*
+* SEE ALSO
+*      Database, osm_db_construct, osm_db_init
+*********/
+
+/****f* OpenSM: Database/osm_db_init
+* NAME
+*      osm_db_init
+*
+* DESCRIPTION
+*      Initializes the osm_db_t structure.
+*
+* SYNOPSIS
+*/
+int
+osm_db_init(
+       IN osm_db_t* const p_db,
+       IN osm_log_t *p_log  );
+/*
+* PARAMETERS
+*
+*      p_db
+*              [in] Pointer to the database object to initialize
+*
+*      p_log 
+*              [in] Pointer to the OSM logging facility
+*
+* RETURN VALUES
+*      0 on success 1 otherwise
+*
+* SEE ALSO
+*      Database, osm_db_construct, osm_db_destroy
+*********/
+
+/****f* OpenSM: Database/osm_db_domain_init
+* NAME
+*      osm_db_domain_init
+*
+* DESCRIPTION
+*      Initializes the osm_db_domain_t structure.
+*
+* SYNOPSIS
+*/
+osm_db_domain_t*
+osm_db_domain_init(
+   IN osm_db_t* const p_db,
+   IN char *domain_name);
+/*
+* PARAMETERS
+*
+*      p_db
+*              [in] Pointer to the database object to initialize
+*
+*      domain_name
+*              [in] a char array with the domain name.
+*
+* RETURN VALUES
+*      pointer to the new domain object or NULL if failed.
+*
+* SEE ALSO
+*      Database, osm_db_construct, osm_db_destroy
+*********/
+
+/****f* OpenSM: Database/osm_db_restore
+* NAME
+*      osm_db_restore
+*
+* DESCRIPTION
+*      Reads the entire domain from persistent storage - overrides all
+*  existing cached data (if any).
+*
+* SYNOPSIS
+*/
+int 
+osm_db_restore(
+  IN osm_db_domain_t *p_domain);
+/*
+* PARAMETERS
+*
+*      p_domain
+*              [in] Pointer to the database domain object to restore from persistent db
+*
+* RETURN VALUES
+*      0 if successful 1 otherwize
+*
+* SEE ALSO
+*      Database, osm_db_domain_init, osm_db_clear, osm_db_store, 
+*  osm_db_keys, osm_db_lookup, osm_db_update, osm_db_delete
+*********/
+   
+/****f* OpenSM: Database/osm_db_clear
+* NAME
+*      osm_db_clear
+*
+* DESCRIPTION
+*      Clears the entire domain values from/in the cache
+*
+* SYNOPSIS
+*/
+int 
+osm_db_clear(
+  IN osm_db_domain_t *p_domain);
+/*
+* PARAMETERS
+*
+*      p_domain
+*              [in] Pointer to the database domain object to clear
+*
+* RETURN VALUES
+*      0 if successful 1 otherwize
+*
+* SEE ALSO
+*      Database, osm_db_domain_init, osm_db_restore, osm_db_store, 
+*  osm_db_keys, osm_db_lookup, osm_db_update, osm_db_delete
+*********/
+
+/****f* OpenSM: Database/osm_db_store
+* NAME
+*      osm_db_store
+*
+* DESCRIPTION
+*      Store the domain cache back to the database (commit)
+*
+* SYNOPSIS
+*/
+int osm_db_store(
+   IN osm_db_domain_t *p_domain);
+/*
+* PARAMETERS
+*
+*      p_domain
+*              [in] Pointer to the database domain object to restore from persistent db
+*
+* RETURN VALUES
+*      0 if successful 1 otherwize
+*
+* SEE ALSO
+*      Database, osm_db_domain_init, osm_db_restore, osm_db_clear,
+*  osm_db_keys, osm_db_lookup, osm_db_update, osm_db_delete
+*********/
+
+/****f* OpenSM: Database/osm_db_keys
+* NAME
+*      osm_db_keys
+*
+* DESCRIPTION
+*      Retrive all keys of the domain
+*
+* SYNOPSIS
+*/
+int 
+osm_db_keys(
+  IN osm_db_domain_t *p_domain,
+  OUT cl_list_t* p_key_list);
+/*
+* PARAMETERS
+*
+* p_domain
+*    [in] Pointer to the database domain object 
+*
+* p_key_list
+*    [out] List of key values. It should be PRE constructed and initialized.
+*
+* RETURN VALUES
+*      0 if successful 1 otherwize
+*
+* NOTE: the caller needs to free and destruct the list, 
+*       the keys returned are intrnal to the hash and should NOT be free'ed
+*
+* SEE ALSO
+*      Database, osm_db_domain_init, osm_db_restore, osm_db_clear, osm_db_store, 
+*  osm_db_lookup, osm_db_update, osm_db_delete
+*********/
+
+/****f* OpenSM: Database/osm_db_lookup
+* NAME
+*      osm_db_lookup
+*
+* DESCRIPTION
+*      Lookup an entry in the domain by the given key
+*
+* SYNOPSIS
+*/
+/* lookup value by key */
+char *osm_db_lookup(
+   IN osm_db_domain_t *p_domain, 
+   IN char *const p_key);
+/*
+* PARAMETERS
+*
+*  p_domain
+*    [in] Pointer to the database domain object 
+*
+*      key
+*              [in] The key to look for
+*
+* RETURN VALUES
+*  the value as char * or NULL if not found
+*
+* SEE ALSO
+*      Database, osm_db_domain_init, osm_db_restore, osm_db_clear, osm_db_store, 
+*  osm_db_keys, osm_db_update, osm_db_delete
+*********/
+
+/****f* OpenSM: Database/osm_db_update
+* NAME
+*      osm_db_update
+*
+* DESCRIPTION
+*      Set the value of the given key
+*
+* SYNOPSIS
+*/
+int 
+osm_db_update(
+  IN osm_db_domain_t *p_domain, 
+  IN char *const p_key,
+  IN char *const p_val);
+/*
+* PARAMETERS
+*
+*  p_domain
+*    [in] Pointer to the database domain object 
+*
+*      p_key
+*              [in] The key to update
+*
+*      p_val
+*              [in] The value to update
+*
+* RETURN VALUES
+*  0 on success
+*
+* NOTE: the value will be duplicated so can be free'ed 
+*
+* SEE ALSO
+*      Database, osm_db_domain_init, osm_db_restore, osm_db_clear, osm_db_store, 
+*  osm_db_keys, osm_db_lookup, osm_db_delete
+*********/
+
+/****f* OpenSM: Database/osm_db_delete
+* NAME
+*      osm_db_delete
+*
+* DESCRIPTION
+*      Delete an entry by the given key
+*
+* SYNOPSIS
+*/
+int 
+osm_db_delete(
+  IN osm_db_domain_t *p_domain, 
+  IN char *const p_key);
+/*
+* PARAMETERS
+*
+*  p_domain
+*    [in] Pointer to the database domain object 
+*
+*      p_key
+*              [in] The key to look for
+*
+* RETURN VALUES
+*  0 on success
+*
+* SEE ALSO
+*      Database, osm_db_domain_init, osm_db_restore, osm_db_clear, osm_db_store, 
+*  osm_db_keys, osm_db_lookup, osm_db_update
+*********/
+
+END_C_DECLS
+
+#endif         /* _OSM_DB_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_db_pack.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_db_pack.h
new file mode 100644 (file)
index 0000000..5074273
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_db_pack.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/****h* OpenSM/DB-Pack
+* NAME
+*      Database Types
+*
+* DESCRIPTION
+*      This module provides packing and unpacking of the database 
+*  storage into specific types.
+*
+*  The following domains/conversions are supported:
+*  guid2lid - key is a guid and data is a lid.
+*
+* AUTHOR
+*      Eitan Zahavi, Mellanox Technologies LTD
+*
+*********/
+
+#ifndef _OSM_DB_PACK_H_
+#define _OSM_DB_PACK_H_
+
+#include <opensm/osm_db.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****f* OpenSM: DB-Pack/osm_db_guid2lid_init
+* NAME
+*      osm_db_guid2lid_init
+*
+* DESCRIPTION
+*      Initialize a domain for the guid2lid table
+*
+* SYNOPSIS
+*/
+static inline osm_db_domain_t*
+osm_db_guid2lid_init(
+  IN osm_db_t* const p_db )
+{
+  return( osm_db_domain_init( p_db, "guid2lid" ) );
+}
+/*
+* PARAMETERS
+*      p_db
+*              [in] Pointer to the database object to construct
+*
+* RETURN VALUES
+*      The pointer to the new allocated domain object or NULL.
+*
+* NOTE: DB domains are destroyed by the osm_db_destroy
+*
+* SEE ALSO
+*      Database, osm_db_init, osm_db_destroy
+*********/
+
+/****f* OpenSM: DB-Pack/osm_db_guid2lid_init
+* NAME
+*      osm_db_guid2lid_init
+*
+* DESCRIPTION
+*      Initialize a domain for the guid2lid table
+*
+* SYNOPSIS
+*/
+typedef struct _osm_db_guid_elem {
+  cl_list_item_t item;
+  uint64_t       guid;
+} osm_db_guid_elem_t;
+/*
+* FIELDS
+*      item
+*              required for list manipulations
+*
+*  guid
+*
+************/
+
+/****f* OpenSM: DB-Pack/osm_db_guid2lid_guids
+* NAME
+*      osm_db_guid2lid_guids
+*
+* DESCRIPTION
+*      Provides back a list of guid elements.
+*
+* SYNOPSIS
+*/
+int
+osm_db_guid2lid_guids(
+  IN osm_db_domain_t* const p_g2l,
+  OUT cl_qlist_t* p_guid_list );
+/*
+* PARAMETERS
+*      p_g2l
+*              [in] Pointer to the guid2lid domain
+*
+*  p_guid_list
+*     [out] A quick list of guid elements of type osm_db_guid_elem_t
+*   
+* RETURN VALUES
+*      0 if successful 
+*
+* NOTE: the output qlist should be initialized and each item freed
+*       by the caller, then destroyed.
+*
+* SEE ALSO
+* osm_db_guid2lid_init, osm_db_guid2lid_guids, osm_db_guid2lid_get 
+* osm_db_guid2lid_set, osm_db_guid2lid_delete
+*********/
+
+/****f* OpenSM: DB-Pack/osm_db_guid2lid_get
+* NAME
+*      osm_db_guid2lid_get
+*
+* DESCRIPTION
+*      Get a lid range by given guid.
+*
+* SYNOPSIS
+*/
+int
+osm_db_guid2lid_get(
+  IN osm_db_domain_t* const p_g2l,
+  IN uint64_t guid,
+  OUT uint16_t *p_min_lid,
+  OUT uint16_t *p_max_lid);
+/*
+* PARAMETERS
+*      p_g2l
+*              [in] Pointer to the guid2lid domain
+*
+*  guid
+*     [in] The guid to look for
+*   
+*  p_min_lid
+*     [out] Pointer to the resulting min lid in host order.
+*
+*  p_max_lid
+*     [out] Pointer to the resulting max lid in host order.
+*
+* RETURN VALUES
+*      0 if successful. The lid will be set to 0 if not found.
+*
+* SEE ALSO
+* osm_db_guid2lid_init, osm_db_guid2lid_guids 
+* osm_db_guid2lid_set, osm_db_guid2lid_delete
+*********/
+
+/****f* OpenSM: DB-Pack/osm_db_guid2lid_set
+* NAME
+*      osm_db_guid2lid_set
+*
+* DESCRIPTION
+*      Set a lid range for the given guid.
+*
+* SYNOPSIS
+*/
+int
+osm_db_guid2lid_set(
+  IN osm_db_domain_t* const p_g2l,
+  IN uint64_t guid,
+  IN uint16_t min_lid,
+  IN uint16_t max_lid);
+/*
+* PARAMETERS
+*      p_g2l
+*              [in] Pointer to the guid2lid domain
+*
+*  guid
+*     [in] The guid to look for
+*
+*  min_lid
+*     [in] The min lid value to set
+*   
+*  max_lid
+*     [in] The max lid value to set
+*   
+* RETURN VALUES
+*      0 if successful 
+*
+* SEE ALSO
+* osm_db_guid2lid_init, osm_db_guid2lid_guids 
+* osm_db_guid2lid_get, osm_db_guid2lid_delete
+*********/
+
+/****f* OpenSM: DB-Pack/osm_db_guid2lid_delete
+* NAME
+*      osm_db_guid2lid_delete
+*
+* DESCRIPTION
+*      Delete the entry by the given guid
+*
+* SYNOPSIS
+*/
+int
+osm_db_guid2lid_delete(
+  IN osm_db_domain_t* const p_g2l,
+  IN uint64_t guid );
+/*
+* PARAMETERS
+*      p_g2l
+*              [in] Pointer to the guid2lid domain
+*
+*  guid
+*     [in] The guid to look for
+*   
+* RETURN VALUES
+*      0 if successful otherwise 1
+*
+* SEE ALSO
+* osm_db_guid2lid_init, osm_db_guid2lid_guids 
+* osm_db_guid2lid_get, osm_db_guid2lid_set
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_DB_PACK_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_drop_mgr.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_drop_mgr.h
new file mode 100644 (file)
index 0000000..48c6ace
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_drop_mgr.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_drop_mgr_t.
+ *     This object represents the Drop Manager object.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_DROP_MGR_H_
+#define _OSM_DROP_MGR_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Drop Manager
+* NAME
+*      Drop Manager
+*
+* DESCRIPTION
+*      The Drop Manager object encapsulates the information
+*      needed to receive the SwitchInfo attribute from a node.
+*
+*      The Drop Manager object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Drop Manager/osm_drop_mgr_t
+* NAME
+*      osm_drop_mgr_t
+*
+* DESCRIPTION
+*      Drop Manager structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_drop_mgr
+{
+       osm_subn_t                                      *p_subn;
+       osm_log_t                                       *p_log;
+       osm_req_t                                       *p_req;
+       cl_plock_t                                      *p_lock;
+
+} osm_drop_mgr_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_req
+*              Pointer to the Request object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+* SEE ALSO
+*      Drop Manager object
+*********/
+
+/****f* OpenSM: Drop Manager/osm_drop_mgr_construct
+* NAME
+*      osm_drop_mgr_construct
+*
+* DESCRIPTION
+*      This function constructs a Drop Manager object.
+*
+* SYNOPSIS
+*/
+void osm_drop_mgr_construct(
+       IN osm_drop_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to a Drop Manager object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_drop_mgr_init, osm_drop_mgr_destroy
+*
+*      Calling osm_drop_mgr_construct is a prerequisite to calling any other
+*      method except osm_drop_mgr_init.
+*
+* SEE ALSO
+*      Drop Manager object, osm_drop_mgr_init,
+*      osm_drop_mgr_destroy
+*********/
+
+/****f* OpenSM: Drop Manager/osm_drop_mgr_destroy
+* NAME
+*      osm_drop_mgr_destroy
+*
+* DESCRIPTION
+*      The osm_drop_mgr_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_drop_mgr_destroy(
+       IN osm_drop_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Drop Manager object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_drop_mgr_construct or osm_drop_mgr_init.
+*
+* SEE ALSO
+*      Drop Manager object, osm_drop_mgr_construct,
+*      osm_drop_mgr_init
+*********/
+
+/****f* OpenSM: Drop Manager/osm_drop_mgr_init
+* NAME
+*      osm_drop_mgr_init
+*
+* DESCRIPTION
+*      The osm_drop_mgr_init function initializes a
+*      Drop Manager object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_drop_mgr_init(
+       IN osm_drop_mgr_t* const p_mgr,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN osm_req_t* const p_req,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to an osm_drop_mgr_t object to initialize.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_req
+*              [in] Pointer to an osm_req_t object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the Drop Manager object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Drop Manager methods.
+*
+* SEE ALSO
+*      Drop Manager object, osm_drop_mgr_construct,
+*      osm_drop_mgr_destroy
+*********/
+
+/****f* OpenSM: Drop Manager/osm_drop_mgr_process
+* NAME
+*      osm_drop_mgr_process
+*
+* DESCRIPTION
+*      Process the SwitchInfo attribute.
+*
+* SYNOPSIS
+*/
+void osm_drop_mgr_process(
+       IN const osm_drop_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to an osm_drop_mgr_t object.
+*
+* RETURN VALUES
+*      None
+*
+* NOTES
+*      This function processes a SwitchInfo attribute.
+*
+* SEE ALSO
+*      Drop Manager, Switch Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_DROP_MGR_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_errors.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_errors.h
new file mode 100644 (file)
index 0000000..d323cdf
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_errors.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of error code ranges for the various OpenSM modules.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_ERRORS_H_
+#define _OSM_ERRORS_H_
+
+/*
+       Generic Request Controller
+       0100 - 01FF
+
+       Node Info Receive Controller
+       0200 - 02FF
+
+       Generic Requester
+       0300 - 03FF
+
+       Node Info Receiver
+       0400 - 04FF
+
+       Node Description Receiver
+       0500 - 05FF
+
+       Node Description Receive Controller
+       0600 - 06FF
+
+       Port Info Receiver
+       0700 - 07FF
+
+       Port Info Receive Controller
+       0800 - 08FF
+
+       Mad Pool
+       0900 - 09FF
+
+       SM
+       1000 - 10FF
+
+       SM MAD Controller
+       1100 - 11FF
+
+       VL15 Interface
+       1200 - 12FF
+
+       Switch Info Receive Controller
+       1300 - 13FF
+
+       Switch Info Receiver
+       1400 - 14FF
+
+       State Manager
+       1500 - 15FF
+
+       State Manager Controller
+       1600 - 16FF
+
+       LID Manager
+       1700 - 17FF
+
+       Link Manager
+       1800 - 18FF
+
+       Drop Manager
+       1900 - 19FF
+
+       Linear Forwarding Receive Controller
+       2000 - 20FF
+
+       Linear Forwarding Receiver
+       2100 - 21FF
+
+       Vendor Specific
+       2200 - 22FF
+
+       SMInfo Receive Controller
+       2300 - 23FF
+
+       SMInfo Info Receiver
+       2400 - 24FF
+
+       Generic Responder
+       2500 - 25FF
+
+       Linear Forwarding Receive Controller
+       2600 - 26FF
+
+       Linear Forwarding Receiver
+       2700 - 27FF
+       
+       SA MAD controller
+       2800 - 28FF
+
+       Node Record Controller
+       2900 - 29FF
+
+       PortInfo Record Controller
+       3000 - 30FF
+
+       Link Record Controller
+       3100 - 31FF
+
+       Path Record Controller
+       3200 - 32FF
+       
+       SMInfo Record Controller
+       3300 - 33FF
+       
+       Multicast Record Controller
+       3400 - 34FF
+
+       Unicast Manager
+       3500 - 35FF
+
+       Multicast Manager
+       3600 - 36FF
+
+       SA Response
+       3700 - 37FF
+
+       Link Record Receiver
+       3800 - 38FF
+
+       Multicast Forwarding Receive Controller
+       3900 - 39FF
+
+       Multicast Forwarding Receiver
+       4000 - 40FF
+
+       SMInfo Record Receiver
+       4100 - 41FF
+
+       PortInfo Record Receiver
+       4200 - 42FF
+
+       Service Record Receiver
+       4300 - 43FF
+
+*/
+
+#endif /* _OSM_ERRORS_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_fwd_tbl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_fwd_tbl.h
new file mode 100644 (file)
index 0000000..7b05384
--- /dev/null
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_fwd_tbl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_fwd_tbl_t.
+ *     This object represents a unicast forwarding table.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_FWD_TBL_H_
+#define _OSM_FWD_TBL_H_
+
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_rand_fwd_tbl.h>
+#include <opensm/osm_lin_fwd_tbl.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Forwarding Table
+* NAME
+*      Forwarding Table
+*
+* DESCRIPTION
+*      The Forwarding Table objects encapsulate the information
+*      needed by the OpenSM to manage forwarding tables.  The OpenSM
+*      allocates one Forwarding Table object per switch in the
+*      IBA subnet.
+*
+*      The Forwarding Table objects are not thread safe, thus
+*      callers must provide serialization.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Forwarding Table/osm_fwd_tbl_t
+* NAME
+*      osm_fwd_tbl_t
+*
+* DESCRIPTION
+*      Forwarding Table structure.  This object hides the type
+*      of fowarding table (linear or random) actually used by
+*      the switch.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_fwd_tbl_t
+{
+       osm_rand_fwd_tbl_t      *p_rnd_tbl;
+       osm_lin_fwd_tbl_t       *p_lin_tbl;
+
+} osm_fwd_tbl_t;
+/*
+* FIELDS
+*      p_rnd_tbl
+*              Pointer to the switch's Random Forwarding Table object.
+*              If the switch does not use a Random Forwarding Table,
+*              then this pointer is NULL.
+*
+*      p_lin_tbl
+*              Pointer to the switch's Linear Forwarding Table object.
+*              If the switch does not use a Linear Forwarding Table,
+*              then this pointer is NULL.
+*
+* SEE ALSO
+*      Forwarding Table object, Random Forwarding Table object.
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_init
+* NAME
+*      osm_fwd_tbl_init
+*
+* DESCRIPTION
+*      Initializes a Forwarding Table object.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_fwd_tbl_init(
+       IN osm_fwd_tbl_t* const p_tbl,
+       IN const ib_switch_info_t* const p_si );
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Forwarding Table object.
+*
+*      p_si
+*              [in] Pointer to the SwitchInfo attribute of the associated
+*              switch.
+*
+* RETURN VALUE
+*      IB_SUCCESS if the operation is successful.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_destroy
+* NAME
+*      osm_fwd_tbl_destroy
+*
+* DESCRIPTION
+*      Destroys a Forwarding Table object.
+*
+* SYNOPSIS
+*/
+void
+osm_fwd_tbl_destroy(
+       IN osm_fwd_tbl_t* const p_tbl );
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_get
+* NAME
+*      osm_fwd_tbl_get
+*
+* DESCRIPTION
+*      Returns the port that routes the specified LID.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_fwd_tbl_get(
+       IN const osm_fwd_tbl_t* const p_tbl,
+       IN uint16_t const lid_ho )
+{
+       if( p_tbl->p_lin_tbl )
+               return( osm_lin_fwd_tbl_get( p_tbl->p_lin_tbl, lid_ho ) );
+       else
+               return( osm_rand_fwd_tbl_get( p_tbl->p_rnd_tbl, lid_ho ) );
+}
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Forwarding Table object.
+*
+*      lid_ho
+*              [in] LID (host order) for which to find the route.
+*
+* RETURN VALUE
+*      Returns the port that routes the specified LID.
+*      IB_INVALID_PORT_NUM if the table does not have a route for this LID.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_set
+* NAME
+*      osm_fwd_tbl_set
+*
+* DESCRIPTION
+*      Sets the port to route the specified LID.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_fwd_tbl_set(
+       IN osm_fwd_tbl_t* const p_tbl,
+       IN const uint16_t lid_ho,
+       IN const uint8_t port )
+{
+       CL_ASSERT( p_tbl );
+       if( p_tbl->p_lin_tbl )
+               osm_lin_fwd_tbl_set( p_tbl->p_lin_tbl, lid_ho, port );
+       else
+               osm_rand_fwd_tbl_set( p_tbl->p_rnd_tbl, lid_ho, port );
+}
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Forwarding Table object.
+*
+*      lid_ho
+*              [in] LID value (host order) for which to set the route.
+*
+*      port
+*              [in] Port to route the specified LID value.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_set_block
+* NAME
+*      osm_fwd_tbl_set_block
+*
+* DESCRIPTION
+*      Copies the specified block into the Forwarding Table.
+*
+* SYNOPSIS
+*/
+static inline ib_api_status_t
+osm_fwd_tbl_set_block(
+       IN osm_fwd_tbl_t* const p_tbl,
+       IN const uint8_t* const p_block,
+       IN const uint32_t block_num )
+{
+       CL_ASSERT( p_tbl );
+       if( p_tbl->p_lin_tbl )
+               return( osm_lin_fwd_tbl_set_block( p_tbl->p_lin_tbl,
+                               p_block, block_num ) );
+       else
+               return( osm_rand_fwd_tbl_set_block( p_tbl->p_rnd_tbl,
+                               p_block, block_num ) );
+}
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_get_size
+* NAME
+*      osm_fwd_tbl_get_size
+*
+* DESCRIPTION
+*      Returns the number of entries available in the forwarding table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_fwd_tbl_get_size(
+       IN const osm_fwd_tbl_t* const p_tbl )
+{
+       CL_ASSERT( p_tbl );
+       if( p_tbl->p_lin_tbl )
+               return( osm_lin_fwd_tbl_get_size( p_tbl->p_lin_tbl ) );
+       else
+               return( osm_rand_fwd_tbl_get_size( p_tbl->p_rnd_tbl ) );
+}
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+*      Returns the number of entries available in the forwarding table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_get_lids_per_block
+* NAME
+*      osm_fwd_tbl_get_lids_per_block
+*
+* DESCRIPTION
+*      Returns the number of LIDs per LID block.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_fwd_tbl_get_lids_per_block(
+       IN const osm_fwd_tbl_t* const p_tbl )
+{
+       CL_ASSERT( p_tbl );
+       if( p_tbl->p_lin_tbl )
+               return( osm_lin_fwd_tbl_get_lids_per_block( p_tbl->p_lin_tbl ) );
+       else
+               return( osm_rand_fwd_tbl_get_lids_per_block( p_tbl->p_rnd_tbl ) );
+}
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+*      Returns the number of LIDs per LID block.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_get_max_block_id_in_use
+* NAME
+*      osm_fwd_tbl_get_max_block_id_in_use
+*
+* DESCRIPTION
+*      Returns the number of LIDs per LID block.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_fwd_tbl_get_max_block_id_in_use(
+       IN const osm_fwd_tbl_t* const p_tbl,
+       IN const uint16_t lid_top_ho )
+{
+       CL_ASSERT( p_tbl );
+       if( p_tbl->p_lin_tbl )
+               return( osm_lin_fwd_tbl_get_max_block_id_in_use(
+                               p_tbl->p_lin_tbl, lid_top_ho ) );
+       else
+               return( osm_rand_fwd_tbl_get_max_block_id_in_use(
+                               p_tbl->p_rnd_tbl, lid_top_ho ) );
+}
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+*      Returns the number of LIDs per LID block.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif         /* _OSM_FWD_TBL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_helper.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_helper.h
new file mode 100644 (file)
index 0000000..90931bb
--- /dev/null
@@ -0,0 +1,620 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_helper.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_HELPER_H_
+#define _OSM_HELPER_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_path.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/*
+ * Abstract:
+ *     Declaration of helpful functions.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+/****f* OpenSM: Helper/ib_get_sa_method_str
+ * NAME
+ *     ib_get_sa_method_str
+ *
+ * DESCRIPTION
+ *     Returns a string for the specified SA Method value.
+ *
+ * SYNOPSIS
+ */
+const char*
+ib_get_sa_method_str(
+  IN uint8_t method );
+/*
+ * PARAMETERS
+ *     method
+ *             [in] Network order METHOD ID value.
+ *
+ * RETURN VALUES
+ *     Pointer to the method string.
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* OpenSM: Helper/ib_get_sm_method_str
+* NAME
+*      ib_get_sm_method_str
+*
+* DESCRIPTION
+*      Returns a string for the specified SM Method value.
+*
+* SYNOPSIS
+*/
+const char*
+ib_get_sm_method_str(
+       IN uint8_t method );
+/*
+* PARAMETERS
+*      method
+*              [in] Network order METHOD ID value.
+*
+* RETURN VALUES
+*      Pointer to the method string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Helper/ib_get_sm_attr_str
+* NAME
+*      ib_get_sm_attr_str
+*
+* DESCRIPTION
+*      Returns a string for the specified SM attribute value.
+*
+* SYNOPSIS
+*/
+const char*
+ib_get_sm_attr_str(
+       IN ib_net16_t attr );
+/*
+* PARAMETERS
+*      attr
+*              [in] Network order attribute ID value.
+*
+* RETURN VALUES
+*      Pointer to the attribute string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Helper/ib_get_sa_attr_str
+* NAME
+*      ib_get_sa_attr_str
+*
+* DESCRIPTION
+*      Returns a string for the specified SA attribute value.
+*
+* SYNOPSIS
+*/
+const char*
+ib_get_sa_attr_str(
+       IN ib_net16_t attr );
+/*
+* PARAMETERS
+*      attr
+*              [in] Network order attribute ID value.
+*
+* RETURN VALUES
+*      Pointer to the attribute string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Helper/osm_dump_port_info
+* NAME
+*      osm_dump_port_info
+*
+* DESCRIPTION
+*      Dumps the PortInfo attribute to the log.
+*
+* SYNOPSIS
+*/
+void osm_dump_port_info(
+       IN osm_log_t* const p_log,
+       IN const ib_net64_t node_guid,
+       IN const ib_net64_t port_guid,
+       IN const uint8_t port_num,
+       IN const ib_port_info_t* const p_pi,
+       IN const osm_log_level_t log_level );
+/*
+* PARAMETERS
+*      p_log
+*              [in] Pointer to the osm_log_t object
+*
+*      node_guid
+*              [in] Node GUID that owns this port.
+*
+*      port_guid
+*              [in] Port GUID for this port.
+*
+*      port_num
+*              [in] Port number for this port.
+*
+*      p_pi
+*              [in] Pointer to the PortInfo attribute
+*
+*      log_level
+*              [in] Log verbosity level with which to dump the data.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+void
+osm_dump_path_record(
+       IN osm_log_t* const p_log,
+       IN const ib_path_rec_t* const p_pr,
+       IN const osm_log_level_t log_level );
+
+void
+osm_dump_multipath_record(
+       IN osm_log_t* const p_log,
+       IN const ib_multipath_rec_t* const p_mpr,
+       IN const osm_log_level_t log_level );
+
+void
+osm_dump_node_record(
+       IN osm_log_t* const p_log,
+       IN const ib_node_record_t* const p_nr,
+       IN const osm_log_level_t log_level );
+
+void
+osm_dump_mc_record(
+       IN osm_log_t* const p_log,
+       IN const ib_member_rec_t* const p_mcmr,
+       IN const osm_log_level_t log_level );
+
+void
+osm_dump_link_record(
+       IN osm_log_t*                   const p_log,
+       IN const ib_link_record_t*      const p_lr,
+       IN const osm_log_level_t        log_level );
+
+void
+osm_dump_service_record(
+       IN osm_log_t* const p_log,
+       IN const ib_service_record_t* const p_sr,
+       IN const osm_log_level_t log_level );
+
+void
+osm_dump_portinfo_record(
+       IN osm_log_t* const p_log,
+       IN const ib_portinfo_record_t* const p_pir,
+       IN const osm_log_level_t log_level );
+
+void
+osm_dump_guidinfo_record(
+       IN osm_log_t* const p_log,
+       IN const ib_guidinfo_record_t* const p_gir,
+       IN const osm_log_level_t log_level );
+
+void
+osm_dump_inform_info(
+       IN osm_log_t* const p_log,
+       IN const ib_inform_info_t* const p_ii,
+       IN const osm_log_level_t log_level );
+
+void
+osm_dump_inform_info_record(
+       IN osm_log_t* const p_log,
+       IN const ib_inform_info_record_t* const p_iir,
+       IN const osm_log_level_t log_level );
+
+void
+osm_dump_switch_info_record(
+       IN osm_log_t* const p_log,
+       IN const ib_switch_info_record_t* const p_sir,
+       IN const osm_log_level_t log_level );
+
+void
+osm_dump_sm_info_record(
+       IN osm_log_t* const p_log,
+       IN const ib_sminfo_record_t* const p_smir,
+       IN const osm_log_level_t log_level );
+
+void
+osm_dump_pkey_block( 
+       IN osm_log_t* const p_log,
+       IN uint64_t port_guid, 
+       IN uint16_t block_num,
+       IN uint8_t port_num,
+       IN const ib_pkey_table_t* const p_pkey_tbl,
+       IN const osm_log_level_t log_level );
+
+void
+osm_dump_slvl_map_table( 
+       IN osm_log_t* const p_log,
+       IN uint64_t port_guid, 
+       IN uint8_t in_port_num,
+       IN uint8_t out_port_num,
+       IN const ib_slvl_table_t* const p_slvl_tbl,
+       IN const osm_log_level_t log_level );
+
+void
+osm_dump_vl_arb_table( 
+       IN osm_log_t* const p_log,
+       IN uint64_t port_guid, 
+       IN uint8_t block_num,
+       IN uint8_t port_num,
+       IN const ib_vl_arb_table_t* const p_vla_tbl,
+       IN const osm_log_level_t log_level );
+
+/****f* OpenSM: Helper/osm_dump_port_info
+* NAME
+*      osm_dump_port_info
+*
+* DESCRIPTION
+*      Dumps the PortInfo attribute to the log.
+*
+* SYNOPSIS
+*/
+void osm_dump_node_info(
+       IN osm_log_t* const p_log,
+       IN const ib_node_info_t* const p_ni,
+       IN const osm_log_level_t log_level );
+/*
+* PARAMETERS
+*      p_log
+*              [in] Pointer to the osm_log_t object
+*
+*      p_ni
+*              [in] Pointer to the NodeInfo attribute
+*
+*      log_level
+*              [in] Log verbosity level with which to dump the data.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Helper/osm_dump_sm_info
+* NAME
+*      osm_dump_sm_info
+*
+* DESCRIPTION
+*      Dumps the SMInfo attribute to the log.
+*
+* SYNOPSIS
+*/
+void
+osm_dump_sm_info(
+       IN osm_log_t* const p_log,
+       IN const ib_sm_info_t* const p_smi,
+       IN const osm_log_level_t log_level );
+/*
+* PARAMETERS
+*      p_log
+*              [in] Pointer to the osm_log_t object
+*
+*      p_smi
+*              [in] Pointer to the SMInfo attribute
+*
+*      log_level
+*              [in] Log verbosity level with which to dump the data.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Helper/osm_dump_switch_info
+* NAME
+*      osm_dump_switch_info
+*
+* DESCRIPTION
+*      Dumps the SwitchInfo attribute to the log.
+*
+* SYNOPSIS
+*/
+void
+osm_dump_switch_info(
+       IN osm_log_t* const p_log,
+       IN const ib_switch_info_t* const p_si,
+       IN const osm_log_level_t log_level );
+/*
+* PARAMETERS
+*      p_log
+*              [in] Pointer to the osm_log_t object
+*
+*      p_si
+*              [in] Pointer to the SwitchInfo attribute
+*
+*      log_level
+*              [in] Log verbosity level with which to dump the data.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Helper/osm_dump_notice
+* NAME
+*      osm_dump_notice
+*
+* DESCRIPTION
+*      Dumps the Notice attribute to the log.
+*
+* SYNOPSIS
+*/
+void
+osm_dump_notice(
+       IN osm_log_t* const p_log,
+       IN const ib_mad_notice_attr_t *p_ntci,
+       IN const osm_log_level_t log_level );
+/*
+* PARAMETERS
+*      p_log
+*              [in] Pointer to the osm_log_t object
+*
+*      p_ntci
+*              [in] Pointer to the Notice attribute
+*
+*      log_level
+*              [in] Log verbosity level with which to dump the data.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/osm_get_disp_msg_str
+* NAME
+*      osm_get_disp_msg_str
+*
+* DESCRIPTION
+*      Returns a string for the specified Dispatcher message.
+*
+* SYNOPSIS
+*/
+const char*
+osm_get_disp_msg_str(
+       IN cl_disp_msgid_t msg );
+/*
+* PARAMETERS
+*      msg
+*              [in] Dispatcher message ID value.
+*
+* RETURN VALUES
+*      Pointer to the message discription string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+void osm_dump_dr_path(
+       IN osm_log_t* const p_log,
+       IN const osm_dr_path_t* const p_path, 
+       IN const osm_log_level_t level );
+
+void osm_dump_smp_dr_path(
+       IN osm_log_t* const p_log,
+       IN const ib_smp_t* const p_smp, 
+       IN const osm_log_level_t level );
+
+void osm_dump_dr_smp(
+       IN osm_log_t* const p_log,
+       IN const ib_smp_t* const p_smp,
+       IN const osm_log_level_t level );
+
+void osm_dump_sa_mad(
+       IN osm_log_t* const p_log,
+       IN const ib_sa_mad_t* const p_smp,
+       IN const osm_log_level_t level );
+
+/****f* IBA Base: Types/osm_get_sm_state_str
+* NAME
+*      osm_get_sm_state_str
+*
+* DESCRIPTION
+*      Returns a string for the specified SM state.
+*
+* SYNOPSIS
+*/
+const char*
+osm_get_sm_state_str(
+       IN osm_sm_state_t state );
+/*
+* PARAMETERS
+*      state
+*              [in] SM State value
+*
+* RETURN VALUES
+*      Pointer to the state discription string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/osm_get_sm_signal_str
+* NAME
+*      osm_get_sm_signal_str
+*
+* DESCRIPTION
+*      Returns a string for the specified SM state.
+*
+* SYNOPSIS
+*/
+const char*
+osm_get_sm_signal_str(
+       IN osm_signal_t signal );
+/*
+* PARAMETERS
+*      state
+*              [in] Signal value
+*
+* RETURN VALUES
+*      Pointer to the signal discription string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+const char*
+osm_get_port_state_str_fixed_width(
+  IN uint8_t port_state );
+
+const char*
+osm_get_node_type_str_fixed_width(
+       IN uint32_t node_type );
+
+const char*
+osm_get_manufacturer_str(
+       IN uint64_t                                     const guid_ho );
+
+const char*
+osm_get_mtu_str(
+       IN uint8_t                                      const mtu );
+
+const char*
+osm_get_lwa_str(
+       IN uint8_t                                      const lwa );
+
+const char*
+osm_get_mtu_str(
+       IN uint8_t                                      const mtu );
+
+const char*
+osm_get_lwa_str(
+       IN uint8_t                                      const lwa );
+
+const char*
+osm_get_lsa_str(
+       IN uint8_t                                      const lsa );
+
+
+/****f* IBA Base: Types/osm_get_sm_mgr_signal_str
+* NAME
+*      osm_get_sm_mgr_signal_str
+*
+* DESCRIPTION
+*      Returns a string for the specified SM manager signal.
+*
+* SYNOPSIS
+*/
+const char*
+osm_get_sm_mgr_signal_str(
+       IN osm_sm_signal_t signal );
+/*
+* PARAMETERS
+*      signal
+*              [in] SM manager signal
+*
+* RETURN VALUES
+*      Pointer to the signal discription string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/osm_get_sm_mgr_state_str
+* NAME
+*      osm_get_sm_mgr_state_str
+*
+* DESCRIPTION
+*      Returns a string for the specified SM manager state.
+*
+* SYNOPSIS
+*/
+const char*
+osm_get_sm_mgr_state_str(
+       IN uint16_t state );
+/*
+* PARAMETERS
+*      state
+*              [in] SM manager state
+*
+* RETURN VALUES
+*      Pointer to the state discription string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_HELPER_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_inform.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_inform.h
new file mode 100644 (file)
index 0000000..e0d5358
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_inform.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_inform_rec_t.
+ *     This object represents an IBA Inform Record.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * Author:
+ *    Eitan Zahavi, Mellanox
+ *
+ * $Revision: 1.5 $
+ */
+
+#ifndef _OSM_INFR_H_
+#define _OSM_INFR_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_spinlock.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_informinfo.h>
+#include <opensm/osm_trap_rcv.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Inform Record
+* NAME
+*      Inform Record
+*
+* DESCRIPTION
+*      The Inform record encapsulates the information needed by the
+*      SA to manage InformInfo registrations and sending Reports(Notice)
+*      when SM receives Traps for registered LIDs.
+*
+*      The inform records is not thread safe, thus callers must provide
+*      serialization.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*    Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: Inform Record/osm_infr_t
+* NAME
+*      osm_infr_t
+*
+* DESCRIPTION
+*      Inform Record structure.
+*
+*      The osm_infr_t object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_infr_t
+{
+       cl_list_item_t          list_item;
+       osm_bind_handle_t       h_bind;
+       osm_infr_rcv_t*         p_infr_rcv;
+       osm_mad_addr_t          report_addr;
+       ib_inform_info_record_t inform_record;
+} osm_infr_t;
+/*
+* FIELDS
+*      list_item
+*              List Item for qlist linkage.  Must be first element!!
+*
+*      h_bind
+*              A handle of lower level mad srvc
+*
+*      p_infr_rcv
+*              The receiver of inform_info's
+*
+*      report_addr
+*              Report address
+*
+*      inform_record
+*              The Inform Info Record
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Inform Record/osm_infr_new
+* NAME
+*      osm_infr_new
+*
+* DESCRIPTION
+*      Allocates and initializes a Inform Record for use.
+*
+* SYNOPSIS
+*/
+osm_infr_t*
+osm_infr_new(
+       IN const osm_infr_t *p_infr_rec );
+/*
+* PARAMETERS
+*      p_inf_rec
+*              [in] Pointer to IB Inform Record
+*
+* RETURN VALUES
+*      pointer to osm_infr_t structure.
+*
+* NOTES
+*      Allows calling other service record methods.
+*
+* SEE ALSO
+*      Inform Record, osm_infr_construct, osm_infr_destroy
+*********/
+
+/****f* OpenSM: Inform Record/osm_infr_init
+* NAME
+*      osm_infr_new
+*
+* DESCRIPTION
+*      Initializes the osm_infr_t structure.
+*
+* SYNOPSIS
+*/
+void
+osm_infr_init(
+       IN osm_infr_t* const p_infr,
+       IN const osm_infr_t *p_infr_rec );
+/*
+* PARAMETERS
+*      p_infr
+*              [in] Pointer to osm_infr_t structure
+*      p_inf_rec
+*              [in] Pointer to the ib_inform_info_record_t
+*
+* SEE ALSO
+*      Inform Record, osm_infr_construct, osm_infr_destroy
+*********/
+
+/****f* OpenSM: Inform Record/osm_infr_construct
+* NAME
+*      osm_infr_construct
+*
+* DESCRIPTION
+*      Constructs the osm_infr_t structure.
+*
+* SYNOPSIS
+*/
+void
+osm_infr_construct(
+       IN osm_infr_t* const p_infr );
+/*
+* PARAMETERS
+*      p_infr
+*              [in] Pointer to osm_infr_t structure
+*
+* SEE ALSO
+*      Inform Record, osm_infr_construct, osm_infr_destroy
+*********/
+
+/****f* OpenSM: Inform Record/osm_infr_destroy
+* NAME
+*      osm_infr_destroy
+*
+* DESCRIPTION
+*      Constructs the osm_infr_t structure.
+*
+* SYNOPSIS
+*/
+void
+osm_infr_destroy(
+       IN osm_infr_t* const p_infr );
+/*
+* PARAMETERS
+*      p_infr
+*              [in] Pointer to osm_infr_t structure
+*
+* SEE ALSO
+*      Inform Record, osm_infr_construct, osm_infr_destroy
+*********/
+
+/****f* OpenSM: Inform Record/osm_infr_get_by_rec
+* NAME
+*      osm_infr_get_by_rec
+*
+* DESCRIPTION
+*      Find a matching osm_infr_t in the subnet DB by inform_info_record
+*
+* SYNOPSIS
+*/
+osm_infr_t*
+osm_infr_get_by_rec(
+       IN osm_subn_t   const   *p_subn,
+       IN osm_log_t    *p_log,
+       IN osm_infr_t*  const   p_infr_rec );
+/*
+* PARAMETERS
+*      p_subn 
+*              [in] Pointer to the subnet object
+*
+*      p_log
+*              [in] Pointer to the log object
+*
+*      p_inf_rec
+*              [in] Pointer to an inform_info record
+*
+* RETURN
+*      The matching osm_infr_t
+* SEE ALSO
+*      Inform Record, osm_infr_construct, osm_infr_destroy
+*********/
+
+void
+osm_infr_insert_to_db(
+       IN osm_subn_t   *p_subn,
+       IN osm_log_t    *p_log,
+       IN osm_infr_t   *p_infr);
+
+void
+osm_infr_remove_from_db(
+       IN osm_subn_t   *p_subn,
+       IN osm_log_t    *p_log,
+       IN osm_infr_t   *p_infr);
+
+/****f* OpenSM: Inform Record/osm_report_notice
+* NAME
+*      osm_report_notice
+*
+* DESCRIPTION
+* Once a Trap was received by the osm_trap_rcv, or a Trap sourced in 
+* the SM was sent (Traps 64-67) this routine is called with a copy of
+* the notice data.
+* Given a notice attribute - compare and see if it matches the InformInfo
+* Element and if it does - call the Report(Notice) for the
+* target QP registered by the address stored in the InformInfo element
+*      
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_report_notice(
+       IN osm_log_t* const p_log,
+       IN osm_subn_t* p_subn,
+       IN ib_mad_notice_attr_t* p_ntc );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to the trap receiver
+*
+*      p_ntc
+*              [in] Pointer to a copy of the incoming trap notice attribute.
+*
+* RETURN
+*      IB_SUCCESS on good completion
+*
+* SEE ALSO
+*      Inform Record, osm_trap_rcv
+*********/
+
+END_C_DECLS
+
+#endif         /* _OSM_INFR_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lid_mgr.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lid_mgr.h
new file mode 100644 (file)
index 0000000..4a2a99a
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_lid_mgr.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_lid_mgr_t.
+ *     This object represents the LID Manager object.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_LID_MGR_H_
+#define _OSM_LID_MGR_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_db.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+#define OSM_LID_MGR_LIST_SIZE_MIN 256
+
+/****h* OpenSM/LID Manager
+* NAME
+*      LID Manager
+*
+* DESCRIPTION
+*      The LID Manager object encapsulates the information
+*      needed to control LID assignments on the subnet.
+*
+*      The LID Manager object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: LID Manager/osm_lid_mgr_t
+* NAME
+*      osm_lid_mgr_t
+*
+* DESCRIPTION
+*      LID Manager structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lid_mgr
+{
+  osm_subn_t      *p_subn;
+  osm_db_t        *p_db;
+  osm_req_t       *p_req;
+  osm_log_t       *p_log;
+  cl_plock_t      *p_lock;
+  boolean_t        send_set_reqs;
+  osm_db_domain_t *p_g2l;
+  cl_ptr_vector_t  used_lids;
+  cl_qlist_t       free_ranges;
+} osm_lid_mgr_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_db
+*              Pointer to the database (persistency) object
+*
+*      p_req
+*              Pointer to the Requester object sending SMPs.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+*      p_g2l
+*              Pointer to the database domain storing guid to lid mapping.
+*
+*      used_lids
+*              A vector the maps from the lid to its guid. keeps track of 
+*              existing and non existing mapping of guid->lid 
+* 
+*      free_ranges
+*              A list of available free lid ranges. The list is initialized 
+*              by the code that initializes the lid assignment and is consumed 
+*              by the procedure that finds a free range. It holds elements of 
+*              type osm_lid_mgr_range_t
+*
+* SEE ALSO
+*      LID Manager object
+*********/
+
+/****f* OpenSM: LID Manager/osm_lid_mgr_construct
+* NAME
+*      osm_lid_mgr_construct
+*
+* DESCRIPTION
+*      This function constructs a LID Manager object.
+*
+* SYNOPSIS
+*/
+void
+osm_lid_mgr_construct(
+       IN osm_lid_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to a LID Manager object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows osm_lid_mgr_destroy
+*
+*      Calling osm_lid_mgr_construct is a prerequisite to calling any other
+*      method except osm_lid_mgr_init.
+*
+* SEE ALSO
+*      LID Manager object, osm_lid_mgr_init,
+*      osm_lid_mgr_destroy
+*********/
+
+/****f* OpenSM: LID Manager/osm_lid_mgr_destroy
+* NAME
+*      osm_lid_mgr_destroy
+*
+* DESCRIPTION
+*      The osm_lid_mgr_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_lid_mgr_destroy(
+       IN osm_lid_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      LID Manager object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_lid_mgr_construct or osm_lid_mgr_init.
+*
+* SEE ALSO
+*      LID Manager object, osm_lid_mgr_construct,
+*      osm_lid_mgr_init
+*********/
+
+/****f* OpenSM: LID Manager/osm_lid_mgr_init
+* NAME
+*      osm_lid_mgr_init
+*
+* DESCRIPTION
+*      The osm_lid_mgr_init function initializes a
+*      LID Manager object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_lid_mgr_init(
+       IN osm_lid_mgr_t* const p_mgr,
+       IN osm_req_t* const p_req,
+       IN osm_subn_t* const p_subn,
+       IN osm_db_t* const p_db,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to an osm_lid_mgr_t object to initialize.
+*
+*      p_req
+*              [in] Pointer to the attribute Requester object.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_db
+*              [in] Pointer to the database object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the LID Manager object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other LID Manager methods.
+*
+* SEE ALSO
+*      LID Manager object, osm_lid_mgr_construct,
+*      osm_lid_mgr_destroy
+*********/
+
+/****f* OpenSM: LID Manager/osm_lid_mgr_process_sm
+* NAME
+*      osm_lid_mgr_process_sm
+*
+* DESCRIPTION
+*      Configures the SM's port with its designated LID values.
+*
+* SYNOPSIS
+*/
+osm_signal_t
+osm_lid_mgr_process_sm(
+       IN osm_lid_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to an osm_lid_mgr_t object.
+*
+* RETURN VALUES
+*      Returns the appropriate signal to the caller:
+*              OSM_SIGNAL_DONE - operation is complete
+*              OSM_SIGNAL_DONE_PENDING - local operations are complete, but
+*                      transactions are still pending on the wire.
+*
+* NOTES
+*
+* SEE ALSO
+*      LID Manager
+*********/
+       
+/****f* OpenSM: LID Manager/osm_lid_mgr_process_subnet
+* NAME
+*      osm_lid_mgr_process_subnet
+*
+* DESCRIPTION
+*      Configures subnet ports (except the SM port itself) with their
+*      designated LID values.
+*
+* SYNOPSIS
+*/
+osm_signal_t
+osm_lid_mgr_process_subnet(
+       IN osm_lid_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to an osm_lid_mgr_t object.
+*
+* RETURN VALUES
+*      Returns the appropriate signal to the caller:
+*              OSM_SIGNAL_DONE - operation is complete
+*              OSM_SIGNAL_DONE_PENDING - local operations are complete, but
+*                      transactions are still pending on the wire.
+*
+* NOTES
+*
+* SEE ALSO
+*      LID Manager
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LID_MGR_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lin_fwd_rcv.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lin_fwd_rcv.h
new file mode 100644 (file)
index 0000000..5acbc53
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_lin_fwd_rcv.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_lft_rcv_t.
+ *     This object represents the LFT Receiver object.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_LFT_RCV_H_
+#define _OSM_LFT_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/LFT Receiver
+* NAME
+*      LFT Receiver
+*
+* DESCRIPTION
+*      The LFT Receiver object encapsulates the information
+*      needed to receive the LFT attribute from a node.
+*
+*      The LFT Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: LFT Receiver/osm_lft_rcv_t
+* NAME
+*      osm_lft_rcv_t
+*
+* DESCRIPTION
+*      LFT Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lft_rcv
+{
+       osm_subn_t                                      *p_subn;
+       osm_log_t                                       *p_log;
+       cl_plock_t                                      *p_lock;
+
+} osm_lft_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+* SEE ALSO
+*      LFT Receiver object
+*********/
+
+/****f* OpenSM: LFT Receiver/osm_lft_rcv_construct
+* NAME
+*      osm_lft_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a LFT Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_lft_rcv_construct(
+       IN osm_lft_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to a LFT Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_lft_rcv_init, osm_lft_rcv_destroy
+*
+*      Calling osm_lft_rcv_construct is a prerequisite to calling any other
+*      method except osm_lft_rcv_init.
+*
+* SEE ALSO
+*      LFT Receiver object, osm_lft_rcv_init,
+*      osm_lft_rcv_destroy
+*********/
+
+/****f* OpenSM: LFT Receiver/osm_lft_rcv_destroy
+* NAME
+*      osm_lft_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_lft_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_lft_rcv_destroy(
+       IN osm_lft_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      LFT Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_lft_rcv_construct or osm_lft_rcv_init.
+*
+* SEE ALSO
+*      LFT Receiver object, osm_lft_rcv_construct,
+*      osm_lft_rcv_init
+*********/
+
+/****f* OpenSM: LFT Receiver/osm_lft_rcv_init
+* NAME
+*      osm_lft_rcv_init
+*
+* DESCRIPTION
+*      The osm_lft_rcv_init function initializes a
+*      LFT Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_lft_rcv_init(
+       IN osm_lft_rcv_t* const p_rcv,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_lft_rcv_t object to initialize.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the LFT Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other LFT Receiver methods.
+*
+* SEE ALSO
+*      LFT Receiver object, osm_lft_rcv_construct,
+*      osm_lft_rcv_destroy
+*********/
+
+/****f* OpenSM: LFT Receiver/osm_lft_rcv_process
+* NAME
+*      osm_lft_rcv_process
+*
+* DESCRIPTION
+*      Process the LFT attribute.
+*
+* SYNOPSIS
+*/
+void osm_lft_rcv_process(
+       IN const osm_lft_rcv_t* const p_rcv,
+       IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_lft_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the node's LFT attribute.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the LFT processing was successful.
+*
+* NOTES
+*      This function processes a LFT attribute.
+*
+* SEE ALSO
+*      LFT Receiver, Node Description Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LFT_RCV_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lin_fwd_rcv_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lin_fwd_rcv_ctrl.h
new file mode 100644 (file)
index 0000000..8cfa14b
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_lin_fwd_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_lft_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA
+ *  LFT attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_LFT_RCV_CTRL_H_
+#define _OSM_LFT_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_lin_fwd_rcv.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/LFT Receive Controller
+* NAME
+*      LFT Receive Controller
+*
+* DESCRIPTION
+*      The LFT Receive Controller object
+*      encapsulates the information
+*      needed to receive the NodeDescription attribute from a node.
+*
+*      The LFT Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: LFT Receive Controller/osm_lft_rcv_ctrl_t
+* NAME
+*      osm_lft_rcv_ctrl_t
+*
+* DESCRIPTION
+*      LFT Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lft_rcv_ctrl
+{
+       osm_lft_rcv_t                           *p_rcv;
+       osm_log_t                                       *p_log;
+       cl_dispatcher_t                         *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_lft_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the LFT Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      LFT Receive Controller object
+*********/
+
+/****f* OpenSM: LFT Receive Controller/osm_lft_rcv_ctrl_construct
+* NAME
+*      osm_lft_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a LFT Receive Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_lft_rcv_ctrl_construct(
+       IN osm_lft_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a LFT Receive Controller object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_lft_rcv_ctrl_init, osm_lft_rcv_ctrl_destroy
+*
+*      Calling osm_lft_rcv_ctrl_construct is a prerequisite to calling any other
+*      method except osm_lft_rcv_ctrl_init.
+*
+* SEE ALSO
+*      LFT Receive Controller object, osm_lft_rcv_ctrl_init,
+*      osm_lft_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: LFT Receive Controller/osm_lft_rcv_ctrl_destroy
+* NAME
+*      osm_lft_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_lft_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_lft_rcv_ctrl_destroy(
+       IN osm_lft_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      LFT Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_lft_rcv_ctrl_construct or osm_lft_rcv_ctrl_init.
+*
+* SEE ALSO
+*      LFT Receive Controller object, osm_lft_rcv_ctrl_construct,
+*      osm_lft_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: LFT Receive Controller/osm_lft_rcv_ctrl_init
+* NAME
+*      osm_lft_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_lft_rcv_ctrl_init function initializes a
+*      LFT Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_lft_rcv_ctrl_init(
+       IN osm_lft_rcv_ctrl_t* const p_ctrl,
+       IN osm_lft_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_lft_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_lft_rcv_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the LFT Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other LFT Receive Controller methods.
+*
+* SEE ALSO
+*      LFT Receive Controller object, osm_lft_rcv_ctrl_construct,
+*      osm_lft_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif         /* OSM_LFT_RCV_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lin_fwd_tbl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_lin_fwd_tbl.h
new file mode 100644 (file)
index 0000000..5d77824
--- /dev/null
@@ -0,0 +1,379 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_lin_fwd_tbl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_lin_fwd_tbl_t.
+ *     This object represents a linear forwarding table.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_LIN_FWD_TBL_H_
+#define _OSM_LIN_FWD_TBL_H_
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Linear Forwarding Table
+* NAME
+*      Linear Forwarding Table
+*
+* DESCRIPTION
+*      The Linear Forwarding Table objects encapsulate the information
+*      needed by the OpenSM to manage linear forwarding tables.  The OpenSM
+*      allocates one Linear Forwarding Table object per switch in the
+*      IBA subnet, if that switch uses a linear table.
+*
+*      The Linear Forwarding Table objects are not thread safe, thus
+*      callers must provide serialization.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Forwarding Table/osm_lin_fwd_tbl_t
+* NAME
+*      osm_lin_fwd_tbl_t
+*
+* DESCRIPTION
+*      Linear Forwarding Table structure.
+*
+*      Callers may directly access this object.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lin_fwd_tbl
+{
+       uint16_t                                size;
+       uint8_t                                 port_tbl[1];
+
+} osm_lin_fwd_tbl_t;
+/*
+* FIELDS
+*      Size
+*              Number of entries in the linear forwarding table.  This value
+*              is taken from the SwitchInfo attribute.
+*
+*      port_tbl
+*              The array that specifies the port number which routes the
+*              corresponding LID.  Index is by LID.
+*
+* SEE ALSO
+*      Forwarding Table object, Random Forwarding Table object.
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_lin_tbl_new
+* NAME
+*      osm_lin_tbl_new
+*
+* DESCRIPTION
+*      This function creates and initializes a Linear Forwarding Table object.
+*
+* SYNOPSIS
+*/
+osm_lin_fwd_tbl_t*
+osm_lin_tbl_new(
+       IN uint16_t const size );
+/*
+* PARAMETERS
+*      size
+*              [in] Number of entries in the Linear Forwarding Table.
+*
+* RETURN VALUE
+*      On success, returns a pointer to a new Linear Forwarding Table object
+*      of the specified size.
+*      NULL otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_lin_tbl_delete
+* NAME
+*      osm_lin_tbl_delete
+*
+* DESCRIPTION
+*      This destroys and deallocates a Linear Forwarding Table object.
+*
+* SYNOPSIS
+*/
+void
+osm_lin_tbl_delete(
+       IN osm_lin_fwd_tbl_t** const pp_tbl );
+/*
+* PARAMETERS
+*      pp_tbl
+*              [in] Pointer a Pointer to the Linear Forwarding Table object.
+*
+* RETURN VALUE
+*      On success, returns a pointer to a new Linear Forwarding Table object
+*      of the specified size.
+*      NULL otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_set
+* NAME
+*      osm_lin_fwd_tbl_set
+*
+* DESCRIPTION
+*      Sets the port to route the specified LID.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_lin_fwd_tbl_set(
+       IN osm_lin_fwd_tbl_t* const p_tbl,
+       IN const uint16_t lid_ho,
+       IN const uint8_t port )
+{
+       CL_ASSERT( lid_ho < p_tbl->size );
+       if( lid_ho < p_tbl->size )
+               p_tbl->port_tbl[lid_ho] = port;
+}
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Linear Forwarding Table object.
+*
+*      lid_ho
+*              [in] LID value (host order) for which to set the route.
+*
+*      port
+*              [in] Port to route the specified LID value.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_get
+* NAME
+*      osm_lin_fwd_tbl_get
+*
+* DESCRIPTION
+*      Returns the port that routes the specified LID.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_lin_fwd_tbl_get(
+       IN const osm_lin_fwd_tbl_t* const p_tbl,
+       IN const uint16_t lid_ho )
+{
+       if( lid_ho < p_tbl->size )
+               return( p_tbl->port_tbl[lid_ho] );
+       else
+               return( 0xFF );
+}
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Linear Forwarding Table object.
+*
+*      lid_ho
+*              [in] LID value (host order) for which to get the route.
+*
+* RETURN VALUE
+*      Returns the port that routes the specified LID.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_get_size
+* NAME
+*      osm_lin_fwd_tbl_get_size
+*
+* DESCRIPTION
+*      Returns the number of entries available in the forwarding table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_lin_fwd_tbl_get_size(
+       IN const osm_lin_fwd_tbl_t* const p_tbl )
+{
+       return( p_tbl->size );
+}
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+*      Returns the number of entries available in the forwarding table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_get_lids_per_block
+* NAME
+*      osm_lin_fwd_tbl_get_lids_per_block
+*
+* DESCRIPTION
+*      Returns the number of LIDs per LID block.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_lin_fwd_tbl_get_lids_per_block(
+       IN const osm_lin_fwd_tbl_t* const p_tbl )
+{
+       UNUSED_PARAM( p_tbl );
+       return( 64 );
+}
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+*      Returns the number of LIDs per LID block.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_get_max_block_id_in_use
+* NAME
+*      osm_lin_fwd_tbl_get_max_block_id_in_use
+*
+* DESCRIPTION
+*      Returns the maximum block ID in actual use by the forwarding table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_lin_fwd_tbl_get_max_block_id_in_use(
+       IN const osm_lin_fwd_tbl_t* const p_tbl,
+       IN const uint16_t lid_top_ho )
+{
+       return( (uint16_t)(lid_top_ho /
+                       osm_lin_fwd_tbl_get_lids_per_block( p_tbl ) ) );
+}
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+*      Returns the maximum block ID in actual use by the forwarding table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_set_block
+* NAME
+*      osm_lin_fwd_tbl_set_block
+*
+* DESCRIPTION
+*      Copies the specified block into the Linear Forwarding Table.
+*
+* SYNOPSIS
+*/
+static inline ib_api_status_t
+osm_lin_fwd_tbl_set_block(
+       IN osm_lin_fwd_tbl_t* const p_tbl,
+       IN const uint8_t* const p_block,
+       IN const uint32_t block_num )
+{
+       uint16_t lid_start;
+       uint16_t num_lids;
+
+       CL_ASSERT( p_tbl );
+       CL_ASSERT( p_block );
+
+       num_lids = osm_lin_fwd_tbl_get_lids_per_block( p_tbl );
+       lid_start = (uint16_t)(block_num * num_lids);
+
+       if( lid_start + num_lids > p_tbl->size )
+               return( IB_INVALID_PARAMETER );
+
+       memcpy( &p_tbl->port_tbl[lid_start], p_block, num_lids );
+       return( IB_SUCCESS );
+}
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Linear Forwarding Table object.
+*
+*      p_block
+*              [in] Pointer to the Forwarding Table block.
+*
+*      block_num
+*              [in] Block number of this block.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif         /* _OSM_LIN_FWD_TBL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_link_mgr.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_link_mgr.h
new file mode 100644 (file)
index 0000000..26c1657
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_link_mgr.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_link_mgr_t.
+ *     This object represents the Link Manager object.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_LINK_MGR_H_
+#define _OSM_LINK_MGR_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Link Manager
+* NAME
+*      Link Manager
+*
+* DESCRIPTION
+*      The Link Manager object encapsulates the information
+*      needed to control unicast LID forwarding on the subnet.
+*
+*      The Link Manager object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Link Manager/osm_link_mgr_t
+* NAME
+*      osm_link_mgr_t
+*
+* DESCRIPTION
+*      Link Manager structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_link_mgr
+{
+       osm_subn_t                                      *p_subn;
+       osm_req_t                                       *p_req;
+       osm_log_t                                       *p_log;
+       cl_plock_t                                      *p_lock;
+   boolean_t               send_set_reqs;
+
+} osm_link_mgr_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_req
+*              Pointer to the Requester object sending SMPs.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+* SEE ALSO
+*      Link Manager object
+*********/
+
+/****f* OpenSM: Link Manager/osm_link_mgr_construct
+* NAME
+*      osm_link_mgr_construct
+*
+* DESCRIPTION
+*      This function constructs a Link Manager object.
+*
+* SYNOPSIS
+*/
+void
+osm_link_mgr_construct(
+       IN osm_link_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to a Link Manager object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows osm_link_mgr_destroy
+*
+*      Calling osm_link_mgr_construct is a prerequisite to calling any other
+*      method except osm_link_mgr_init.
+*
+* SEE ALSO
+*      Link Manager object, osm_link_mgr_init,
+*      osm_link_mgr_destroy
+*********/
+
+/****f* OpenSM: Link Manager/osm_link_mgr_destroy
+* NAME
+*      osm_link_mgr_destroy
+*
+* DESCRIPTION
+*      The osm_link_mgr_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_link_mgr_destroy(
+       IN osm_link_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Link Manager object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_link_mgr_construct or osm_link_mgr_init.
+*
+* SEE ALSO
+*      Link Manager object, osm_link_mgr_construct,
+*      osm_link_mgr_init
+*********/
+
+/****f* OpenSM: Link Manager/osm_link_mgr_init
+* NAME
+*      osm_link_mgr_init
+*
+* DESCRIPTION
+*      The osm_link_mgr_init function initializes a
+*      Link Manager object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_link_mgr_init(
+       IN osm_link_mgr_t* const p_mgr,
+       IN osm_req_t* const p_req,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to an osm_link_mgr_t object to initialize.
+*
+*      p_req
+*              [in] Pointer to the attribute Requester object.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the Link Manager object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Link Manager methods.
+*
+* SEE ALSO
+*      Link Manager object, osm_link_mgr_construct,
+*      osm_link_mgr_destroy
+*********/
+
+/****f* OpenSM: Link Manager/osm_link_mgr_process
+* NAME
+*      osm_link_mgr_process
+*
+* DESCRIPTION
+*      Processes all ports in the subnet per the link manager command.
+*
+* SYNOPSIS
+*/
+osm_signal_t
+osm_link_mgr_process(
+       IN osm_link_mgr_t* const p_mgr,
+       IN const uint8_t link_state );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to an osm_link_mgr_t object.
+*
+*      link_state
+*              [in] state to which to the set the port.
+*
+*
+* RETURN VALUES
+*      Returns the appropriate signal to the caller:
+*              OSM_SIGNAL_DONE - operation is complete
+*              OSM_SIGNAL_DONE_PENDING - local operations are complete, but
+*                      transactions are still pending on the wire.
+*
+* NOTES
+*
+* SEE ALSO
+*      Link Manager, Node Info Response Controller
+*********/
+       
+END_C_DECLS
+
+#endif /* _OSM_LINK_MGR_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_log.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_log.h
new file mode 100644 (file)
index 0000000..e8abd3e
--- /dev/null
@@ -0,0 +1,474 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_log.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_log_t.
+ *     This object represents the log file.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#ifndef _OSM_LOG_H_
+#define _OSM_LOG_H_
+
+#ifndef __WIN__
+#include <syslog.h>
+#endif
+#include <complib/cl_log.h>
+#include <complib/cl_spinlock.h>
+#include <opensm/osm_base.h>
+#include <iba/ib_types.h>
+#include <stdio.h>
+
+#ifdef __GNUC__
+#define STRICT_OSM_LOG_FORMAT __attribute__((format(printf, 3, 4)))
+#else
+#define STRICT_OSM_LOG_FORMAT
+#endif
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+#define LOG_ENTRY_SIZE_MAX             4096
+#define BUF_SIZE                       LOG_ENTRY_SIZE_MAX
+
+#define __func__ __FUNCTION__
+
+#define OSM_LOG_ENTER( OSM_LOG_PTR, NAME ) \
+       osm_log( OSM_LOG_PTR, OSM_LOG_FUNCS, \
+                "%s: [\n", __func__);
+
+#define OSM_LOG_EXIT( OSM_LOG_PTR ) \
+       osm_log( OSM_LOG_PTR, OSM_LOG_FUNCS, \
+                "%s: ]\n", __func__);
+
+/****h* OpenSM/Log
+* NAME
+*      Log
+*
+* DESCRIPTION
+*
+* AUTHOR
+*
+*********/
+typedef uint8_t osm_log_level_t;
+
+#define OSM_LOG_NONE                   0x00
+#define OSM_LOG_ERROR                  0x01
+#define OSM_LOG_INFO                   0x02
+#define OSM_LOG_VERBOSE                        0x04
+#define OSM_LOG_DEBUG                  0x08
+#define OSM_LOG_FUNCS                  0x10
+#define OSM_LOG_FRAMES                 0x20
+#define OSM_LOG_ROUTING                        0x40
+#define OSM_LOG_SYS                    0x80
+
+/*
+       DEFAULT - turn on ERROR and INFO only
+*/
+#define OSM_LOG_DEFAULT_LEVEL          OSM_LOG_ERROR | OSM_LOG_INFO
+
+/****s* OpenSM: MAD Wrapper/osm_log_t
+* NAME
+*      osm_log_t
+*
+* DESCRIPTION
+*
+* SYNOPSIS
+*/
+typedef struct _osm_log
+{
+       osm_log_level_t                 level;
+       cl_spinlock_t                   lock;
+       unsigned long                   count;
+       unsigned long                   max_size;
+       boolean_t                       flush;
+       FILE*                           out_port;
+} osm_log_t;
+/*********/
+
+/****f* OpenSM: Log/osm_log_construct
+* NAME
+*      osm_log_construct
+*
+* DESCRIPTION
+*      This function constructs a Log object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_log_construct(
+       IN osm_log_t* const p_log )
+{
+       cl_spinlock_construct( &p_log->lock );
+}
+/*
+* PARAMETERS
+*      p_log
+*              [in] Pointer to a Log object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_log_init, osm_log_init_v2, osm_log_destroy
+*
+*      Calling osm_log_construct is a prerequisite to calling any other
+*      method except osm_log_init or osm_log_init_v2.
+*
+* SEE ALSO
+*      Log object, osm_log_init, osm_log_init_v2,
+*      osm_log_destroy
+*********/
+
+/****f* OpenSM: Log/osm_log_destroy
+* NAME
+*      osm_log_destroy
+*
+* DESCRIPTION
+*      The osm_log_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_log_destroy(
+       IN osm_log_t* const p_log )
+{
+       cl_spinlock_destroy( &p_log->lock );
+       if (p_log->out_port != stdout) {
+         fclose(p_log->out_port);
+         p_log->out_port = stdout;
+       }
+       closelog();
+}
+/*
+* PARAMETERS
+*      p_log
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Log object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_log_construct, osm_log_init, or osm_log_init_v2.
+*
+* SEE ALSO
+*      Log object, osm_log_construct,
+*      osm_log_init, osm_log_init_v2
+*********/
+
+/****f* OpenSM: Log/osm_log_init_v2
+* NAME
+*      osm_log_init_v2
+*
+* DESCRIPTION
+*      The osm_log_init_v2 function initializes a
+*      Log object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_log_init_v2(
+  IN osm_log_t* const p_log,
+  IN const boolean_t flush,
+  IN const uint8_t log_flags,
+  IN const char *log_file,
+  IN const unsigned long max_size,
+  IN const boolean_t accum_log_file );
+/*
+* PARAMETERS
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      flush
+*              [in] Set to TRUE directs the log to flush all log messages
+*              immediately.  This severely degrades log performance,
+*              and is normally used for debugging only.
+*
+*  log_flags
+*     [in] The log verbosity level to be used.
+*
+*  log_file
+*     [in] if not NULL defines the name of the log file. Otherwise it is stdout.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Log object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Log methods.
+*
+* SEE ALSO
+*      Log object, osm_log_construct,
+*      osm_log_destroy
+*********/
+
+/****f* OpenSM: Log/osm_log_init
+* NAME
+*      osm_log_init
+*
+* DESCRIPTION
+*      The osm_log_init function initializes a
+*      Log object for use. It is a wrapper for osm_log_init_v2().
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_log_init(
+  IN osm_log_t* const p_log,
+  IN const boolean_t flush,
+  IN const uint8_t log_flags,
+  IN const char *log_file,
+  IN const boolean_t accum_log_file );
+/*
+ * Same as osm_log_init_v2() but without max_size parameter
+ */
+
+/****f* OpenSM: Log/osm_log_get_level
+* NAME
+*      osm_log_get_level
+*
+* DESCRIPTION
+*      Returns the current log level.
+*
+* SYNOPSIS
+*/
+static inline osm_log_level_t
+osm_log_get_level(
+       IN const osm_log_t* const p_log )
+{
+       return( p_log->level );
+}
+/*
+* PARAMETERS
+*      p_log
+*              [in] Pointer to the log object.
+*
+* RETURN VALUES
+*      Returns the current log level.
+*
+* NOTES
+*
+* SEE ALSO
+*      Log object, osm_log_construct,
+*      osm_log_destroy
+*********/
+
+/****f* OpenSM: Log/osm_log_set_level
+* NAME
+*      osm_log_set_level
+*
+* DESCRIPTION
+*      Sets the current log level.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_log_set_level(
+       IN osm_log_t* const p_log,
+       IN const osm_log_level_t level )
+{
+       p_log->level = level;
+}
+/*
+* PARAMETERS
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      level
+*              [in] New level to set.
+*
+* RETURN VALUES
+*      Returns the current log level.
+*
+* NOTES
+*
+* SEE ALSO
+*      Log object, osm_log_construct,
+*      osm_log_destroy
+*********/
+
+/****f* OpenSM: Log/osm_log_is_active
+* NAME
+*      osm_log_is_active
+*
+* DESCRIPTION
+*      Returns TRUE if the specified log level would be logged.
+*      FALSE otherwise.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_log_is_active(
+       IN const osm_log_t* const p_log,
+       IN const osm_log_level_t level )
+{
+       return( (p_log->level & level) != 0 );
+}
+/*
+* PARAMETERS
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      level
+*              [in] Level to check.
+*
+* RETURN VALUES
+*      Returns TRUE if the specified log level would be logged.
+*      FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*      Log object, osm_log_construct,
+*      osm_log_destroy
+*********/
+
+extern int osm_log_printf(osm_log_t *p_log, osm_log_level_t level,
+                         const char *fmt, ...);
+
+void
+osm_log(
+       IN osm_log_t* const p_log,
+       IN const osm_log_level_t verbosity,
+       IN const char *p_str, ... ) STRICT_OSM_LOG_FORMAT;
+
+void
+osm_log_raw(
+       IN osm_log_t* const p_log,
+       IN const osm_log_level_t verbosity,
+       IN const char *p_buf );
+
+#define DBG_CL_LOCK 0
+
+#define CL_PLOCK_EXCL_ACQUIRE( __exp__ )  \
+{                                                                                                      \
+   if (DBG_CL_LOCK)                      \
+     printf("cl_plock_excl_acquire: Acquiring %p file %s, line %d\n", \
+          __exp__,__FILE__, __LINE__);            \
+   cl_plock_excl_acquire( __exp__ );      \
+   if (DBG_CL_LOCK)                      \
+     printf("cl_plock_excl_acquire: Acquired %p file %s, line %d\n", \
+          __exp__,__FILE__, __LINE__);            \
+}
+
+#define CL_PLOCK_ACQUIRE( __exp__ )  \
+{                                                                                                      \
+   if (DBG_CL_LOCK)                      \
+     printf("cl_plock_acquire: Acquiring %p file %s, line %d\n", \
+          __exp__,__FILE__, __LINE__);            \
+   cl_plock_acquire( __exp__ );      \
+   if (DBG_CL_LOCK)                      \
+     printf("cl_plock_acquire: Acquired %p file %s, line %d\n", \
+          __exp__,__FILE__, __LINE__);            \
+}
+
+#define CL_PLOCK_RELEASE( __exp__ )  \
+{                                                                                                      \
+   if (DBG_CL_LOCK)                      \
+     printf("cl_plock_release: Releasing %p file %s, line %d\n", \
+          __exp__,__FILE__, __LINE__);            \
+   cl_plock_release( __exp__ );      \
+   if (DBG_CL_LOCK)                      \
+     printf("cl_plock_release: Released  %p file %s, line %d\n", \
+          __exp__,__FILE__, __LINE__);            \
+}
+
+#define DBG_CL_SPINLOCK 0
+#define CL_SPINLOCK_RELEASE( __exp__ )  \
+{                                                                                                      \
+   if (DBG_CL_SPINLOCK)                      \
+     printf("cl_spinlock_release: Releasing %p file %s, line %d\n", \
+          __exp__,__FILE__, __LINE__);            \
+   cl_spinlock_release( __exp__ );      \
+   if (DBG_CL_SPINLOCK)                      \
+     printf("cl_spinlock_release: Released  %p file %s, line %d\n", \
+          __exp__,__FILE__, __LINE__);            \
+}
+
+#define CL_SPINLOCK_ACQUIRE( __exp__ )  \
+{                                                                                                      \
+   if (DBG_CL_SPINLOCK)                      \
+     printf("cl_spinlock_acquire: Acquiring %p file %s, line %d\n", \
+          __exp__,__FILE__, __LINE__);            \
+   cl_spinlock_acquire( __exp__ );      \
+   if (DBG_CL_SPINLOCK)                      \
+     printf("cl_spinlock_acquire: Acquired %p file %s, line %d\n", \
+          __exp__,__FILE__, __LINE__);            \
+}
+
+/****f* OpenSM: Helper/osm_is_debug
+* NAME
+*      osm_is_debug
+*
+* DESCRIPTION
+*      The osm_is_debug function returns TRUE if the opensm was compiled
+*  in debug mode, and FALSE otherwise.
+*
+* SYNOPSIS
+*/
+boolean_t
+osm_is_debug(void);
+/*
+* PARAMETERS
+*    None
+*
+* RETURN VALUE
+*        TRUE if compiled in debug version. FALSE otherwise.
+*
+* NOTES
+*
+*********/
+
+END_C_DECLS
+
+#endif         /* _OSM_LOG_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mad_pool.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mad_pool.h
new file mode 100644 (file)
index 0000000..e3c0993
--- /dev/null
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_mad_pool.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_mad_pool_t.
+ *     This object represents a pool of management datagram (MAD) objects.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#ifndef _OSM_MAD_POOL_H_
+#define _OSM_MAD_POOL_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_atomic.h>
+#include <complib/cl_qlockpool.h>
+#include <opensm/osm_base.h>
+#include <vendor/osm_vendor.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/MAD Pool
+* NAME
+*      MAD Pool
+*
+* DESCRIPTION
+*      The MAD Pool encapsulates the information needed by the
+*      OpenSM to manage a pool of MAD objects.  The OpenSM allocates
+*      one MAD Pool per IBA subnet.
+*
+*      The MAD Pool is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: MAD Pool/osm_mad_pool_t
+* NAME
+*      osm_mad_pool_t
+*
+* DESCRIPTION
+*      MAD Pool structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mad_pool
+{
+       osm_log_t                                       *p_log;
+       cl_qlock_pool_t                         madw_pool;
+       atomic32_t                                      mads_out;
+} osm_mad_pool_t;
+/*
+* FIELDS
+*      p_log
+*              Pointer to the log object.
+*
+*      lock
+*              Spinlock guarding the pool.
+*
+*      mads_out
+*              Running total of the number of MADs outstanding.
+*
+* SEE ALSO
+*      MAD Pool
+*********/
+
+/****f* OpenSM: MAD Pool/osm_mad_pool_construct
+* NAME
+*      osm_mad_pool_construct
+*
+* DESCRIPTION
+*      This function constructs a MAD Pool.
+*
+* SYNOPSIS
+*/
+void osm_mad_pool_construct(
+       IN osm_mad_pool_t* const p_pool );
+/*
+* PARAMETERS
+*      p_pool
+*              [in] Pointer to a MAD Pool to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_mad_pool_init, osm_mad_pool_destroy
+*
+*      Calling osm_mad_pool_construct is a prerequisite to calling any other
+*      method except osm_mad_pool_init.
+*
+* SEE ALSO
+*      MAD Pool, osm_mad_pool_init, osm_mad_pool_destroy
+*********/
+
+/****f* OpenSM: MAD Pool/osm_mad_pool_destroy
+* NAME
+*      osm_mad_pool_destroy
+*
+* DESCRIPTION
+*      The osm_mad_pool_destroy function destroys a node, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_mad_pool_destroy(
+       IN osm_mad_pool_t* const p_pool );
+/*
+* PARAMETERS
+*      p_pool
+*              [in] Pointer to a MAD Pool to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified MAD Pool.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to osm_mad_pool_construct or
+*      osm_mad_pool_init.
+*
+* SEE ALSO
+*      MAD Pool, osm_mad_pool_construct, osm_mad_pool_init
+*********/
+
+/****f* OpenSM: MAD Pool/osm_mad_pool_init
+* NAME
+*      osm_mad_pool_init
+*
+* DESCRIPTION
+*      The osm_mad_pool_init function initializes a MAD Pool for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_mad_pool_init(
+       IN osm_mad_pool_t* const p_pool,
+       IN osm_log_t* const p_log );
+/*
+* PARAMETERS
+*      p_pool
+*              [in] Pointer to an osm_mad_pool_t object to initialize.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*
+* RETURN VALUES
+*      CL_SUCCESS if the MAD Pool was initialized successfully.
+*
+* NOTES
+*      Allows calling other MAD Pool methods.
+*
+* SEE ALSO
+*      MAD Pool, osm_mad_pool_construct, osm_mad_pool_destroy
+*********/
+
+/****f* OpenSM: MAD Pool/osm_mad_pool_get
+* NAME
+*      osm_mad_pool_get
+*
+* DESCRIPTION
+*      Gets a MAD wrapper and wire MAD from the pool.
+*
+* SYNOPSIS
+*/
+osm_madw_t*
+osm_mad_pool_get(
+       IN osm_mad_pool_t* const p_pool,
+       IN osm_bind_handle_t h_bind,
+       IN const uint32_t total_size,
+       IN const osm_mad_addr_t* const p_mad_addr );
+/*
+* PARAMETERS
+*      p_pool
+*              [in] Pointer to an osm_mad_pool_t object.
+*
+*      h_bind
+*              [in] Handle returned from osm_vendor_bind() call to the
+*              port over which this mad will be sent.
+*
+*      total_size
+*              [in] Total size, including MAD header of the requested MAD.
+*
+*      p_mad_addr
+*              [in] Pointer to the MAD address structure.  This parameter
+*              may be NULL for directed route MADs.
+*
+* RETURN VALUES
+*      Returns a pointer to a MAD wrapper containing the MAD.
+*      A return value of NULL means no MADs are available.
+*
+* NOTES
+*      The MAD must eventually be returned to the pool with a call to
+*      osm_mad_pool_put.
+*
+*      The osm_mad_pool_construct or osm_mad_pool_init must be called before
+*      using this function.
+*
+* SEE ALSO
+*      MAD Pool, osm_mad_pool_put
+*********/
+
+/****f* OpenSM: MAD Pool/osm_mad_pool_put
+* NAME
+*      osm_mad_pool_put
+*
+* DESCRIPTION
+*      Returns a MAD to the pool.
+*
+* SYNOPSIS
+*/
+void osm_mad_pool_put(
+       IN osm_mad_pool_t* const p_pool,
+       IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_pool
+*              [in] Pointer to an osm_mad_pool_t object.
+*
+*      p_madw
+*              [in] Pointer to a MAD Wrapper for a MAD that was previously
+*              retrieved from the pool.
+*
+* RETURN VALUES
+*      This function does not return a value.
+*
+* NOTES
+*      The osm_mad_pool_construct or osm_mad_pool_init must be called before
+*      using this function.
+*
+* SEE ALSO
+*      MAD Pool, osm_mad_pool_get
+*********/
+
+/****f* OpenSM: MAD Pool/osm_mad_pool_get_wrapper
+* NAME
+*      osm_mad_pool_get_wrapper
+*
+* DESCRIPTION
+*      Gets a only MAD wrapper from the pool (no wire MAD).
+*
+* SYNOPSIS
+*/
+osm_madw_t*
+osm_mad_pool_get_wrapper(
+       IN osm_mad_pool_t* const p_pool,
+       IN osm_bind_handle_t h_bind,
+       IN const uint32_t total_size,
+       IN const ib_mad_t* const p_mad,
+       IN const osm_mad_addr_t* const p_mad_addr );
+/*
+* PARAMETERS
+*      p_pool
+*              [in] Pointer to an osm_mad_pool_t object.
+*
+*      h_bind
+*              [in] Handle returned from osm_vendor_bind() call to the
+*              port for which this mad wrapper will be used.
+*
+*      total_size
+*              [in] Total size, including MAD header of the MAD that will
+*              be attached to this wrapper.
+*
+*      p_mad
+*              [in] Pointer to the MAD to attach to this wrapper.
+*
+*      p_mad_addr
+*              [in] Pointer to the MAD address structure.  This parameter
+*              may be NULL for directed route MADs.
+*
+* RETURN VALUES
+*      Returns a pointer to a MAD wrapper.
+*      A return value of NULL means no MAD wrappers are available.
+*
+* NOTES
+*      The MAD must eventually be returned to the pool with a call to
+*      osm_mad_pool_put.
+*
+*      The osm_mad_pool_construct or osm_mad_pool_init must be called before
+*      using this function.
+*
+* SEE ALSO
+*      MAD Pool, osm_mad_pool_put
+*********/
+
+/****f* OpenSM: MAD Pool/osm_mad_pool_get_wrapper_raw
+* NAME
+*      osm_mad_pool_get_wrapper_raw
+*
+* DESCRIPTION
+*      Gets a only an uninitialized MAD wrapper from the pool (no wire MAD).
+*
+* SYNOPSIS
+*/
+osm_madw_t*
+osm_mad_pool_get_wrapper_raw(
+       IN osm_mad_pool_t* const p_pool );
+/*
+* PARAMETERS
+*      p_pool
+*              [in] Pointer to an osm_mad_pool_t object.
+*
+* RETURN VALUES
+*      Returns a pointer to a MAD wrapper.
+*      A return value of NULL means no MAD wrappers are available.
+*
+* NOTES
+*      The MAD must eventually be returned to the pool with a call to
+*      osm_mad_pool_put.
+*
+*      The osm_mad_pool_construct or osm_mad_pool_init must be called before
+*      using this function.
+*
+* SEE ALSO
+*      MAD Pool, osm_mad_pool_put
+*********/
+
+/****f* OpenSM: MAD Pool/osm_mad_pool_get_outstanding
+* NAME
+*      osm_mad_pool_get_count
+*
+* DESCRIPTION
+*      Returns the running count of MADs currently outstanding from the pool.
+*
+* SYNOPSIS
+*/
+static inline uint32_t
+osm_mad_pool_get_outstanding(
+       IN const osm_mad_pool_t* const p_pool )
+{
+       return( p_pool->mads_out );
+}
+/*
+* PARAMETERS
+*      p_pool
+*              [in] Pointer to an osm_mad_pool_t object.
+*
+* RETURN VALUES
+*      Returns the running count of MADs currently outstanding from the pool.
+*
+* NOTES
+*      The osm_mad_pool_construct or osm_mad_pool_init must be called before
+*      using this function.
+*
+* SEE ALSO
+*      MAD Pool, osm_mad_pool_get
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MAD_POOL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_madw.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_madw.h
new file mode 100644 (file)
index 0000000..dfd6f91
--- /dev/null
@@ -0,0 +1,1160 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_madw.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_mad_wrapper_t.
+ *     This object represents the context wrapper for OpenSM MAD processing.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#ifndef _OSM_MADW_H_
+#define _OSM_MADW_H_
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <vendor/osm_vendor.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****s* OpenSM: MAD Wrapper/osm_bind_info_t
+* NAME
+*   osm_bind_info_t
+*
+* DESCRIPTION
+*
+* SYNOPSIS
+*/
+typedef struct _osm_bind_info
+{
+    ib_net64_t         port_guid;
+    uint8_t            mad_class;
+    uint8_t            class_version;
+    boolean_t          is_responder;
+    boolean_t          is_trap_processor;
+    boolean_t          is_report_processor;
+    uint32_t           send_q_size;
+    uint32_t           recv_q_size;
+} osm_bind_info_t;
+/*
+* FIELDS
+*      portguid
+*              PortGuid of local port 
+*
+*      class
+*              Mgmt Class ID 
+*
+*      class_version
+*              Mgmt Class version
+*
+*      is_responder
+*              True if this is a GSI Agent
+*
+*      is_trap_processor
+*              True if GSI Trap msgs are handled
+*      
+*      is_report_processo
+*              True if GSI Report msgs are handled
+*
+*      send_q_size
+*              SendQueueSize
+*
+*      recv_q_size
+*              Receive Queue Size
+* 
+* SEE ALSO
+*********/
+
+/****h* OpenSM/MAD Wrapper
+* NAME
+*      MAD Wrapper
+*
+* DESCRIPTION
+*      The MAD Wrapper object encapsulates the information needed by the
+*      OpenSM to manage individual MADs.  The OpenSM allocates one MAD Wrapper
+*      per MAD.
+*
+*      The MAD Wrapper is not thread safe, thus callers must provide
+*      serialization.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: MAD Wrapper/osm_ni_context_t
+* NAME
+*      osm_ni_context_t
+*
+* DESCRIPTION
+*      Context needed by recipient of NodeInfo attribute.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_ni_context
+{
+  ib_net64_t                   node_guid;
+  uint8_t                      port_num;
+} osm_ni_context_t;
+/*
+* FIELDS
+*      p_node
+*              Pointer to the node thru which we got to this node.
+*
+*      p_sw
+*              Pointer to the switch object (if any) of the switch
+*              thru which we got to this node.
+*
+*      port_num
+*              Port number on the node or switch thru which we got
+*              to this node.
+* 
+* SEE ALSO
+*********/
+
+/****s* OpenSM: MAD Wrapper/osm_pi_context_t
+* NAME
+*      osm_pi_context_t
+*
+* DESCRIPTION
+*      Context needed by recipient of PortInfo attribute.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pi_context
+{
+  ib_net64_t                   node_guid;
+  ib_net64_t                   port_guid;
+  boolean_t                    set_method;
+  boolean_t                    light_sweep;
+  boolean_t                    update_master_sm_base_lid;
+  boolean_t                    ignore_errors;
+  boolean_t                    active_transition;
+} osm_pi_context_t;
+/*********/
+
+/****s* OpenSM: MAD Wrapper/osm_nd_context_t
+* NAME
+*      osm_nd_context_t
+*
+* DESCRIPTION
+*      Context needed by recipient of NodeDescription attribute.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_nd_context
+{
+       ib_net64_t                      node_guid;
+} osm_nd_context_t;
+/*********/
+
+/****s* OpenSM: MAD Wrapper/osm_si_context_t
+* NAME
+*      osm_si_context_t
+*
+* DESCRIPTION
+*      Context needed by recipient of SwitchInfo attribute.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_si_context
+{
+       ib_net64_t                      node_guid;
+       boolean_t                       set_method;
+       boolean_t                       light_sweep;
+} osm_si_context_t;
+/*********/
+
+/****s* OpenSM: MAD Wrapper/osm_lft_context_t
+* NAME
+*      osm_lft_context_t
+*
+* DESCRIPTION
+*      Context needed by recipient of LinearForwardingTable attribute.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lft_context
+{
+       ib_net64_t                      node_guid;
+       boolean_t                       set_method;
+} osm_lft_context_t;
+/*********/
+
+/****s* OpenSM: MAD Wrapper/osm_mft_context_t
+* NAME
+*      osm_mft_context_t
+*
+* DESCRIPTION
+*      Context needed by recipient of MulticastForwardingTable attribute.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mft_context
+{
+       ib_net64_t                      node_guid;
+       boolean_t                       set_method;
+} osm_mft_context_t;
+/*********/
+
+/****s* OpenSM: MAD Wrapper/osm_smi_context_t
+* NAME
+*      osm_smi_context_t
+*
+* DESCRIPTION
+*      Context needed by recipient of SMInfo attribute.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_smi_context
+{
+  ib_net64_t           port_guid;
+  boolean_t            set_method;
+} osm_smi_context_t;
+/*********/
+
+/****s* OpenSM: MAD Wrapper/osm_pkey_context_t
+* NAME
+*      osm_pkey_context_t
+*
+* DESCRIPTION
+*      Context needed by recipient of P_Key attribute.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pkey_context
+{
+  ib_net64_t                   node_guid;
+  ib_net64_t                   port_guid;
+  boolean_t                    set_method;
+} osm_pkey_context_t;
+/*********/
+
+/****s* OpenSM: MAD Wrapper/osm_slvl_context_t
+* NAME
+*      osm_slvl_context_t
+*
+* DESCRIPTION
+*      Context needed by recipient of PortInfo attribute.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_slvl_context
+{
+  ib_net64_t                   node_guid;
+  ib_net64_t                   port_guid;
+  boolean_t                    set_method;
+} osm_slvl_context_t;
+/*********/
+
+/****s* OpenSM: MAD Wrapper/osm_vla_context_t
+* NAME
+*      osm_vla_context_t
+*
+* DESCRIPTION
+*      Context needed by recipient of VL Arb attribute.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_vla_context
+{
+  ib_net64_t                   node_guid;
+  ib_net64_t                   port_guid;
+  boolean_t                    set_method;
+} osm_vla_context_t;
+/*********/
+
+#ifndef OSM_VENDOR_INTF_OPENIB
+/****s* OpenSM: MAD Wrapper/osm_arbitrary_context_t
+* NAME
+*      osm_arbitrary_context_t
+*
+* DESCRIPTION
+*      Context needed by arbitrary recipient.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_arbitrary_context
+{
+  void*             context1;
+  void*             context2;
+} osm_arbitrary_context_t;
+/*********/
+#endif
+
+/****s* OpenSM: MAD Wrapper/osm_madw_context_t
+* NAME
+*      osm_madw_context_t
+*
+* DESCRIPTION
+*      Context needed by recipients of MAD responses.
+*
+* SYNOPSIS
+*/
+typedef union _osm_madw_context
+{
+       osm_ni_context_t        ni_context;
+       osm_pi_context_t        pi_context;
+       osm_nd_context_t        nd_context;
+       osm_si_context_t        si_context;
+       osm_lft_context_t       lft_context;
+       osm_mft_context_t       mft_context;
+       osm_smi_context_t       smi_context;
+       osm_slvl_context_t      slvl_context;
+       osm_pkey_context_t      pkey_context;
+       osm_vla_context_t       vla_context;
+#ifndef OSM_VENDOR_INTF_OPENIB
+       osm_arbitrary_context_t arb_context;
+#endif
+} osm_madw_context_t;
+/*********/
+
+/****s* OpenSM: MAD Wrapper/osm_mad_addr_t
+* NAME
+*   osm_mad_addr_t
+*
+* DESCRIPTION
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mad_addr
+{
+    ib_net16_t dest_lid;
+    uint8_t    path_bits;
+    uint8_t    static_rate;
+
+    union addr_type
+    {
+        struct _smi
+               {
+                 ib_net16_t            source_lid;    
+                 uint8_t               port_num;       
+        } smi;
+
+        struct _gsi
+               {
+            ib_net32_t                 remote_qp;          
+            ib_net32_t                 remote_qkey;       
+            ib_net16_t                 pkey;
+            uint8_t                    service_level;          
+            boolean_t                  global_route;
+            ib_grh_t                   grh_info;
+        } gsi;
+    } addr_type;
+
+} osm_mad_addr_t;
+/*
+* FIELDS
+*
+* SEE ALSO
+*********/
+
+/****s* OpenSM: MAD Wrapper/osm_madw_t
+* NAME
+*      osm_madw_t
+*
+* DESCRIPTION
+*      Context needed for processing individual MADs
+*
+* SYNOPSIS
+*/
+typedef struct _osm_madw
+{
+       cl_pool_item_t                                  pool_item;
+       osm_bind_handle_t                               h_bind;
+       osm_vend_wrap_t                                 vend_wrap;
+       osm_mad_addr_t                                  mad_addr;
+       osm_bind_info_t                                 bind_info;
+       osm_madw_context_t                              context;
+       uint32_t                                        mad_size;
+       ib_api_status_t                                 status;
+       cl_disp_msgid_t                                 fail_msg;
+       boolean_t                                       resp_expected;
+       const ib_mad_t                                  *p_mad;
+} osm_madw_t;
+/*
+* FIELDS
+*      pool_item
+*              List linkage for pools and lists.  MUST BE FIRST MEMBER!
+*
+*      h_bind
+*              Bind handle for the port on which this MAD will be sent
+*              or was received.
+*
+*      vend_wrap
+*              Transport vendor specific context.  This structure is not
+*              used outside MAD transport vendor specific code.
+*
+*      context
+*              Union of controller specific contexts needed for this MAD.
+*              This structure allows controllers to indirectly communicate
+*              with each other through the dispatcher.
+*
+*      mad_size
+*              Size of this MAD in bytes.
+*
+*      status
+*              Status of completed operation on the MAD.
+*              CL_SUCCESS if the operation was successful.
+*
+*      fail_msg
+*              Dispatcher message with which to post this MAD on failure.
+*              This value is set by the originator of the MAD.
+*              If an operation on this MAD fails, for example due to a timeout,
+*              then the transport layer will dispose of the MAD by sending
+*              it through the Dispatcher with this message type.  Presumably,
+*              there is a controller listening for the failure message that can
+*              properly clean up.
+*
+*      resp_expected
+*              TRUE if a response is expected to this MAD.
+*              FALSE otherwise.
+*
+*      p_mad
+*              Pointer to the wire MAD.  The MAD itself cannot be part of the
+*              wrapper, since wire MADs typically reside in special memory
+*              registered with the local HCA.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_construct
+* NAME
+*      osm_madw_construct
+*
+* DESCRIPTION
+*      This function constructs a MAD Wrapper object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_madw_construct(
+       IN osm_madw_t* const p_madw )
+{
+       /*
+               Don't touch the pool_item since that is an opaque object.
+               Clear all other objects in the mad wrapper.
+       */
+       memset( ((uint8_t *)p_madw) + sizeof( cl_pool_item_t ), 0,
+               sizeof(*p_madw) - sizeof( cl_pool_item_t ) );
+}
+/*
+* PARAMETERS
+*      p_madw
+*              [in] Pointer to a MAD Wrapper object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_madw_init, osm_madw_destroy
+*
+*      Calling osm_madw_construct is a prerequisite to calling any other
+*      method except osm_madw_init.
+*
+* SEE ALSO
+*      MAD Wrapper object, osm_madw_init, osm_madw_destroy
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_destroy
+* NAME
+*      osm_madw_destroy
+*
+* DESCRIPTION
+*      The osm_madw_destroy function destroys a node, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_madw_destroy(
+       IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_madw
+*              [in] Pointer to a MAD Wrapper object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified MAD Wrapper object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to osm_madw_construct or
+*      osm_madw_init.
+*
+* SEE ALSO
+*      MAD Wrapper object, osm_madw_construct, osm_madw_init
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_init
+* NAME
+*      osm_madw_init
+*
+* DESCRIPTION
+*      Initializes a MAD Wrapper object for use.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_madw_init(
+       IN osm_madw_t* const p_madw,
+       IN osm_bind_handle_t h_bind,
+       IN const uint32_t mad_size,
+       IN const osm_mad_addr_t* const p_mad_addr )
+{
+       osm_madw_construct( p_madw );
+       p_madw->h_bind = h_bind;
+       p_madw->fail_msg = CL_DISP_MSGID_NONE;
+       p_madw->mad_size = mad_size;
+       if( p_mad_addr )
+               p_madw->mad_addr = *p_mad_addr;
+       p_madw->resp_expected = FALSE;
+}
+/*
+* PARAMETERS
+*      p_madw
+*              [in] Pointer to an osm_madw_t object to initialize.
+*
+*      h_bind
+*              [in] Pointer to the wire MAD.
+*
+*      p_mad_addr
+*              [in] Pointer to the MAD address structure.  This parameter may
+*              be NULL for directed route MADs.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_smp_ptr
+* NAME
+*      osm_madw_get_smp_ptr
+*
+* DESCRIPTION
+*      Gets a pointer to the SMP in this MAD.
+*
+* SYNOPSIS
+*/
+static inline ib_smp_t*
+osm_madw_get_smp_ptr(
+       IN const osm_madw_t* const p_madw )
+{
+       return( (ib_smp_t*)p_madw->p_mad );
+}
+/*
+* PARAMETERS
+*      p_madw
+*              [in] Pointer to an osm_madw_t object to initialize.
+*
+* RETURN VALUES
+*      Pointer to the start of the SMP MAD.
+*
+* NOTES
+*
+* SEE ALSO
+*      MAD Wrapper object, osm_madw_construct, osm_madw_destroy
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_sa_mad_ptr
+* NAME
+*      osm_madw_get_sa_mad_ptr
+*
+* DESCRIPTION
+*      Gets a pointer to the SA MAD in this MAD wrapper.
+*
+* SYNOPSIS
+*/
+static inline ib_sa_mad_t*
+osm_madw_get_sa_mad_ptr(
+       IN const osm_madw_t* const p_madw )
+{
+       return( (ib_sa_mad_t*)p_madw->p_mad );
+}
+/*
+* PARAMETERS
+*      p_madw
+*              [in] Pointer to an osm_madw_t object to initialize.
+*
+* RETURN VALUES
+*      Pointer to the start of the SMP MAD.
+*
+* NOTES
+*
+* SEE ALSO
+*      MAD Wrapper object, osm_madw_construct, osm_madw_destroy
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_ni_context_ptr
+* NAME
+*      osm_madw_get_ni_context_ptr
+*
+* DESCRIPTION
+*      Gets a pointer to the NodeInfo context in this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_ni_context_t*
+osm_madw_get_ni_context_ptr(
+       IN const osm_madw_t* const p_madw )
+{
+       return( (osm_ni_context_t*)&p_madw->context );
+}
+/*
+* PARAMETERS
+*      p_madw
+*              [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+*      Pointer to the start of the context structure.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_pi_context_ptr
+* NAME
+*      osm_madw_get_pi_context_ptr
+*
+* DESCRIPTION
+*      Gets a pointer to the PortInfo context in this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_pi_context_t*
+osm_madw_get_pi_context_ptr(
+       IN const osm_madw_t* const p_madw )
+{
+       return( (osm_pi_context_t*)&p_madw->context );
+}
+/*
+* PARAMETERS
+*      p_madw
+*              [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+*      Pointer to the start of the context structure.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_nd_context_ptr
+* NAME
+*      osm_madw_get_nd_context_ptr
+*
+* DESCRIPTION
+*      Gets a pointer to the NodeDescription context in this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_nd_context_t*
+osm_madw_get_nd_context_ptr(
+       IN const osm_madw_t* const p_madw )
+{
+       return( (osm_nd_context_t*)&p_madw->context );
+}
+/*
+* PARAMETERS
+*      p_madw
+*              [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+*      Pointer to the start of the context structure.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_lft_context_ptr
+* NAME
+*      osm_madw_get_lft_context_ptr
+*
+* DESCRIPTION
+*      Gets a pointer to the LFT context in this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_lft_context_t*
+osm_madw_get_lft_context_ptr(
+       IN const osm_madw_t* const p_madw )
+{
+       return( (osm_lft_context_t*)&p_madw->context );
+}
+/*
+* PARAMETERS
+*      p_madw
+*              [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+*      Pointer to the start of the context structure.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_mft_context_ptr
+* NAME
+*      osm_madw_get_mft_context_ptr
+*
+* DESCRIPTION
+*      Gets a pointer to the MFT context in this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_mft_context_t*
+osm_madw_get_mft_context_ptr(
+       IN const osm_madw_t* const p_madw )
+{
+       return( (osm_mft_context_t*)&p_madw->context );
+}
+/*
+* PARAMETERS
+*      p_madw
+*              [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+*      Pointer to the start of the context structure.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_si_context_ptr
+* NAME
+*      osm_madw_get_si_context_ptr
+*
+* DESCRIPTION
+*      Gets a pointer to the SwitchInfo context in this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_si_context_t*
+osm_madw_get_si_context_ptr(
+       IN const osm_madw_t* const p_madw )
+{
+       return( (osm_si_context_t*)&p_madw->context );
+}
+/*
+* PARAMETERS
+*      p_madw
+*              [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+*      Pointer to the start of the context structure.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_smi_context_ptr
+* NAME
+*      osm_madw_get_smi_context_ptr
+*
+* DESCRIPTION
+*      Gets a pointer to the SMInfo context in this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_smi_context_t*
+osm_madw_get_smi_context_ptr(
+       IN const osm_madw_t* const p_madw )
+{
+       return( (osm_smi_context_t*)&p_madw->context );
+}
+/*
+* PARAMETERS
+*      p_madw
+*              [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+*      Pointer to the start of the context structure.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_pkey_context_ptr
+* NAME
+*      osm_madw_get_pkey_context_ptr
+*
+* DESCRIPTION
+*      Gets a pointer to the P_Key context in this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_pkey_context_t*
+osm_madw_get_pkey_context_ptr(
+       IN const osm_madw_t* const p_madw )
+{
+       return( (osm_pkey_context_t*)&p_madw->context );
+}
+/*
+* PARAMETERS
+*      p_madw
+*              [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+*      Pointer to the start of the context structure.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_slvl_context_ptr
+* NAME
+*      osm_madw_get_slvl_context_ptr
+*
+* DESCRIPTION
+*      Gets a pointer to the PortInfo context in this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_slvl_context_t*
+osm_madw_get_slvl_context_ptr(
+       IN const osm_madw_t* const p_madw )
+{
+       return( (osm_slvl_context_t*)&p_madw->context );
+}
+/*
+* PARAMETERS
+*      p_madw
+*              [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+*      Pointer to the start of the context structure.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_vla_context_ptr
+* NAME
+*      osm_madw_get_vla_context_ptr
+*
+* DESCRIPTION
+*      Gets a pointer to the Vl Arb context in this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_vla_context_t*
+osm_madw_get_vla_context_ptr(
+       IN const osm_madw_t* const p_madw )
+{
+       return( (osm_vla_context_t*)&p_madw->context );
+}
+/*
+* PARAMETERS
+*      p_madw
+*              [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+*      Pointer to the start of the context structure.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+#ifndef OSM_VENDOR_INTF_OPENIB
+/****f* OpenSM: MAD Wrapper/osm_madw_get_arbitrary_context_ptr
+* NAME
+*      osm_madw_get_arbitrary_context_ptr
+*
+* DESCRIPTION
+*      Gets a pointer to the arbitrary context in this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_arbitrary_context_t*
+osm_madw_get_arbitrary_context_ptr(
+       IN const osm_madw_t* const p_madw )
+{
+       return( (osm_arbitrary_context_t*)&p_madw->context );
+}
+/*
+* PARAMETERS
+*      p_madw
+*              [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+*      Pointer to the start of the context structure.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+#endif
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_vend_ptr
+* NAME
+*      osm_madw_get_vend_ptr
+*
+* DESCRIPTION
+*      Gets a pointer to the vendor specific MAD wrapper component.
+*
+* SYNOPSIS
+*/
+static inline osm_vend_wrap_t*
+osm_madw_get_vend_ptr(
+       IN const osm_madw_t* const p_madw )
+{
+       return( (osm_vend_wrap_t*)&p_madw->vend_wrap );
+}
+/*
+* PARAMETERS
+*      p_madw
+*              [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+*      Gets a pointer to the vendor specific MAD wrapper component.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_vend_ptr
+* NAME
+*      osm_madw_get_vend_ptr
+*
+* DESCRIPTION
+*      Returns the bind handle associated with this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_bind_handle_t
+osm_madw_get_bind_handle(
+       IN const osm_madw_t* const p_madw )
+{
+       return( (osm_bind_handle_t)p_madw->h_bind );
+}
+/*
+* PARAMETERS
+*      p_madw
+*              [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+*      Returns the bind handle associated with this MAD.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_mad_addr_ptr
+* NAME
+*      osm_madw_get_mad_addr_ptr
+*
+* DESCRIPTION
+*      Returns the mad address structure associated with this MAD.
+*
+* SYNOPSIS
+*/
+static inline osm_mad_addr_t*
+osm_madw_get_mad_addr_ptr(
+       IN const osm_madw_t* const p_madw )
+{
+       return( (osm_mad_addr_t*)&p_madw->mad_addr );
+}
+/*
+* PARAMETERS
+*      p_madw
+*              [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+*      Returns the mad address structure associated with this MAD.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_mad_ptr
+* NAME
+*      osm_madw_get_mad_ptr
+*
+* DESCRIPTION
+*      Returns the mad address structure associated with this MAD.
+*
+* SYNOPSIS
+*/
+static inline ib_mad_t*
+osm_madw_get_mad_ptr(
+       IN const osm_madw_t* const p_madw )
+{
+       return( (ib_mad_t*)p_madw->p_mad );
+}
+/*
+* PARAMETERS
+*      p_madw
+*              [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+*      Returns the mad address structure associated with this MAD.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_get_err_msg
+* NAME
+*      osm_madw_get_err_msg
+*
+* DESCRIPTION
+*      Returns the message with which to post this mad wrapper if
+*      an error occurs during processing the mad.
+*
+* SYNOPSIS
+*/
+static inline cl_disp_msgid_t
+osm_madw_get_err_msg(
+       IN const osm_madw_t* const p_madw )
+{
+       return( (cl_disp_msgid_t)p_madw->fail_msg );
+}
+/*
+* PARAMETERS
+*      p_madw
+*              [in] Pointer to an osm_madw_t object.
+*
+* RETURN VALUES
+*      Returns the message with which to post this mad wrapper if
+*      an error occurs during processing the mad.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_set_mad
+* NAME
+*      osm_madw_set_mad
+*
+* DESCRIPTION
+*      Associates a wire MAD with this MAD Wrapper object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_madw_set_mad(
+       IN osm_madw_t* const p_madw,
+       IN const ib_mad_t* const p_mad )
+{
+       p_madw->p_mad = p_mad;
+}
+/*
+* PARAMETERS
+*      p_madw
+*              [in] Pointer to an osm_madw_t object.
+*
+*      p_mad
+*              [in] Pointer to the wire MAD to attach to this wrapper.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_copy_context
+* NAME
+*      osm_madw_copy_context
+*
+* DESCRIPTION
+*      Copies the controller context from one MAD Wrapper to another.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_madw_copy_context(
+       IN osm_madw_t* const p_dest,
+       IN const osm_madw_t* const p_src )
+{
+       p_dest->context = p_src->context;
+}
+/*
+* PARAMETERS
+*      p_dest
+*              [in] Pointer to the destination osm_madw_t object.
+*
+*      p_src
+*              [in] Pointer to the source osm_madw_t object.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif         /* _OSM_MADW_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_matrix.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_matrix.h
new file mode 100644 (file)
index 0000000..51ff3c0
--- /dev/null
@@ -0,0 +1,454 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_matrix.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_lid_matrix_t.
+ *     This object represents a two dimensional array of port numbers
+ *     and LID values.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+
+#ifndef _OSM_MATRIX_H_
+#define _OSM_MATRIX_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_vector.h>
+#include <opensm/osm_base.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/LID Matrix
+* NAME
+*      LID Matrix
+*
+* DESCRIPTION
+*      The LID Matrix object encapsulates the information needed by the
+*      OpenSM to manage fabric routes.  It is a two dimensional array
+*      index by LID value and Port Number.  Each element contains the
+*      number of hops from that Port Number to the LID.
+*      Every Switch object contains a LID Matrix.
+*
+*      The LID Matrix is not thread safe, thus callers must provide
+*      serialization.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: LID Matrix/osm_lid_matrix_t
+* NAME
+*      osm_lid_matrix_t
+*
+* DESCRIPTION
+*
+*      The LID Matrix object encapsulates the information needed by the
+*      OpenSM to manage fabric routes.  It is a two dimensional array
+*      index by LID value and Port Number.  Each element contains the
+*      number of hops from that Port Number to the LID.
+*      Every Switch object contains a LID Matrix.
+*
+*      The LID Matrix is not thread safe, thus callers must provide
+*      serialization.
+*
+*      The num_ports index into the matrix serves a special purpose, in that it
+*      contains the shortest hop path for that LID through any port.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lid_matrix_t
+{
+       cl_vector_t                     lid_vec;
+       uint8_t                         num_ports;
+
+} osm_lid_matrix_t;
+/*
+* FIELDS
+*      lid_vec
+*              Vector (indexed by LID) of port arrays (indexed by port number)
+*
+*      num_ports
+*              Number of ports at each entry in the LID vector.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_construct
+* NAME
+*      osm_lid_matrix_construct
+*
+* DESCRIPTION
+*      This function constructs a LID Matrix object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_lid_matrix_construct(
+       IN osm_lid_matrix_t* const p_lmx )
+{
+       p_lmx->num_ports = 0;
+       cl_vector_construct( &p_lmx->lid_vec );
+}
+/*
+* PARAMETERS
+*      p_lmx
+*              [in] Pointer to a LID Matrix object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_lid_matrix_init, osm_lid_matrix_destroy
+*
+*      Calling osm_lid_matrix_construct is a prerequisite to calling any other
+*      method except osm_lid_matrix_init.
+*
+* SEE ALSO
+*      LID Matrix object, osm_lid_matrix_init, osm_lid_matrix_destroy
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_destroy
+* NAME
+*      osm_lid_matrix_destroy
+*
+* DESCRIPTION
+*      The osm_lid_matrix_destroy function destroys a node, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_lid_matrix_destroy(
+       IN osm_lid_matrix_t* const p_lmx );
+/*
+* PARAMETERS
+*      p_lmx
+*              [in] Pointer to a LID Matrix object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified LID Matrix object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to osm_lid_matrix_construct or
+*      osm_lid_matrix_init.
+*
+* SEE ALSO
+*      LID Matrix object, osm_lid_matrix_construct, osm_lid_matrix_init
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_init
+* NAME
+*      osm_lid_matrix_init
+*
+* DESCRIPTION
+*      Initializes a LID Matrix object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_lid_matrix_init(
+       IN osm_lid_matrix_t* const p_lmx,
+       IN const uint8_t num_ports );
+/*
+* PARAMETERS
+*      p_lmx
+*              [in] Pointer to an osm_lid_matrix_t object to initialize.
+*
+*      num_ports
+*              [in] Number of ports at each LID index.  This value is fixed
+*              at initialization time.
+*
+* RETURN VALUES
+*      IB_SUCCESS on success
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_get
+* NAME
+*      osm_lid_matrix_get
+*
+* DESCRIPTION
+*      Returns the hop count at the specified LID/Port intersection.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_lid_matrix_get(
+       IN const osm_lid_matrix_t* const p_lmx,
+       IN const uint16_t lid_ho,
+       IN const uint8_t port_num )
+{
+       CL_ASSERT( port_num < p_lmx->num_ports );
+       CL_ASSERT( lid_ho <cl_vector_get_size(&p_lmx->lid_vec) );
+       return( ((uint8_t *)cl_vector_get_ptr(
+                       &p_lmx->lid_vec, lid_ho ))[port_num] );
+}
+/*
+* PARAMETERS
+*      p_lmx
+*              [in] Pointer to an osm_lid_matrix_t object.
+*
+*      lid_ho
+*              [in] LID value (host order) for which to return the hop count
+*
+*      port_num
+*              [in] Port number in the switch
+*
+* RETURN VALUES
+*      Returns the hop count at the specified LID/Port intersection.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_get_max_lid_ho
+* NAME
+*      osm_lid_matrix_get_max_lid_ho
+*
+* DESCRIPTION
+*      Returns the maximum LID (host order) value contained
+*      in the matrix.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_lid_matrix_get_max_lid_ho(
+       IN const osm_lid_matrix_t* const p_lmx )
+{
+       return( (uint16_t)(cl_vector_get_size( &p_lmx->lid_vec ) - 1 ) );
+}
+/*
+* PARAMETERS
+*      p_lmx
+*              [in] Pointer to an osm_lid_matrix_t object.
+*
+* RETURN VALUES
+*      Returns the maximum LID (host order) value contained
+*      in the matrix.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_get_num_ports
+* NAME
+*      osm_lid_matrix_get_num_ports
+*
+* DESCRIPTION
+*      Returns the number of ports in this lid matrix.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_lid_matrix_get_num_ports(
+       IN const osm_lid_matrix_t* const p_lmx )
+{
+       return( p_lmx->num_ports );
+}
+/*
+* PARAMETERS
+*      p_lmx
+*              [in] Pointer to an osm_lid_matrix_t object.
+*
+* RETURN VALUES
+*      Returns the number of ports in this lid matrix.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_get_least_hops
+* NAME
+*      osm_lid_matrix_get_least_hops
+*
+* DESCRIPTION
+*      Returns the least number of hops for specified lid
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_lid_matrix_get_least_hops(
+       IN const osm_lid_matrix_t* const p_lmx,
+       IN const uint16_t lid_ho )
+{
+       if( lid_ho > osm_lid_matrix_get_max_lid_ho( p_lmx ) )
+               return( OSM_NO_PATH );
+
+       return( ((uint8_t *)cl_vector_get_ptr(
+                       &p_lmx->lid_vec, lid_ho ))[p_lmx->num_ports] );
+}
+/*
+* PARAMETERS
+*      p_lmx
+*              [in] Pointer to an osm_lid_matrix_t object.
+*
+*      lid_ho
+*              [in] LID (host order) for which to retrieve the shortest hop count.
+*
+* RETURN VALUES
+*      Returns the least number of hops for specified lid
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_set
+* NAME
+*      osm_lid_matrix_set
+*
+* DESCRIPTION
+*      Sets the hop count at the specified LID/Port intersection.
+*
+* SYNOPSIS
+*/
+cl_status_t
+osm_lid_matrix_set(
+       IN osm_lid_matrix_t* const p_lmx,
+       IN const uint16_t lid_ho,
+       IN const uint8_t port_num,
+       IN const uint8_t val );
+/*
+* PARAMETERS
+*      p_lmx
+*              [in] Pointer to an osm_lid_matrix_t object.
+*
+*      lid_ho
+*              [in] LID value (host order) to index into the vector.
+*
+*      port_num
+*              [in] port number index into the vector entry.
+*
+*      val
+*              [in] value (number of hops) to assign to this entry.
+*
+* RETURN VALUES
+*      Returns the hop count at the specified LID/Port intersection.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_set_min_lid_size
+* NAME
+*      osm_lid_matrix_set_min_lid_size
+*
+* DESCRIPTION
+*      Sets the size of the matrix to at least accomodate the
+*      specified LID value (host ordered)
+*
+* SYNOPSIS
+*/
+static inline cl_status_t
+osm_lid_matrix_set_min_lid_size(
+       IN osm_lid_matrix_t* const p_lmx,
+       IN const uint16_t lid_ho )
+{
+       return( cl_vector_set_min_size( &p_lmx->lid_vec, lid_ho + 1 ) );
+}
+/*
+* PARAMETERS
+*      p_lmx
+*              [in] Pointer to an osm_lid_matrix_t object.
+*
+*      lid_ho
+*              [in] Minimum LID value (host order) to accomodate.
+*
+* RETURN VALUES
+*      Sets the size of the matrix to at least accomodate the
+*      specified LID value (host ordered)
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_clear
+* NAME
+*      osm_lid_matrix_clear
+*
+* DESCRIPTION
+*      Clears a LID Matrix object in anticipation of a rebuild.
+*
+* SYNOPSIS
+*/
+void
+osm_lid_matrix_clear(
+       IN osm_lid_matrix_t* const p_lmx );
+/*
+* PARAMETERS
+*      p_lmx
+*              [in] Pointer to an osm_lid_matrix_t object to clear.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif         /* _OSM_MATRIX_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_fwd_rcv.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_fwd_rcv.h
new file mode 100644 (file)
index 0000000..ddc92dc
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_mcast_fwd_rcv.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_mft_rcv_t.
+ *     This object represents the Multicast Forwarding Table Receiver object.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_MFT_RCV_H_
+#define _OSM_MFT_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/MFT Receiver
+* NAME
+*      MFT Receiver
+*
+* DESCRIPTION
+*      The MFT Receiver object encapsulates the information
+*      needed to receive the MFT attribute from a node.
+*
+*      The MFT Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: MFT Receiver/osm_mft_rcv_t
+* NAME
+*      osm_mft_rcv_t
+*
+* DESCRIPTION
+*      MFT Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mft_rcv
+{
+       osm_subn_t                                      *p_subn;
+       osm_log_t                                       *p_log;
+       cl_plock_t                                      *p_lock;
+
+} osm_mft_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+* SEE ALSO
+*      MFT Receiver object
+*********/
+
+/****f* OpenSM: MFT Receiver/osm_mft_rcv_construct
+* NAME
+*      osm_mft_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a MFT Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_mft_rcv_construct(
+       IN osm_mft_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to a MFT Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_mft_rcv_init, osm_mft_rcv_destroy
+*
+*      Calling osm_mft_rcv_construct is a prerequisite to calling any other
+*      method except osm_mft_rcv_init.
+*
+* SEE ALSO
+*      MFT Receiver object, osm_mft_rcv_init,
+*      osm_mft_rcv_destroy
+*********/
+
+/****f* OpenSM: MFT Receiver/osm_mft_rcv_destroy
+* NAME
+*      osm_mft_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_mft_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mft_rcv_destroy(
+       IN osm_mft_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      MFT Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_mft_rcv_construct or osm_mft_rcv_init.
+*
+* SEE ALSO
+*      MFT Receiver object, osm_mft_rcv_construct,
+*      osm_mft_rcv_init
+*********/
+
+/****f* OpenSM: MFT Receiver/osm_mft_rcv_init
+* NAME
+*      osm_mft_rcv_init
+*
+* DESCRIPTION
+*      The osm_mft_rcv_init function initializes a
+*      MFT Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_mft_rcv_init(
+       IN osm_mft_rcv_t* const p_rcv,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_mft_rcv_t object to initialize.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the MFT Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other MFT Receiver methods.
+*
+* SEE ALSO
+*      MFT Receiver object, osm_mft_rcv_construct,
+*      osm_mft_rcv_destroy
+*********/
+
+/****f* OpenSM: MFT Receiver/osm_mft_rcv_process
+* NAME
+*      osm_mft_rcv_process
+*
+* DESCRIPTION
+*      Process the MFT attribute.
+*
+* SYNOPSIS
+*/
+void
+osm_mft_rcv_process(
+       IN const osm_mft_rcv_t* const p_rcv,
+       IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_mft_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the node's MFT attribute.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the MFT processing was successful.
+*
+* NOTES
+*      This function processes a MFT attribute.
+*
+* SEE ALSO
+*      MFT Receiver, Node Description Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MFT_RCV_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_fwd_rcv_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_fwd_rcv_ctrl.h
new file mode 100644 (file)
index 0000000..11f3bcb
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_mcast_fwd_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_mft_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA
+ *  Multicast Forwarding Table attribute from a node (specifically, a
+ *     switch).
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_MFT_RCV_CTRL_H_
+#define _OSM_MFT_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mcast_fwd_rcv.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/MFT Receive Controller
+* NAME
+*      MFT Receive Controller
+*
+* DESCRIPTION
+*      The MFT Receive Controller object
+*      encapsulates the information
+*      needed to receive the Multicast Forwarding Table
+*      attribute from a node.
+*
+*      The MFT Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: MFT Receive Controller/osm_mft_rcv_ctrl_t
+* NAME
+*      osm_mft_rcv_ctrl_t
+*
+* DESCRIPTION
+*      MFT Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mft_rcv_ctrl
+{
+       osm_mft_rcv_t                           *p_rcv;
+       osm_log_t                                       *p_log;
+       cl_dispatcher_t                         *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_mft_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the MFT Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      MFT Receive Controller object
+*********/
+
+/****f* OpenSM: MFT Receive Controller/osm_mft_rcv_ctrl_construct
+* NAME
+*      osm_mft_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a MFT Receive Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_mft_rcv_ctrl_construct(
+       IN osm_mft_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a MFT Receive Controller object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_mft_rcv_ctrl_init, osm_mft_rcv_ctrl_destroy
+*
+*      Calling osm_mft_rcv_ctrl_construct is a prerequisite to calling any other
+*      method except osm_mft_rcv_ctrl_init.
+*
+* SEE ALSO
+*      MFT Receive Controller object, osm_mft_rcv_ctrl_init,
+*      osm_mft_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: MFT Receive Controller/osm_mft_rcv_ctrl_destroy
+* NAME
+*      osm_mft_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_mft_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mft_rcv_ctrl_destroy(
+       IN osm_mft_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      MFT Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_mft_rcv_ctrl_construct or osm_mft_rcv_ctrl_init.
+*
+* SEE ALSO
+*      MFT Receive Controller object, osm_mft_rcv_ctrl_construct,
+*      osm_mft_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: MFT Receive Controller/osm_mft_rcv_ctrl_init
+* NAME
+*      osm_mft_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_mft_rcv_ctrl_init function initializes a
+*      MFT Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_mft_rcv_ctrl_init(
+       IN osm_mft_rcv_ctrl_t* const p_ctrl,
+       IN osm_mft_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_mft_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_mft_rcv_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the MFT Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other MFT Receive Controller methods.
+*
+* SEE ALSO
+*      MFT Receive Controller object, osm_mft_rcv_ctrl_construct,
+*      osm_mft_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif         /* OSM_MFT_RCV_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_mgr.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_mgr.h
new file mode 100644 (file)
index 0000000..d0adc6b
--- /dev/null
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_mcast_mgr.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_mcast_mgr_t.
+ *     This object represents the Multicast Manager object.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_MCAST_MGR_H_
+#define _OSM_MCAST_MGR_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_multicast.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+#define OSM_MCAST_MGR_LIST_SIZE_MIN 256
+
+/****h* OpenSM/Multicast Manager
+* NAME
+*      Multicast Manager
+*
+* DESCRIPTION
+*      The Multicast Manager object encapsulates the information
+*      needed to control multicast LID forwarding on the subnet.
+*
+*      The Multicast Manager object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Multicast Manager/osm_mcast_mgr_t
+* NAME
+*      osm_mcast_mgr_t
+*
+* DESCRIPTION
+*      Multicast Manager structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mcast_mgr
+{
+       osm_subn_t                                      *p_subn;
+       osm_req_t                                       *p_req;
+       osm_log_t                                       *p_log;
+       cl_plock_t                                      *p_lock;
+
+} osm_mcast_mgr_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_req
+*              Pointer to the Requester object sending SMPs.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+* SEE ALSO
+*      Multicast Manager object
+*********/
+
+/****f* OpenSM: Multicast Manager/osm_mcast_mgr_construct
+* NAME
+*      osm_mcast_mgr_construct
+*
+* DESCRIPTION
+*      This function constructs a Multicast Manager object.
+*
+* SYNOPSIS
+*/
+void
+osm_mcast_mgr_construct(
+       IN osm_mcast_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to a Multicast Manager object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows osm_mcast_mgr_destroy
+*
+*      Calling osm_mcast_mgr_construct is a prerequisite to calling any other
+*      method except osm_mcast_mgr_init.
+*
+* SEE ALSO
+*      Multicast Manager object, osm_mcast_mgr_init,
+*      osm_mcast_mgr_destroy
+*********/
+
+/****f* OpenSM: Multicast Manager/osm_mcast_mgr_destroy
+* NAME
+*      osm_mcast_mgr_destroy
+*
+* DESCRIPTION
+*      The osm_mcast_mgr_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mcast_mgr_destroy(
+       IN osm_mcast_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Multicast Manager object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_mcast_mgr_construct or osm_mcast_mgr_init.
+*
+* SEE ALSO
+*      Multicast Manager object, osm_mcast_mgr_construct,
+*      osm_mcast_mgr_init
+*********/
+
+/****f* OpenSM: Multicast Manager/osm_mcast_mgr_init
+* NAME
+*      osm_mcast_mgr_init
+*
+* DESCRIPTION
+*      The osm_mcast_mgr_init function initializes a
+*      Multicast Manager object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_mcast_mgr_init(
+       IN osm_mcast_mgr_t* const p_mgr,
+       IN osm_req_t* const p_req,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to an osm_mcast_mgr_t object to initialize.
+*
+*      p_req
+*              [in] Pointer to the attribute Requester object.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the Multicast Manager object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Multicast Manager methods.
+*
+* SEE ALSO
+*      Multicast Manager object, osm_mcast_mgr_construct,
+*      osm_mcast_mgr_destroy
+*********/
+
+/****f* OpenSM: Multicast Manager/osm_mcast_mgr_process
+* NAME
+*      osm_mcast_mgr_process
+*
+* DESCRIPTION
+*      Process and configure the subnet's multicast forwarding tables.
+*
+* SYNOPSIS
+*/
+osm_signal_t
+osm_mcast_mgr_process(
+       IN osm_mcast_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to an osm_mcast_mgr_t object.
+*
+* RETURN VALUES
+*      Returns the appropriate signal to the caller:
+*              OSM_SIGNAL_DONE - operation is complete
+*              OSM_SIGNAL_DONE_PENDING - local operations are complete, but
+*                      transactions are still pending on the wire.
+*
+* NOTES
+*      This function processes the subnet, configuring switch
+*      multicast forwarding tables.
+*
+* SEE ALSO
+*      Multicast Manager, Node Info Response Controller
+*********/
+
+/****f* OpenSM: Multicast Manager/osm_mcast_mgr_process_mgrp_cb
+* NAME
+*      osm_mcast_mgr_process_mgrp_cb
+*
+* DESCRIPTION
+*      Callback entry point for the osm_mcast_mgr_process_mgrp function.
+*
+* SYNOPSIS
+*/
+osm_signal_t
+osm_mcast_mgr_process_mgrp_cb(
+       IN void*                                        const Context1,
+       IN void*                                        const Context2 );
+/*
+* PARAMETERS
+*      (Context1) p_mgr
+*              [in] Pointer to an osm_mcast_mgr_t object.
+*
+*      (Context2) p_mgrp
+*              [in] Pointer to the multicast group to process.
+*
+* RETURN VALUES
+*      IB_SUCCESS
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Manager/osm_mcast_mgr_process
+* NAME
+*      osm_mcast_mgr_process_single
+*
+* DESCRIPTION
+*      Attempts to add a single port to an existing multicast spanning tree.
+*      This function can only succeed if the port to be added is connected
+*      to a switch that is already routing traffic for this multicast group.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_mcast_mgr_process_single(
+       IN osm_mcast_mgr_t* const p_mgr,
+       IN const ib_net16_t mlid,
+       IN const ib_net64_t port_guid,
+       IN const uint8_t join_state );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to an osm_mcast_mgr_t object.
+*
+*      mlid
+*              [in] Multicast LID of relevent multicast group.
+*
+*      port_guid
+*              [in] GUID of port to attempt to add to the group.
+*
+*      join_state
+*              [in] Specifies the join state for this port per the spec.
+*
+* RETURN VALUES
+*      IB_SUCCESS
+*      IB_NOT_DONE
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+       
+END_C_DECLS
+
+#endif /* _OSM_MCAST_MGR_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_tbl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcast_tbl.h
new file mode 100644 (file)
index 0000000..efb6d23
--- /dev/null
@@ -0,0 +1,484 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_mcast_tbl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_mcast_tbl_t.
+ *     This object represents a multicast forwarding table.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#ifndef _OSM_MCAST_TBL_H_
+#define _OSM_MCAST_TBL_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <opensm/osm_base.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****s* OpenSM: Forwarding Table/osm_mcast_tbl_t
+* NAME
+*      osm_mcast_tbl_t
+*
+* DESCRIPTION
+*      Multicast Forwarding Table structure.
+*
+*      Callers may directly access this object.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mcast_fwd_tbl
+{
+       uint8_t                         num_ports;
+       uint8_t                         max_position;
+       uint16_t                        max_block;
+       int16_t                         max_block_in_use;
+       uint16_t                        num_entries;
+       uint16_t                        max_mlid_ho;
+       uint16_t                        (*p_mask_tbl)[][IB_MCAST_POSITION_MAX];
+} osm_mcast_tbl_t;
+/*
+* FIELDS
+*      num_ports
+*              The number of ports in the port mask.  This value
+*              is the same as the number of ports on the switch
+*
+*      max_position
+*              Maximum bit mask position for this table.  This value
+*              is computed from the number of ports on the switch.
+*
+*      max_block
+*              Maximum block number supported in the table.  This value
+*              is approximately the number of MLID entries divided by the
+*              number of MLIDs per block
+*
+*      num_entries
+*              Number of entries in the table (aka number of MLIDs supported).
+*
+*      max_mlid_ho
+*              Maximum MLID value (host order).
+*
+*      pp_mask_tbl
+*              Pointer to a two dimensional array of port_masks for this switch.
+*              The first dimension is MLID, the second dimension is mask position.
+*              This pointer is null for switches that do not support multicast.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_mcast_tbl_init
+* NAME
+*      osm_mcast_tbl_init
+*
+* DESCRIPTION
+*      This function initializes a Multicast Forwarding Table object.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_mcast_tbl_init(
+       IN osm_mcast_tbl_t* const p_tbl,
+       IN uint8_t const num_ports,
+       IN uint16_t const capacity );
+/*
+* PARAMETERS
+*      num_ports
+*              [in] Number of ports in the switch owning this table.
+*
+*      capacity
+*              [in] The number of MLID entries (starting at 0xC000) supported
+*              by this switch.
+*
+* RETURN VALUE
+*      IB_SUCCESS on success.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_mcast_tbl_delete
+* NAME
+*      osm_mcast_tbl_delete
+*
+* DESCRIPTION
+*      This destroys and deallocates a Multicast Forwarding Table object.
+*
+* SYNOPSIS
+*/
+void
+osm_mcast_tbl_delete(
+       IN osm_mcast_tbl_t** const pp_tbl );
+/*
+* PARAMETERS
+*      pp_tbl
+*              [in] Pointer a Pointer to the Multicast Forwarding Table object.
+*
+* RETURN VALUE
+*      On success, returns a pointer to a new Multicast Forwarding Table object
+*      of the specified size.
+*      NULL otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_mcast_tbl_destroy
+* NAME
+*      osm_mcast_tbl_destroy
+*
+* DESCRIPTION
+*      This destroys and deallocates a Multicast Forwarding Table object.
+*
+* SYNOPSIS
+*/
+void
+osm_mcast_tbl_destroy(
+  IN osm_mcast_tbl_t* const p_tbl );
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Multicast Forwarding Table object.
+*
+* RETURN VALUE
+*    None
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_mcast_tbl_set
+* NAME
+*      osm_mcast_tbl_set
+*
+* DESCRIPTION
+*      Adds the port to the multicast group.
+*
+* SYNOPSIS
+*/
+void
+osm_mcast_tbl_set(
+       IN osm_mcast_tbl_t* const p_tbl,
+       IN const uint16_t mlid_ho,
+       IN const uint8_t port_num );
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Multicast Forwarding Table object.
+*
+*      mlid_ho
+*              [in] MLID value (host order) for which to set the route.
+*
+*      port_num
+*              [in] Port to add to the multicast group.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_mcast_tbl_clear_mlid
+* NAME
+*      osm_mcast_tbl_clear_mlid
+*
+* DESCRIPTION
+*      Removes all multicast paths for the specified MLID.
+*
+* SYNOPSIS
+*/
+void
+osm_mcast_tbl_clear_mlid(
+       IN osm_mcast_tbl_t* const p_tbl,
+       IN const uint16_t mlid_ho );
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Multicast Forwarding Table object.
+*
+*      mlid_ho
+*              [in] MLID value (host order) for which to clear.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_mcast_tbl_is_port
+* NAME
+*      osm_mcast_tbl_is_port
+*
+* DESCRIPTION
+*      Returns TRUE if the port is in the multicast group.
+*
+* SYNOPSIS
+*/
+boolean_t
+osm_mcast_tbl_is_port(
+       IN const osm_mcast_tbl_t* const p_tbl,
+       IN const uint16_t mlid_ho,
+       IN const uint8_t port_num );
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Multicast Forwarding Table object.
+*
+*      mlid_ho
+*              [in] MLID value (host order).
+*
+*      port_num
+*              [in] Port number on the switch
+*
+* RETURN VALUE
+*      Returns the port that routes the specified LID.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_mcast_tbl_is_any_port
+* NAME
+*      osm_mcast_tbl_is_any_port
+*
+* DESCRIPTION
+*      Returns TRUE if any port is in the multicast group.
+*
+* SYNOPSIS
+*/
+boolean_t
+osm_mcast_tbl_is_any_port(
+       IN const osm_mcast_tbl_t* const p_tbl,
+       IN const uint16_t mlid_ho );
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Multicast Forwarding Table object.
+*
+*      mlid_ho
+*              [in] MLID value (host order).
+*
+* RETURN VALUE
+*      Returns TRUE if any port is in the multicast group.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_mcast_tbl_set_block
+* NAME
+*      osm_mcast_tbl_set_block
+*
+* DESCRIPTION
+*      Copies the specified block into the Multicast Forwarding Table.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_mcast_tbl_set_block(
+       IN osm_mcast_tbl_t* const p_tbl,
+       IN const ib_net16_t* const p_block,
+       IN const int16_t block_num,
+       IN const uint8_t position );
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Multicast Forwarding Table object.
+*
+*      p_block
+*              [in] Pointer to the Forwarding Table block.
+*
+*      block_num
+*              [in] Block number of this block.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_mcast_get_tbl_block
+* NAME
+*      osm_mcast_get_tbl_block
+*
+* DESCRIPTION
+*      Retrieve a multicast forwarding table block.
+*
+* SYNOPSIS
+*/
+boolean_t
+osm_mcast_tbl_get_block(
+       IN osm_mcast_tbl_t* const p_tbl,
+       IN const int16_t block_num,
+       IN const uint8_t position,
+       OUT ib_net16_t* const p_block );
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to an osm_mcast_tbl_t object.
+*
+*      p_block
+*              [in] Pointer to the Forwarding Table block.
+*
+*      block_num
+*              [in] Block number of this block.
+*
+*      p_block
+*              [out] Pointer to the 32 entry array to store the
+*              forwarding table clock specified by block_id.
+*
+* RETURN VALUES
+*      Returns true if there are more blocks necessary to 
+*      configure all the MLIDs reachable from this switch.
+*      FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_mcast_tbl_get_max_block
+* NAME
+*      osm_mcast_tbl_get_max_block
+*
+* DESCRIPTION
+*      Returns the maximum block ID in this table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_mcast_tbl_get_max_block(
+       IN osm_mcast_tbl_t* const p_tbl )
+{
+       return( p_tbl->max_block );
+}
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to an osm_mcast_tbl_t object.
+*
+* RETURN VALUES
+*      Returns the maximum block ID in this table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_mcast_tbl_get_max_block_in_use
+* NAME
+*      osm_mcast_tbl_get_max_block_in_use
+*
+* DESCRIPTION
+*      Returns the maximum block ID in use in this table.
+*      A value of -1 indicates no blocks are in use.
+*
+* SYNOPSIS
+*/
+static inline int16_t
+osm_mcast_tbl_get_max_block_in_use(
+       IN osm_mcast_tbl_t* const p_tbl )
+{
+       return( p_tbl->max_block_in_use );
+}
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to an osm_mcast_tbl_t object.
+*
+* RETURN VALUES
+*      Returns the maximum block ID in use in this table.
+*      A value of -1 indicates no blocks are in use.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_mcast_tbl_get_max_position
+* NAME
+*      osm_mcast_tbl_get_max_position
+*
+* DESCRIPTION
+*      Returns the maximum position in this table.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_mcast_tbl_get_max_position(
+       IN osm_mcast_tbl_t* const p_tbl )
+{
+       return( p_tbl->max_position );
+}
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to an osm_mcast_tbl_t object.
+*
+* RETURN VALUES
+*      Returns the maximum position in this table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif         /* _OSM_MCAST_TBL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcm_info.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcm_info.h
new file mode 100644 (file)
index 0000000..e2a7f7c
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_mcm_info.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_mcm_info_t.
+ *     This object represents a Multicast Forwarding Information object.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_MCM_INFO_H_
+#define _OSM_MCM_INFO_H_
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****s* OpenSM: Multicast Member Info/osm_mcm_info_t
+* NAME
+*      osm_mcm_info_t
+*
+* DESCRIPTION
+*      Multicast Membership Info object.
+*      This object contains information about a nodes membership
+*      in a particular multicast group.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mcm_info
+{
+       cl_list_item_t                          list_item;
+       ib_net16_t                                      mlid;
+
+} osm_mcm_info_t;
+/*
+* FIELDS
+*      list_item
+*              Linkage structure for cl_qlist.  MUST BE FIRST MEMBER!
+*
+*      mlid
+*              MLID of this multicast group.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Member Info/osm_mcm_info_construct
+* NAME
+*      osm_mcm_info_construct
+*
+* DESCRIPTION
+*      This function constructs a Multicast Member Info object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_mcm_info_construct(
+       IN osm_mcm_info_t* const p_mcm )
+{
+       memset( p_mcm, 0, sizeof(*p_mcm) );
+}
+/*
+* PARAMETERS
+*      p_mcm
+*              [in] Pointer to a Multicast Member Info object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Member Info/osm_mcm_info_destroy
+* NAME
+*      osm_mcm_info_destroy
+*
+* DESCRIPTION
+*      The osm_mcm_info_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mcm_info_destroy(
+       IN osm_mcm_info_t* const p_mcm );
+/*
+* PARAMETERS
+*      p_mcm
+*              [in] Pointer to a Multicast Member Info object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified Multicast Member Info object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to osm_mtree_construct or
+*      osm_mtree_init.
+*
+* SEE ALSO
+*      Multicast Member Info object, osm_mtree_construct, osm_mtree_init
+*********/
+
+/****f* OpenSM: Multicast Member Info/osm_mcm_info_init
+* NAME
+*      osm_mcm_info_init
+*
+* DESCRIPTION
+*      Initializes a Multicast Member Info object for use.
+*
+* SYNOPSIS
+*/
+void
+osm_mcm_info_init(
+       IN osm_mcm_info_t* const p_mcm,
+       IN const ib_net16_t mlid );
+/*
+* PARAMETERS
+*      p_mcm
+*              [in] Pointer to an osm_mcm_info_t object to initialize.
+*
+*      mlid
+*              [in] MLID value for this multicast group.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Member Info/osm_mcm_info_new
+* NAME
+*      osm_mcm_info_new
+*
+* DESCRIPTION
+*      Returns an initialized a Multicast Member Info object for use.
+*
+* SYNOPSIS
+*/
+osm_mcm_info_t*
+osm_mcm_info_new(
+  IN const ib_net16_t mlid );
+/*
+* PARAMETERS
+*      mlid
+*              [in] MLID value for this multicast group.
+*
+* RETURN VALUES
+*      Pointer to an initialized tree node.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Member Info/osm_mcm_info_delete
+* NAME
+*      osm_mcm_info_delete
+*
+* DESCRIPTION
+*      Destroys and deallocates the specified object.
+*
+* SYNOPSIS
+*/
+void
+osm_mcm_info_delete(
+       IN osm_mcm_info_t* const p_mcm );
+/*
+* PARAMETERS
+*      p_mcm
+*              Pointer to the object to destroy.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif         /* _OSM_MCM_INFO_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcm_port.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mcm_port.h
new file mode 100644 (file)
index 0000000..006c571
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_mcm_port.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_mcm_port_t.
+ *     This object represents the membership of a port in a multicast group.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_MCM_PORT_H_
+#define _OSM_MCM_PORT_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <opensm/osm_base.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****s* OpenSM: MCM Port Object/osm_mcm_port_t
+* NAME
+*   osm_mcm_port_t
+*
+* DESCRIPTION
+*   This object represents a particular        port as a member of a
+*      multicast group.
+*
+*   This object should be treated as opaque and should
+*   be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mcm_port
+{
+       cl_map_item_t   map_item;
+       ib_gid_t        port_gid;
+       uint8_t         scope_state;
+       boolean_t       proxy_join;
+} osm_mcm_port_t;
+/*
+* FIELDS
+*      map_item
+*              Map Item for qmap linkage.  Must be first element!!
+*
+*      port_gid
+*              GID of the member port.
+*
+*      scope_state
+*              ???
+*
+*      proxy_join
+*              If FALSE - Join was performed by the endport identified
+*              by PortGID. If TRUE - Join was performed on behalf of
+*              the endport identified by PortGID by another port within
+*              the same partition.
+*
+* SEE ALSO
+*      MCM Port Object
+*********/
+
+/****f* OpenSM: MCM Port Object/osm_mcm_port_construct
+* NAME
+*      osm_mcm_port_construct
+*
+* DESCRIPTION
+*      This function constructs a MCM Port object.
+*
+* SYNOPSIS
+*/
+void
+osm_mcm_port_construct(
+       IN osm_mcm_port_t* const p_mcm );
+/*
+* PARAMETERS
+*      p_mcm
+*              [in] Pointer to a MCM Port Object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_mcm_port_init, osm_mcm_port_destroy.
+*
+*      Calling osm_mcm_port_construct is a prerequisite to calling any other
+*      method except osm_mcm_port_init.
+*
+* SEE ALSO
+*      MCM Port Object, osm_mcm_port_init, osm_mcm_port_destroy
+*********/
+
+/****f* OpenSM: MCM Port Object/osm_mcm_port_destroy
+* NAME
+*      osm_mcm_port_destroy
+*
+* DESCRIPTION
+*      The osm_mcm_port_destroy function destroys a MCM Port Object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mcm_port_destroy(
+       IN osm_mcm_port_t* const p_mcm );
+/*
+* PARAMETERS
+*      p_mcm
+*              [in] Pointer to a MCM Port Object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified MCM Port Object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_mcm_port_construct or osm_mcm_port_init.
+*
+* SEE ALSO
+*      MCM Port Object, osm_mcm_port_construct, osm_mcm_port_init
+*********/
+
+/****f* OpenSM: MCM Port Object/osm_mcm_port_init
+* NAME
+*      osm_mcm_port_init
+*
+* DESCRIPTION
+*      The osm_mcm_port_init function initializes a MCM Port Object for use.
+*
+* SYNOPSIS
+*/
+void
+osm_mcm_port_init(
+       IN osm_mcm_port_t* const p_mcm,
+       IN const ib_gid_t* const p_port_gid,
+       IN const uint8_t   scope_state,
+   IN const boolean_t proxy_join );
+/*
+* PARAMETERS
+*      p_mcm
+*              [in] Pointer to an osm_mcm_port_t object to initialize.
+*
+*      p_port_gid
+*              [in] Pointer to the GID of the port to add to the multicast group.
+*
+*      scope_state
+*              [in] scope state of the join request
+*
+*  proxy_join
+*     [in] proxy_join state analyzed from the request
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*      Allows calling other MCM Port Object methods.
+*
+* SEE ALSO
+*      MCM Port Object, osm_mcm_port_construct, osm_mcm_port_destroy,
+*********/
+
+/****f* OpenSM: MCM Port Object/osm_mcm_port_init
+* NAME
+*      osm_mcm_port_init
+*
+* DESCRIPTION
+*      The osm_mcm_port_init function initializes a MCM Port Object for use.
+*
+* SYNOPSIS
+*/
+osm_mcm_port_t*
+osm_mcm_port_new(
+       IN const ib_gid_t* const p_port_gid,
+       IN const uint8_t   scope_state,
+   IN const boolean_t proxy_join );
+/*
+* PARAMETERS
+*      p_port_gid
+*              [in] Pointer to the GID of the port to add to the multicast group.
+*
+*      scope_state
+*              [in] scope state of the join request
+*
+*  proxy_join
+*     [in] proxy_join state analyzed from the request
+*
+* RETURN VALUES
+*      Pointer to the allocated and initialized MCM Port object.
+*
+* NOTES
+*
+* SEE ALSO
+*      MCM Port Object, osm_mcm_port_construct, osm_mcm_port_destroy,
+*********/
+
+/****f* OpenSM: MCM Port Object/osm_mcm_port_destroy
+* NAME
+*      osm_mcm_port_destroy
+*
+* DESCRIPTION
+*      The osm_mcm_port_destroy function destroys and dellallocates an
+*      MCM Port Object, releasing all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mcm_port_delete(
+       IN osm_mcm_port_t* const p_mcm );
+/*
+* PARAMETERS
+*      p_mcm
+*              [in] Pointer to a MCM Port Object to delete.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+*      MCM Port Object, osm_mcm_port_construct, osm_mcm_port_init
+*********/
+
+END_C_DECLS
+
+#endif         /* _OSM_MCM_PORT_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_msgdef.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_msgdef.h
new file mode 100644 (file)
index 0000000..efd672d
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_msgdef.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of Dispatcher message values.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#ifndef _OSM_MSGDEF_H_
+#define _OSM_MSGDEF_H_
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Dispatcher Messages
+* NAME
+*      Dispatcher Messages
+*
+* DESCRIPTION
+*      These constants define the messages sent between OpenSM controllers
+*      attached to the Dispatcher.
+*
+*      Each message description contains the following information:
+*      Sent by: which controller(s) send this message
+*      Received by: which controller receives this message
+*      Delivery notice: Indicates if the sender requires confirmation
+*              that the message has been delivered.  Typically a "yes" here
+*              means that some resources associated with sending the
+*              message must be freed.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Dispatcher Messages/OSM_MSG_REQ
+* NAME
+*      OSM_MSG_REQ
+*
+* DESCRIPTION
+*      Initiates a QP0 attribute request.
+*
+* NOTES
+*      Sent by:                        osm_sm_t
+*      Received by:                    osm_req_ctrl_t
+*      Delivery notice:                yes
+* 
+***********/
+
+/****s* OpenSM: Dispatcher Messages/OSM_MSG_MAD_NODE_INFO
+* NAME
+*      OSM_MSG_MAD_NODE_INFO
+*
+* DESCRIPTION
+*      Message for received NodeInfo MADs.
+*
+* NOTES
+*      Sent by:                        osm_mad_ctrl_t
+*      Received by:                    osm_ni_rcv_ctrl_t
+*      Delivery notice:                yes
+* 
+*
+***********/
+
+/****s* OpenSM: Dispatcher Messages/OSM_MSG_MAD_PORT_INFO
+* NAME
+*      OSM_MSG_MAD_PORT_INFO
+*
+* DESCRIPTION
+*      Message for received PortInfo MADs.
+*
+* NOTES
+*      Sent by:                        osm_mad_ctrl_t
+*      Received by:                    osm_pi_rcv_ctrl_t
+*      Delivery notice:                yes
+* 
+*
+***********/
+
+/****s* OpenSM: Dispatcher Messages/OSM_MSG_MAD_SWITCH_INFO
+* NAME
+*      OSM_MSG_MAD_SWITCH_INFO
+*
+* DESCRIPTION
+*      Message for received SwitchInfo MADs.
+*
+* NOTES
+*      Sent by:                        osm_mad_ctrl_t
+*      Received by:                    osm_si_rcv_ctrl_t
+*      Delivery notice:                yes
+* 
+***********/
+
+/****s* OpenSM: Dispatcher Messages/OSM_MSG_MAD_NODE_DESC
+* NAME
+*      OSM_MSG_MAD_NODE_DESC
+*
+* DESCRIPTION
+*      Message for received NodeDescription MADs.
+*
+* NOTES
+*      Sent by:                        osm_mad_ctrl_t
+*      Received by:                    osm_nd_rcv_ctrl_t
+*      Delivery notice:                yes
+* 
+* SOURCE
+***********/
+
+/****d* OpenSM: Dispatcher Messages/OSM_MSG_NO_SMPS_OUTSTANDING
+* NAME
+*   OSM_MSG_NO_SMPS_OUTSTANDING
+*
+* DESCRIPTION
+*   Message indicating that there are no outstanding SMPs on the subnet.
+*
+* NOTES
+*   Sent by:                osm_mad_ctrl_t
+*   Received by:            osm_state_mgr_ctrl_t
+*   Delivery notice:        no
+*
+* SOURCE
+***********/
+enum
+{
+       OSM_MSG_REQ = 0,
+       OSM_MSG_MAD_NODE_INFO,
+       OSM_MSG_MAD_PORT_INFO,  
+       OSM_MSG_MAD_SWITCH_INFO,
+       OSM_MSG_MAD_NODE_DESC,
+       OSM_MSG_NO_SMPS_OUTSTANDING,
+       OSM_MSG_MAD_NODE_RECORD,
+       OSM_MSG_MAD_PORTINFO_RECORD,
+       OSM_MSG_MAD_SERVICE_RECORD,
+       OSM_MSG_MAD_PATH_RECORD,
+       OSM_MSG_MAD_MCMEMBER_RECORD,
+       OSM_MSG_MAD_LINK_RECORD,
+       OSM_MSG_MAD_SMINFO_RECORD,
+       OSM_MSG_MAD_CLASS_PORT_INFO,
+       OSM_MSG_MAD_INFORM_INFO,
+       OSM_MSG_MAD_LFT_RECORD,
+       OSM_MSG_MAD_LFT,
+       OSM_MSG_MAD_SM_INFO,
+       OSM_MSG_MAD_NOTICE,
+       OSM_MSG_LIGHT_SWEEP_FAIL,
+       OSM_MSG_MAD_MFT,
+       OSM_MSG_MAD_PKEY_TBL_RECORD,
+       OSM_MSG_MAD_VL_ARB_RECORD,
+       OSM_MSG_MAD_SLVL_TBL_RECORD,
+       OSM_MSG_MAD_PKEY,
+       OSM_MSG_MAD_VL_ARB,
+       OSM_MSG_MAD_SLVL,
+       OSM_MSG_MAD_GUIDINFO_RECORD,
+       OSM_MSG_MAD_INFORM_INFO_RECORD,
+       OSM_MSG_MAD_SWITCH_INFO_RECORD,
+       OSM_MSG_MAD_MFT_RECORD,
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+       OSM_MSG_MAD_MULTIPATH_RECORD,
+#endif
+       OSM_MSG_MAX
+};
+
+END_C_DECLS
+
+#endif /* _OSM_MSGDEF_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mtl_bind.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mtl_bind.h
new file mode 100644 (file)
index 0000000..021b22a
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_mtl_bind.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_BIND_H_
+#define _OSM_BIND_H_
+
+#include <opensm/osm_helper.h>
+#include <vendor/osm_vendor_mtl.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_opensm.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****s* OpenSM: Vendor/osm_vendor_mgt_bind
+* NAME
+*   osm_vendor_mgt_bind_t
+*
+* DESCRIPTION
+*      Tracks the handles returned by IB_MGT to the SMI and GSI
+*  Nulled on init of the vendor obj. Populated on first bind.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_vendor_mgt_bind
+{
+  boolean_t smi_init, gsi_init;
+  IB_MGT_mad_hndl_t smi_mads_hdl;
+  IB_MGT_mad_hndl_t gsi_mads_hdl;
+  struct _osm_mtl_bind_info *smi_p_bind;
+}
+osm_vendor_mgt_bind_t;
+
+/*
+* FIELDS
+*      smi_mads_hdl
+*              Handle returned by IB_MGT_get_handle to the IB_MGT_SMI
+*
+*      gsi_mads_hdl
+*              Handle returned by IB_MGT_get_handle to the IB_MGT_GSI
+*
+* SEE ALSO
+*********/
+
+/****s* OpenSM: Vendor osm_mtl_bind_info_t
+* NAME
+*   osm_mtl_bind_info_t
+*
+* DESCRIPTION
+*      Handle to the result of binding a class callbacks to IB_MGT.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mtl_bind_info
+{
+  IB_MGT_mad_hndl_t mad_hndl;
+  osm_vendor_t *p_vend;
+  void *client_context;
+  VAPI_hca_hndl_t hca_hndl;
+  VAPI_hca_id_t hca_id;
+  uint8_t port_num;
+  osm_vend_mad_recv_callback_t rcv_callback;
+  osm_vend_mad_send_err_callback_t send_err_callback;
+  osm_mad_pool_t *p_osm_pool;
+}
+osm_mtl_bind_info_t;
+
+/*
+* FIELDS
+*      mad_hndl
+*              the handle returned from the registration in IB_MGT
+*
+*      p_vend
+*              Pointer to the vendor object.
+*
+*      client_context
+*              User's context passed during osm_bind
+*
+*  hca_id
+*     HCA Id we bind to.
+*
+*      port_num
+*              Port number (within the HCA) of the bound port.
+*
+*      rcv_callback
+*              OSM Callback function to be called on receive of MAD.
+*
+*  send_err_callback
+*     OSM Callback to be called on send error.
+*
+*  p_osm_pool
+*     Points to the MAD pool used by OSM 
+*
+*
+* SEE ALSO
+*********/
+ib_api_status_t
+osm_mtl_send_mad(
+  IN osm_mtl_bind_info_t *p_bind,
+  IN osm_madw_t * const p_madw);
+
+END_C_DECLS
+
+#endif // _OSM_BIND_H_
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mtree.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_mtree.h
new file mode 100644 (file)
index 0000000..8365a97
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_mtree.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_mtree_t.
+ *     This object represents multicast spanning tree.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_MTREE_H_
+#define _OSM_MTREE_H_
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_switch.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+#define OSM_MTREE_LEAF ((void*)-1)
+
+/****h* OpenSM/Multicast Tree
+* NAME
+*      Multicast Tree
+*
+* DESCRIPTION
+*      The Multicast Tree object encapsulates the information needed by the
+*      OpenSM to manage multicast fabric routes.  It is a tree structure
+*      in which each node in the tree represents a switch, and may have a
+*      varying number of children.
+*
+*      Multicast trees do not contain loops.
+*
+*      The Multicast Tree is not thread safe, thus callers must provide
+*      serialization.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Multicast Tree/osm_mtree_node_t
+* NAME
+*      osm_mtree_node_t
+*
+* DESCRIPTION
+*      The MTree Node object encapsulates the information needed by the
+*      OpenSM for a particular switch in the multicast tree.
+*
+*      The MTree Node object is not thread safe, thus callers must provide
+*      serialization.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mtree_node
+{
+       cl_map_item_t           map_item;
+       osm_switch_t            *p_sw;
+       uint8_t                 max_children;
+       struct _osm_mtree_node  *p_up;
+       struct _osm_mtree_node  *child_array[1];
+} osm_mtree_node_t;
+/*
+* FIELDS
+*      map_item
+*              Linkage for quick map.  MUST BE FIRST ELEMENT!!!
+*
+*      p_sw
+*              Pointer to the switch represented by this tree node.
+*
+*      max_children
+*              Maximum number of child nodes of this node.  Equal to the
+*              the number of ports on the switch if the switch supports
+*              multicast.  Equal to 1 (default route) if the switch does
+*              not support multicast.
+*
+*      p_up
+*              Pointer to the parent of this node.  If this pointer is
+*              NULL, the node is at the root of the tree.
+*
+*      child_array
+*              Array (indexed by port number) of pointers to the
+*              child osm_mtree_node_t objects of this tree node, if any.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Tree/osm_mtree_node_construct
+* NAME
+*      osm_mtree_node_construct
+*
+* DESCRIPTION
+*      This function constructs a Multicast Tree Node object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_mtree_node_construct(
+       IN osm_mtree_node_t* const p_mtn )
+{
+       memset( p_mtn, 0, sizeof(*p_mtn) );
+}
+/*
+* PARAMETERS
+*      p_mtn
+*              [in] Pointer to a Multicast Tree Node object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Tree/osm_mtree_node_destroy
+* NAME
+*      osm_mtree_node_destroy
+*
+* DESCRIPTION
+*      The osm_mtree_node_destroy function destroys a node, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mtree_node_destroy(
+       IN osm_mtree_node_t* const p_mtn );
+/*
+* PARAMETERS
+*      p_mtn
+*              [in] Pointer to a Multicast Tree Node object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified Multicast Tree object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to osm_mtree_construct or
+*      osm_mtree_init.
+*
+* SEE ALSO
+*      Multicast Tree object, osm_mtree_construct, osm_mtree_init
+*********/
+
+/****f* OpenSM: Multicast Tree/osm_mtree_node_init
+* NAME
+*      osm_mtree_node_init
+*
+* DESCRIPTION
+*      Initializes a Multicast Tree Node object for use.
+*
+* SYNOPSIS
+*/
+void
+osm_mtree_node_init(
+       IN osm_mtree_node_t* const p_mtn,
+       IN const osm_switch_t* const p_sw );
+/*
+* PARAMETERS
+*      p_mtn
+*              [in] Pointer to an osm_mtree_node_t object to initialize.
+*
+*      p_sw
+*              [in] Pointer to the switch represented by this node.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Tree/osm_mtree_node_new
+* NAME
+*      osm_mtree_node_new
+*
+* DESCRIPTION
+*      Returns an initialized a Multicast Tree object for use.
+*
+* SYNOPSIS
+*/
+osm_mtree_node_t*
+osm_mtree_node_new(
+       IN const osm_switch_t* const p_sw );
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to the switch represented by this node.
+*
+* RETURN VALUES
+*      Pointer to an initialized tree node.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Tree/osm_mtree_destroy
+* NAME
+*      osm_mtree_destroy
+*
+* DESCRIPTION
+*      Destroys a Multicast Tree object given by the p_mtn
+*
+* SYNOPSIS
+*/
+void
+osm_mtree_destroy(
+  IN osm_mtree_node_t *p_mtn );
+/*
+* PARAMETERS
+*      p_mtn
+*              [in] Pointer to an osm_mtree_node_t object to destroy.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Tree/osm_mtree_node_get_max_children
+* NAME
+*      osm_mtree_node_get_max_children
+*
+* DESCRIPTION
+*      Returns the number maximum number of children of this node.
+*      The return value is 1 greater than the highest valid port
+*      number on the switch.
+*
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_mtree_node_get_max_children(
+       IN const osm_mtree_node_t* const p_mtn )
+{
+       return( p_mtn->max_children );
+}
+/*
+* PARAMETERS
+*      p_mtn
+*              [in] Pointer to the multicast tree node.
+*
+* RETURN VALUES
+*      See description.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Tree/osm_mtree_node_get_child
+* NAME
+*      osm_mtree_node_get_child
+*
+* DESCRIPTION
+*      Returns the specified child node of this node.
+*
+* SYNOPSIS
+*/
+static inline osm_mtree_node_t*
+osm_mtree_node_get_child(
+       IN const osm_mtree_node_t* const p_mtn,
+       IN const uint8_t child )
+{
+       CL_ASSERT( child < p_mtn->max_children );
+       return( p_mtn->child_array[child] );
+}
+/*
+* PARAMETERS
+*      p_mtn
+*              [in] Pointer to the multicast tree node.
+*
+*      child
+*              [in] Index of the child to retrieve.
+*
+* RETURN VALUES
+*      Returns the specified child node of this node.
+*      
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Tree/osm_mtree_node_get_switch_ptr
+* NAME
+*      osm_mtree_node_get_switch_ptr
+*
+* DESCRIPTION
+*      Returns a pointer to the switch object represented by this tree node.
+*
+* SYNOPSIS
+*/
+static inline osm_switch_t*
+osm_mtree_node_get_switch_ptr(
+       IN const osm_mtree_node_t* const p_mtn )
+{
+       return( p_mtn->p_sw );
+}
+/*
+* PARAMETERS
+*      p_mtn
+*              [in] Pointer to the multicast tree node.
+*
+*      child
+*              [in] Index of the child to retrieve.
+*
+* RETURN VALUES
+*      Returns a pointer to the switch object represented by this tree node.
+*      
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif         /* _OSM_MTREE_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_multicast.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_multicast.h
new file mode 100644 (file)
index 0000000..90a3b57
--- /dev/null
@@ -0,0 +1,769 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_multicast.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_mgrp_t.
+ *     This object represents an IBA Multicast Group.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_MULTICAST_H_
+#define _OSM_MULTICAST_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_spinlock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_mtree.h>
+#include <opensm/osm_mcm_port.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Multicast Group
+* NAME
+*      Multicast Group
+*
+* DESCRIPTION
+*      The Multicast Group encapsulates the information needed by the
+*      OpenSM to manage Multicast Groups.  The OpenSM allocates one
+*      Multicast Group object per Multicast Group in the IBA subnet.
+*
+*      The Multicast Group is not thread safe, thus callers must provide
+*      serialization.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****f* IBA Base: OpneSM: Multicast Group/osm_get_mcast_req_type_str
+* NAME
+*      osm_get_mcast_req_type_str
+*
+* DESCRIPTION
+*      Returns a string for the specified osm_mcast_req_type_t value.
+*
+* SYNOPSIS
+*/
+const char*
+osm_get_mcast_req_type_str(
+  IN osm_mcast_req_type_t  req_type );
+/*
+* PARAMETERS
+*      req_type
+*              [in] osm_mcast_req_type value
+*
+* RETURN VALUES
+*      Pointer to the request type description string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****s* OpenSM: Multicast Group/osm_mcast_mgr_ctxt_t
+* NAME
+*      osm_mcast_mgr_ctxt_t
+*
+* DESCRIPTION
+*      Struct for passing context arguments to the multicast manager.
+*
+*      The osm_mcast_mgr_ctxt_t object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct osm_mcast_mgr_ctxt
+{
+  ib_net16_t                                           mlid;
+  osm_mcast_req_type_t        req_type;
+  ib_net64_t                  port_guid;
+} osm_mcast_mgr_ctxt_t;
+/*
+* FIELDS
+*
+*      mlid
+*              The network ordered LID of this Multicast Group (must be >= 0xC000).
+*
+*      req_type
+*              The type of the request that caused this call
+*     (multicast create/join/leave).
+*
+*      port_guid
+*              The port guid of the port that is being added/removed from
+*     the multicast group due to this call.
+*
+* SEE ALSO
+*********/
+
+/****s* OpenSM: Multicast Group/osm_mgrp_t
+* NAME
+*      osm_mgrp_t
+*
+* DESCRIPTION
+*      Multicast Group structure.
+*
+*      The osm_mgrp_t object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mgrp
+{
+       cl_map_item_t           map_item;
+       ib_net16_t              mlid;
+       osm_mtree_node_t        *p_root;
+       cl_qmap_t               mcm_port_tbl;
+       ib_member_rec_t         mcmember_rec;
+       boolean_t               well_known;
+       boolean_t               to_be_deleted;
+       uint32_t                last_change_id;
+       uint32_t                last_tree_id;
+} osm_mgrp_t;
+/*
+* FIELDS
+*      map_item
+*              Map Item for qmap linkage.  Must be first element!!
+*
+*      mlid
+*              The network ordered LID of this Multicast Group (must be
+*              >= 0xC000).
+*
+*      p_root
+*              Pointer to the root "tree node" in the single spanning tree
+*              for this multicast group.  The nodes of the tree represent
+*              switches.  Member ports are not represented in the tree.
+*
+*      mcm_port_tbl
+*              Table (sorted by port GUID) of osm_mcm_port_t objects
+*              representing the member ports of this multicast group.
+*
+*      mcmember_rec
+*              Hold the parameters of the Multicast Group.
+*
+*      well_known
+*              Indicates that this is the wellknow multicast group which
+*              is created during the initialization of SM/SA and will be
+*              present even if there are no ports for this group
+*
+*      to_be_deleted
+*              Since groups are deleted only after re-route we need to
+*              track the fact the group is about to be deleted so we can
+*              track the fact a new join is actually a create request.
+*
+*      last_change_id
+*              a counter for the number of changes applied to the group.
+*              This counter shuold be incremented on any modification
+*              to the group: joining or leaving of ports.
+*
+*      last_tree_id
+*              the last change id used for building the current tree.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Vendor API/osm_mgrp_func_t
+* NAME
+*      osm_mgrp_func_t
+*
+* DESCRIPTION
+*      Callback for the osm_mgrp_apply_func function.
+*      The callback function must not modify the tree linkage.
+*
+* SYNOPSIS
+*/
+typedef        void (*osm_mgrp_func_t)(
+       IN const osm_mgrp_t* const p_mgrp,
+       IN const osm_mtree_node_t* const p_mtn,
+       IN void* context );
+/*
+* PARAMETERS
+*      p_mgrp
+*              [in] Pointer to the multicast group object.
+*
+*      p_mtn
+*              [in] Pointer to the multicast tree node.
+*
+*      context
+*              [in] User context.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_construct
+* NAME
+*      osm_mgrp_construct
+*
+* DESCRIPTION
+*      This function constructs a Multicast Group.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_construct(
+       IN osm_mgrp_t* const p_mgrp );
+/*
+* PARAMETERS
+*      p_mgrp
+*              [in] Pointer to a Multicast Group to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_mgrp_init, osm_mgrp_destroy.
+*
+*      Calling osm_mgrp_construct is a prerequisite to calling any other
+*      method except osm_mgrp_init.
+*
+* SEE ALSO
+*      Multicast Group, osm_mgrp_init, osm_mgrp_destroy
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_destroy
+* NAME
+*      osm_mgrp_destroy
+*
+* DESCRIPTION
+*      The osm_mgrp_destroy function destroys a Multicast Group, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_destroy(
+       IN osm_mgrp_t* const p_mgrp );
+/*
+* PARAMETERS
+*      p_mgrp
+*              [in] Pointer to a Muticast Group to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified Multicast Group.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to osm_mgrp_construct or
+*      osm_mgrp_init.
+*
+* SEE ALSO
+*      Multicast Group, osm_mgrp_construct, osm_mgrp_init
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_init
+* NAME
+*      osm_mgrp_init
+*
+* DESCRIPTION
+*      The osm_mgrp_init function initializes a Multicast Group for use.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_init(
+       IN osm_mgrp_t* const p_mgrp,
+       IN const ib_net16_t mlid );
+/*
+* PARAMETERS
+*      p_mgrp
+*              [in] Pointer to an osm_mgrp_t object to initialize.
+*
+*      mlid
+*              [in] Multicast LID for this multicast group.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*      Allows calling other Multicast Group methods.
+*
+* SEE ALSO
+*      Multicast Group, osm_mgrp_construct, osm_mgrp_destroy,
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_new
+* NAME
+*      osm_mgrp_new
+*
+* DESCRIPTION
+*      Allocates and initializes a Multicast Group for use.
+*
+* SYNOPSIS
+*/
+osm_mgrp_t*
+osm_mgrp_new(
+       IN const ib_net16_t mlid );
+/*
+* PARAMETERS
+*      mlid
+*              [in] Multicast LID for this multicast group.
+*
+* RETURN VALUES
+*      IB_SUCCESS if initialization was successful.
+*
+* NOTES
+*      Allows calling other Multicast Group methods.
+*
+* SEE ALSO
+*      Multicast Group, osm_mgrp_construct, osm_mgrp_destroy,
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_delete
+* NAME
+*      osm_mgrp_delete
+*
+* DESCRIPTION
+*      Destroys and de-allocates a Multicast Group.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_delete(
+       IN osm_mgrp_t* const p_mgrp );
+/*
+* PARAMETERS
+*      p_mgrp
+*              [in] Pointer to an osm_mgrp_t object.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      Multicast Group, osm_mgrp_construct, osm_mgrp_destroy,
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_is_guid
+* NAME
+*      osm_mgrp_is_guid
+*
+* DESCRIPTION
+*      Indicates if the specified port GUID is a member of the Multicast Group.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_mgrp_is_guid(
+       IN const osm_mgrp_t* const p_mgrp,
+       IN const ib_net64_t port_guid )
+{
+       return( cl_qmap_get( &p_mgrp->mcm_port_tbl, port_guid ) !=
+                       cl_qmap_end( &p_mgrp->mcm_port_tbl ) );
+}
+/*
+* PARAMETERS
+*      p_mgrp
+*              [in] Pointer to an osm_mgrp_t object.
+*
+*      port_guid
+*              [in] Port GUID.
+*
+* RETURN VALUES
+*      TRUE if the port GUID is a member of the group,
+*      FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*      Multicast Group
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_is_empty
+* NAME
+*      osm_mgrp_is_empty
+*
+* DESCRIPTION
+*      Indicates if the multicast group has any member ports.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_mgrp_is_empty(
+       IN const osm_mgrp_t* const p_mgrp )
+{
+       return( cl_qmap_count( &p_mgrp->mcm_port_tbl ) == 0 );
+}
+/*
+* PARAMETERS
+*      p_mgrp
+*              [in] Pointer to an osm_mgrp_t object.
+*
+* RETURN VALUES
+*      TRUE if there are no ports in the multicast group.
+*      FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*      Multicast Group
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_get_mlid
+* NAME
+*      osm_mgrp_get_mlid
+*
+* DESCRIPTION
+*      The osm_mgrp_get_mlid function returns the multicast LID of this group.
+*
+* SYNOPSIS
+*/
+static inline ib_net16_t
+osm_mgrp_get_mlid(
+       IN const osm_mgrp_t* const p_mgrp )
+{
+       return( p_mgrp->mlid );
+}
+/*
+* PARAMETERS
+*      p_mgrp
+*              [in] Pointer to an osm_mgrp_t object.
+*
+* RETURN VALUES
+*      MLID of the Multicast Group.
+*
+* NOTES
+*
+* SEE ALSO
+*      Multicast Group
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_add_port
+* NAME
+*      osm_mgrp_add_port
+*
+* DESCRIPTION
+*      Adds a port to the multicast group.
+*
+* SYNOPSIS
+*/
+osm_mcm_port_t*
+osm_mgrp_add_port(
+       IN osm_mgrp_t* const p_mgrp,
+       IN const ib_gid_t* const p_port_gid,
+       IN const uint8_t join_state,
+   IN boolean_t     proxy_join);
+/*
+* PARAMETERS
+*      p_mgrp
+*              [in] Pointer to an osm_mgrp_t object to initialize.
+*
+*      p_port_gid
+*              [in] Pointer to the GID of the port to add to the multicast group.
+*
+*      join_state
+*              [in] The join state for this port in the group.
+*
+* RETURN VALUES
+*      IB_SUCCESS
+*      IB_INSUFFICIENT_MEMORY
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_is_port_present
+* NAME
+*      osm_mgrp_is_port_present
+*
+* DESCRIPTION
+*      checks a port from the multicast group.
+*
+* SYNOPSIS
+*/
+
+boolean_t
+osm_mgrp_is_port_present(
+       IN const osm_mgrp_t* const p_mgrp,
+       IN const ib_net64_t port_guid,
+       OUT osm_mcm_port_t ** const pp_mcm_port);
+/*
+* PARAMETERS
+*      p_mgrp
+*              [in] Pointer to an osm_mgrp_t object.
+*
+*      port_guid
+*              [in] Port guid of the departing port.
+*
+*  pp_mcm_port
+*     [out] Pointer to a pointer to osm_mcm_port_t
+*           Updated to the member on success or NULLed
+*
+* RETURN VALUES
+*      TRUE if port present
+*      FALSE if port is not present.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_remove_port
+* NAME
+*      osm_mgrp_remove_port
+*
+* DESCRIPTION
+*      Removes a port from the multicast group.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_remove_port(
+       IN osm_subn_t* const p_subn,
+   IN osm_log_t* const p_log,
+       IN osm_mgrp_t* const p_mgrp,
+       IN const ib_net64_t port_guid );
+/*
+* PARAMETERS
+*
+*  p_subn
+*     [in] Pointer to the subnet object
+*
+*  p_log 
+*     [in] The log object pointer
+*
+*      p_mgrp
+*              [in] Pointer to an osm_mgrp_t object.
+*
+*      port_guid
+*              [in] Port guid of the departing port.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_get_root_switch
+* NAME
+*      osm_mgrp_get_root_switch
+*
+* DESCRIPTION
+*      Returns the "root" switch of this multicast group.  The root switch
+*      is at the trunk of the multicast single spanning tree.
+*
+* SYNOPSIS
+*/
+static inline osm_switch_t*
+osm_mgrp_get_root_switch(
+       IN const osm_mgrp_t* const p_mgrp )
+{
+       if( p_mgrp->p_root )
+               return( p_mgrp->p_root->p_sw );
+       else
+               return( NULL );
+}
+/*
+* PARAMETERS
+*      p_mgrp
+*              [in] Pointer to an osm_mgrp_t object.
+*
+* RETURN VALUES
+*      Returns the "root" switch of this multicast group.  The root switch
+*      is at the trunk of the multicast single spanning tree.
+*
+* NOTES
+*
+* SEE ALSO
+*      Multicast Group
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_compute_avg_hops
+* NAME
+*      osm_mgrp_compute_avg_hops
+*
+* DESCRIPTION
+*      Returns the average number of hops from the given to switch
+*      to all member of a multicast group.
+*
+* SYNOPSIS
+*/
+float
+osm_mgrp_compute_avg_hops(
+       const osm_mgrp_t* const p_mgrp,
+       const osm_switch_t* const p_sw );
+/*
+* PARAMETERS
+*      p_mgrp
+*              [in] Pointer to an osm_mgrp_t object.
+*
+*      p_sw
+*              [in] Pointer to the switch from which to measure.
+*
+* RETURN VALUES
+*      Returns the average number of hops from the given to switch
+*      to all member of a multicast group.
+*
+* NOTES
+*
+* SEE ALSO
+*      Multicast Group
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_apply_func
+* NAME
+*      osm_mgrp_apply_func
+*
+* DESCRIPTION
+*      Calls the specified function for each element in the tree.
+*      Elements are passed to the callback function in no particular order.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_apply_func(
+       const osm_mgrp_t* const p_mgrp,
+       osm_mgrp_func_t p_func,
+       void* context );
+/*
+* PARAMETERS
+*      p_mgrp
+*              [in] Pointer to an osm_mgrp_t object.
+*
+*      p_func
+*              [in] Pointer to the users callback function.
+*
+*      context
+*              [in] User context passed to the callback function.
+*
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      Multicast Group
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_send_delete_notice
+* NAME
+*      osm_mgrp_send_delete_notice
+*
+* DESCRIPTION
+*      Sends a notice that the given multicast group is now deleted.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_send_delete_notice(
+       IN osm_subn_t* const p_subn,
+   IN osm_log_t* const p_log,
+   IN osm_mgrp_t *p_mgrp );
+/*
+* PARAMETERS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_mgrp
+*              [in] Pointer to an osm_mgrp_t object.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      Multicast Group
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_send_create_notice
+* NAME
+*      osm_mgrp_send_create_notice
+*
+* DESCRIPTION
+*      Sends a notice that the given multicast group is now created.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_send_create_notice(
+       IN osm_subn_t* const p_subn,
+   IN osm_log_t* const p_log,
+   IN osm_mgrp_t *p_mgrp );
+/*
+* PARAMETERS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_mgrp
+*              [in] Pointer to an osm_mgrp_t object.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      Multicast Group
+*********/
+
+END_C_DECLS
+
+#endif         /* _OSM_MULTICAST_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node.h
new file mode 100644 (file)
index 0000000..1bcc0f9
--- /dev/null
@@ -0,0 +1,957 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_node.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_node_t.
+ *     This object represents an IBA node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_NODE_H_
+#define _OSM_NODE_H_
+
+#include <complib/cl_qmap.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_path.h>
+#include <opensm/osm_madw.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+struct _osm_switch;
+
+/****h* OpenSM/Node
+* NAME
+*      Node
+*
+* DESCRIPTION
+*      The Node object encapsulates the information needed by the
+*      OpenSM to manage nodes.  The OpenSM allocates one Node object
+*      per node in the IBA subnet.
+*
+*      The Node object is not thread safe, thus callers must provide
+*      serialization.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Node/osm_node_t
+* NAME
+*      osm_node_t
+*
+* DESCRIPTION
+*      Node structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_node
+{
+       cl_map_item_t   map_item;
+       struct _osm_switch *sw;
+       ib_node_info_t  node_info;
+       ib_node_desc_t  node_desc;
+       uint32_t        discovery_count;
+       uint32_t        physp_tbl_size;
+       osm_physp_t     physp_table[1];
+} osm_node_t;
+/*
+* FIELDS
+*      map_item
+*              Linkage structure for cl_qmap.  MUST BE FIRST MEMBER!
+*
+*      sw
+*              For switch node contains pointer to appropriate osm_switch
+*              structure. NULL for non-switch nodes. Can be used for fast
+*              access to switch object and for simple node type detection
+*
+*      node_info
+*              The IBA defined NodeInfo data for this node.
+*
+*      node_desc
+*              The IBA defined NodeDescription data for this node.
+*
+*      discovery_count
+*              The number of times this node has been discovered
+*              during the current fabric sweep.  This number is reset
+*              to zero at the start of a sweep.
+*
+*      phsyp_tbl_size
+*              The size of the physp_table array.  This value is one greater
+*              than the number of ports in the node, since port numbers
+*              start with 1 for some bizzare reason.
+*
+*      phsyp_table
+*              Array of physical port objects belonging to this node.
+*              Index is contiguous by local port number.
+*              For switches, port 0 is the always the management port (14.2.5.6).
+*              MUST BE LAST MEMBER! - Since it grows !!!!
+*
+* SEE ALSO
+*      Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_destroy
+* NAME
+*      osm_node_destroy
+*
+* DESCRIPTION
+*      The osm_node_destroy function destroys a node, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/void
+osm_node_destroy(
+  IN osm_node_t *p_node );
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer a Node object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified Node object.
+*      This function should only be called after a call to osm_node_new.
+*
+* SEE ALSO
+*      Node object, osm_node_new
+*********/
+
+/****f* OpenSM: Node/osm_node_delete
+* NAME
+*      osm_node_delete
+*
+* DESCRIPTION
+*      The osm_node_delete function destroys a node, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_node_delete(
+       IN OUT osm_node_t** const p_node );
+/*
+* PARAMETERS
+*      p_node
+*              [in][out] Pointer to a Pointer a Node object to destroy.
+*              On return, the pointer to set to NULL.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified Node object.
+*      This function should only be called after a call to osm_node_new.
+*
+* SEE ALSO
+*      Node object, osm_node_new
+*********/
+
+/****f* OpenSM: Node/osm_node_new
+* NAME
+*      osm_node_new
+*
+* DESCRIPTION
+*      The osm_node_new function initializes a Node object for use.
+*
+* SYNOPSIS
+*/
+osm_node_t*
+osm_node_new(
+       IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_madw
+*              [in] Pointer to a osm_madw_t object containing a mad with
+*              the node's NodeInfo attribute.  The caller may discard the
+*              osm_madw_t structure after calling osm_node_new.
+*
+* RETURN VALUES
+*      On success, a pointer to the new initialized osm_node_t structure.
+*      NULL otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_is_lid
+* NAME
+*      osm_node_is_lid
+*
+* DESCRIPTION
+*      Indicates if the specified LID belongs to this node.
+*
+* SYNOPSIS
+*/
+boolean_t osm_node_is_lid(
+       IN const osm_node_t* const p_node,
+       IN const uint16_t lid );
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer to an osm_node_t object.
+*
+*      lid
+*              [in] LID value.
+*
+* RETURN VALUES
+*      TRUE if the specified LID belongs to the node,
+*      FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_get_physp_ptr
+* NAME
+*      osm_node_get_physp_ptr
+*
+* DESCRIPTION
+*      Returns a pointer to the physical port object at the
+*      specified local port number.
+*
+* SYNOPSIS
+*/
+static inline osm_physp_t*
+osm_node_get_physp_ptr(
+       IN const osm_node_t* const p_node,
+       IN const uint32_t port_num )
+{
+
+  CL_ASSERT( port_num < p_node->physp_tbl_size );
+  return( (osm_physp_t*)&p_node->physp_table[port_num] );
+}
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer to an osm_node_t object.
+*
+*      port_num
+*              [in] Local port number.
+*
+* RETURN VALUES
+*      Returns a pointer to the physical port object at the
+*      specified local port number.
+*      A return value of zero means the port number was out of range.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_get_any_physp_ptr
+* NAME
+*      osm_node_get_any_physp_ptr
+*
+* DESCRIPTION
+*      Returns a pointer to any valid physical port object associated
+*      with this node.  This operation is mostly meaningful for switches,
+*      in which case all the Physical Ports share the same GUID. 
+*
+* SYNOPSIS
+*/
+static inline osm_physp_t*
+osm_node_get_any_physp_ptr(
+       IN const osm_node_t* const p_node )
+{
+       CL_ASSERT( p_node );
+       return( (osm_physp_t*)&p_node->physp_table[
+                       ib_node_info_get_local_port_num( &p_node->node_info )] );
+}
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer to an osm_node_t object.
+*
+* RETURN VALUES
+*      Returns a pointer to any valid physical port object associated
+*      with this node.  This operation is mostly meaningful for switches,
+*      in which case all the Physical Ports share the same GUID. 
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_get_any_path
+* NAME
+*      osm_node_get_any_path
+*
+* DESCRIPTION
+*      Returns a pointer to the physical port object at the
+*      specified local port number.
+*
+* SYNOPSIS
+*/
+static inline osm_dr_path_t*
+osm_node_get_any_dr_path_ptr(
+       IN const osm_node_t* const p_node )
+{
+       CL_ASSERT( p_node );
+       return( osm_physp_get_dr_path_ptr( &p_node->physp_table[
+                       ib_node_info_get_local_port_num( &p_node->node_info )] ) );
+}
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer to an osm_node_t object.
+*
+*      port_num
+*              [in] Local port number.
+*
+* RETURN VALUES
+*      Returns a pointer to the physical port object at the
+*      specified local port number.
+*      A return value of zero means the port number was out of range.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_get_type
+* NAME
+*      osm_node_get_type
+*
+* DESCRIPTION
+*      Returns the type of this node.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_node_get_type(
+       IN const osm_node_t* const p_node )
+{
+       return( p_node->node_info.node_type );
+}
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer to an osm_node_t object.
+*
+* RETURN VALUES
+*      Returns the IBA defined type of this node.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_get_num_physp
+* NAME
+*      osm_node_get_num_physp
+*
+* DESCRIPTION
+*      Returns the type of this node.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_node_get_num_physp(
+       IN const osm_node_t* const p_node )
+{
+       return( (uint8_t)p_node->physp_tbl_size );
+}
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer to an osm_node_t object.
+*
+* RETURN VALUES
+*      Returns the IBA defined type of this node.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_get_remote_node
+* NAME
+*      osm_node_get_remote_node
+*
+* DESCRIPTION
+*      Returns a pointer to the node on the other end of the
+*      specified port.
+*      Returns NULL if no remote node exists.
+*
+* SYNOPSIS
+*/
+osm_node_t*
+osm_node_get_remote_node(
+       IN const osm_node_t* const p_node,
+       IN const uint8_t port_num,
+       OUT uint8_t *p_remote_port_num );
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer to an osm_node_t object.
+*
+*      port_num
+*              [in] Port number in p_node through which to get the remote node.
+*
+*      p_remote_port_num
+*              [out] Port number in the remote's node through which this
+*              link exists.  The caller may specify NULL for this pointer
+*              if the port number isn't needed.
+*
+* RETURN VALUES
+*      Returns a pointer to the node on the other end of the
+*      specified port.
+*      Returns NULL if no remote node exists.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_get_base_lid
+* NAME
+*      osm_node_get_base_lid
+*
+* DESCRIPTION
+*      Returns the LID value of the specified port on this node.
+*
+* SYNOPSIS
+*/
+static inline ib_net16_t
+osm_node_get_base_lid(
+       IN const osm_node_t* const p_node,
+       IN const uint32_t port_num )
+{
+       CL_ASSERT( port_num < p_node->physp_tbl_size );
+       return( osm_physp_get_base_lid( &p_node->physp_table[port_num] ) );
+}
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer to an osm_node_t object.
+*
+*      port_num
+*              [in] Local port number.
+*
+* RETURN VALUES
+*      Returns a pointer to the physical port object at the
+*      specified local port number.
+*      A return value of zero means the port number was out of range.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_get_remote_base_lid
+* NAME
+*      osm_node_get_remote_base_lid
+*
+* DESCRIPTION
+*      Returns the base LID value of the port on the other side
+*      of the wire from the specified port on this node.
+*
+* SYNOPSIS
+*/
+ib_net16_t
+osm_node_get_remote_base_lid(
+       IN const osm_node_t* const p_node,
+       IN const uint32_t port_num );
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer to an osm_node_t object.
+*
+*      port_num
+*              [in] Local port number.
+*
+* RETURN VALUES
+*      Returns a pointer to the physical port object at the
+*      specified local port number.
+*      A return value of zero means the port number was out of range.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_get_remote_type
+* NAME
+*      osm_node_get_remote_type
+*
+* DESCRIPTION
+*      Returns the type of the node on the other side
+*      of the wire from the specified port on this node.
+*      The remote node must exist.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_node_get_remote_type(
+       IN const osm_node_t* const p_node,
+       IN const uint8_t port_num )
+{
+       osm_node_t *p_remote_node;
+
+       p_remote_node = osm_node_get_remote_node( p_node, port_num, NULL );
+       CL_ASSERT( p_remote_node );
+       return( osm_node_get_type( p_remote_node ) );
+}
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer to an osm_node_t object.
+*
+*      port_num
+*              [in] Local port number.
+*
+* RETURN VALUES
+*      Returns the type of the node on the other side
+*      of the wire from the specified port on this node.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_get_lmc
+* NAME
+*      osm_node_get_lmc
+*
+* DESCRIPTION
+*      Returns the LMC value of the specified port on this node.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_node_get_lmc(
+       IN const osm_node_t* const p_node,
+       IN const uint32_t port_num )
+{
+       CL_ASSERT( port_num < p_node->physp_tbl_size );
+       return( osm_physp_get_lmc( &p_node->physp_table[port_num] ) );
+}
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer to an osm_node_t object.
+*
+*      port_num
+*              [in] Local port number.
+*
+* RETURN VALUES
+*      Returns the LMC value of the specified port on this node.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_init_physp
+* NAME
+*      osm_node_init_physp
+*
+* DESCRIPTION
+*      Initializes a physical port for the given node.
+*
+* SYNOPSIS
+*/
+void
+osm_node_init_physp(
+       IN osm_node_t* const p_node,
+       IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer to an osm_node_t object.
+*
+*      p_madw
+*              [in] Pointer to a osm_madw_t object containing a mad with
+*              the node's NodeInfo attribute as discovered through the
+*              Physical Port to add to the node.  The caller may discard the
+*              osm_madw_t structure after calling osm_node_new.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object, Physical Port object.
+*********/
+
+/****f* OpenSM: Node/osm_node_discovery_count_get
+* NAME
+*      osm_node_discovery_count_get
+*
+* DESCRIPTION
+*      Returns a pointer to the physical port object at the
+*      specified local port number.
+*
+* SYNOPSIS
+*/
+static inline uint32_t
+osm_node_discovery_count_get(
+       IN const osm_node_t* const p_node )
+{
+       return( p_node->discovery_count );
+}
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer to an osm_node_t object.
+*
+* RETURN VALUES
+*      Returns the discovery count for this node.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_discovery_count_reset
+* NAME
+*      osm_node_discovery_count_reset
+*
+* DESCRIPTION
+*      Resets the discovery count for this node to zero.
+*      This operation should be performed at the start of a sweep.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_node_discovery_count_reset(
+       IN osm_node_t* const p_node )
+{
+       p_node->discovery_count = 0;
+}
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer to an osm_node_t object.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_discovery_count_inc
+* NAME
+*      osm_node_discovery_count_inc
+*
+* DESCRIPTION
+*      Increments the discovery count for this node.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_node_discovery_count_inc(
+       IN osm_node_t* const p_node )
+{
+       p_node->discovery_count++;
+}
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer to an osm_node_t object.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_get_node_guid
+* NAME
+*      osm_node_get_node_guid
+*
+* DESCRIPTION
+*      Returns the node GUID of this node.
+*
+* SYNOPSIS
+*/
+static inline ib_net64_t
+osm_node_get_node_guid(
+       IN const osm_node_t* const p_node )
+{
+       return( p_node->node_info.node_guid );
+}
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer to an osm_node_t object.
+*
+* RETURN VALUES
+*      Returns the node GUID of this node.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_link
+* NAME
+*      osm_node_link
+*
+* DESCRIPTION
+*      Logically connects a node to another node through the specified port.
+*
+* SYNOPSIS
+*/
+void
+osm_node_link(
+       IN osm_node_t* const p_node,
+       IN const uint8_t port_num,
+       IN osm_node_t* const p_remote_node,
+       IN const uint8_t remote_port_num );
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer to an osm_node_t object.
+*
+*      port_num
+*              [in] Port number in p_node through which to create the link.
+*
+*      p_remote_node
+*              [in] Pointer to the remote port object.
+*
+*      remote_port_num
+*              [in] Port number in the remote's node through which to
+*              create this link.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_unlink
+* NAME
+*      osm_node_unlink
+*
+* DESCRIPTION
+*      Logically disconnects a node from another node through
+*      the specified port.
+*
+* SYNOPSIS
+*/
+void
+osm_node_unlink(
+       IN osm_node_t* const p_node,
+       IN const uint8_t port_num,
+       IN osm_node_t* const p_remote_node,
+       IN const uint8_t remote_port_num );
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer to an osm_node_t object.
+*
+*      port_num
+*              [in] Port number in p_node through which to unlink.
+*
+*      p_remote_node
+*              [in] Pointer to the remote port object.
+*
+*      remote_port_num
+*              [in] Port number in the remote's node through which to unlink.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_link_exists
+* NAME
+*      osm_node_link_exists
+*
+* DESCRIPTION
+*      Return TRUE if a link exists between the specified nodes on
+*      the specified ports.
+*      Returns FALSE otherwise.
+*
+* SYNOPSIS
+*/
+boolean_t
+osm_node_link_exists(
+       IN osm_node_t* const p_node,
+       IN const uint8_t port_num,
+       IN osm_node_t* const p_remote_node,
+       IN const uint8_t remote_port_num );
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer to an osm_node_t object.
+*
+*      port_num
+*              [in] Port number in p_node through which to check the link.
+*
+*      p_remote_node
+*              [in] Pointer to the remote port object.
+*
+*      remote_port_num
+*              [in] Port number in the remote's node through which to
+*              check this link.
+*
+* RETURN VALUES
+*      Return TRUE if a link exists between the specified nodes on
+*      the specified ports.
+*      Returns FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_has_any_link
+* NAME
+*      osm_node_has_any_link
+*
+* DESCRIPTION
+*      Return TRUE if a any link exists from the specified nodes on
+*      the specified port.
+*      Returns FALSE otherwise.
+*
+* SYNOPSIS
+*/
+boolean_t
+osm_node_has_any_link(
+       IN osm_node_t* const p_node,
+       IN const uint8_t port_num );
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer to an osm_node_t object.
+*
+*      port_num
+*              [in] Port number in p_node through which to check the link.
+*
+* RETURN VALUES
+*      Return TRUE if a any link exists from the specified nodes on
+*      the specified port.
+*      Returns FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_link_has_valid_ports
+* NAME
+*      osm_node_link_has_valid_ports
+*
+* DESCRIPTION
+*      Return TRUE if both ports in the link are valid (initialized).
+*      Returns FALSE otherwise.
+*
+* SYNOPSIS
+*/
+boolean_t
+osm_node_link_has_valid_ports(
+       IN osm_node_t* const p_node,
+       IN const uint8_t port_num,
+       IN osm_node_t* const p_remote_node,
+       IN const uint8_t remote_port_num );
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer to an osm_node_t object.
+*
+*      port_num
+*              [in] Port number in p_node through which to check the link.
+*
+* RETURN VALUES
+*      Return TRUE if both ports in the link are valid (initialized).
+*      Returns FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_NODE_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_desc_rcv.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_desc_rcv.h
new file mode 100644 (file)
index 0000000..413fdf3
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_node_desc_rcv.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_nd_rcv_t.
+ *     This object represents the NodeInfo Receiver object.
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_ND_RCV_H_
+#define _OSM_ND_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Node Description Receiver
+* NAME
+*      Node Description Receiver
+*
+* DESCRIPTION
+*      The Node Description Receiver object encapsulates the information
+*      needed to receive the NodeInfo attribute from a node.
+*
+*      The Node Description Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Node Description Receiver/osm_nd_rcv_t
+* NAME
+*      osm_nd_rcv_t
+*
+* DESCRIPTION
+*      Node Description Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_nd_rcv
+{
+       osm_subn_t                                      *p_subn;
+       osm_log_t                                       *p_log;
+       cl_plock_t                                      *p_lock;
+
+} osm_nd_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+* SEE ALSO
+*      Node Description Receiver object
+*********/
+
+/****f* OpenSM: Node Description Receiver/osm_nd_rcv_construct
+* NAME
+*      osm_nd_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a Node Description Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_nd_rcv_construct(
+       IN osm_nd_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to a Node Description Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_nd_rcv_init, osm_nd_rcv_destroy
+*
+*      Calling osm_nd_rcv_construct is a prerequisite to calling any other
+*      method except osm_nd_rcv_init.
+*
+* SEE ALSO
+*      Node Description Receiver object, osm_nd_rcv_init,
+*      osm_nd_rcv_destroy
+*********/
+
+/****f* OpenSM: Node Description Receiver/osm_nd_rcv_destroy
+* NAME
+*      osm_nd_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_nd_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_nd_rcv_destroy(
+       IN osm_nd_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Node Description Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_nd_rcv_construct or osm_nd_rcv_init.
+*
+* SEE ALSO
+*      Node Description Receiver object, osm_nd_rcv_construct,
+*      osm_nd_rcv_init
+*********/
+
+/****f* OpenSM: Node Description Receiver/osm_nd_rcv_init
+* NAME
+*      osm_nd_rcv_init
+*
+* DESCRIPTION
+*      The osm_nd_rcv_init function initializes a
+*      Node Description Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_nd_rcv_init(
+       IN osm_nd_rcv_t* const p_rcv,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_nd_rcv_t object to initialize.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Node Description Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Node Description Receiver methods.
+*
+* SEE ALSO
+*      Node Description Receiver object, osm_nd_rcv_construct,
+*      osm_nd_rcv_destroy
+*********/
+
+/****f* OpenSM: Node Description Receiver/osm_nd_rcv_process
+* NAME
+*      osm_nd_rcv_process
+*
+* DESCRIPTION
+*      Process the NodeInfo attribute.
+*
+* SYNOPSIS
+*/
+void osm_nd_rcv_process(
+       IN const osm_nd_rcv_t* const p_rcv,
+       IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_nd_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the node's NodeInfo attribute.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the NodeInfo processing was successful.
+*
+* NOTES
+*      This function processes a NodeInfo attribute.
+*
+* SEE ALSO
+*      Node Description Receiver, Node Description Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_ND_RCV_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_desc_rcv_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_desc_rcv_ctrl.h
new file mode 100644 (file)
index 0000000..0fbc4f8
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_node_desc_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_nd_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA NodeDescription
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_ND_RCV_CTRL_H_
+#define _OSM_ND_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_node_desc_rcv.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Node Description Receive Controller
+* NAME
+*      Node Description Receive Controller
+*
+* DESCRIPTION
+*      The Node Description Receive Controller object encapsulates the information
+*      needed to receive the NodeDescription attribute from a node.
+*
+*      The Node Description Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Node Description Receive Controller/osm_nd_rcv_ctrl_t
+* NAME
+*      osm_nd_rcv_ctrl_t
+*
+* DESCRIPTION
+*      Node Description Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_nd_rcv_ctrl
+{
+       osm_nd_rcv_t                            *p_rcv;
+       osm_log_t                                       *p_log;
+       cl_dispatcher_t                         *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_nd_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the Node Description Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      Node Description Receive Controller object
+*********/
+
+/****f* OpenSM: Node Description Receive Controller/osm_nd_rcv_ctrl_construct
+* NAME
+*      osm_nd_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Node Description Receive Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_nd_rcv_ctrl_construct(
+       IN osm_nd_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Node Description Receive Controller object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_nd_rcv_ctrl_init, osm_nd_rcv_ctrl_destroy
+*
+*      Calling osm_nd_rcv_ctrl_construct is a prerequisite to calling any other
+*      method except osm_nd_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Node Description Receive Controller object, osm_nd_rcv_ctrl_init,
+*      osm_nd_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: Node Description Receive Controller/osm_nd_rcv_ctrl_destroy
+* NAME
+*      osm_nd_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_nd_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_nd_rcv_ctrl_destroy(
+       IN osm_nd_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Node Description Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_nd_rcv_ctrl_construct or osm_nd_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Node Description Receive Controller object, osm_nd_rcv_ctrl_construct,
+*      osm_nd_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Node Description Receive Controller/osm_nd_rcv_ctrl_init
+* NAME
+*      osm_nd_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_nd_rcv_ctrl_init function initializes a
+*      Node Description Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_nd_rcv_ctrl_init(
+       IN osm_nd_rcv_ctrl_t* const p_ctrl,
+       IN osm_nd_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_nd_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_nd_rcv_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Node Description Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Node Description Receive Controller methods.
+*
+* SEE ALSO
+*      Node Description Receive Controller object, osm_nd_rcv_ctrl_construct,
+*      osm_nd_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif         /* OSM_ND_RCV_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_info_rcv.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_info_rcv.h
new file mode 100644 (file)
index 0000000..f6f0b99
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_node_info_rcv.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_ni_rcv_t.
+ *     This object represents the NodeInfo Receiver object.
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_NI_RCV_H_
+#define _OSM_NI_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_state_mgr.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Node Info Receiver
+* NAME
+*      Node Info Receiver
+*
+* DESCRIPTION
+*      The Node Info Receiver object encapsulates the information
+*      needed to receive the NodeInfo attribute from a node.
+*
+*      The Node Info Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Node Info Receiver/osm_ni_rcv_t
+* NAME
+*      osm_ni_rcv_t
+*
+* DESCRIPTION
+*      Node Info Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_ni_rcv
+{
+       osm_subn_t                              *p_subn;
+       osm_req_t                               *p_gen_req;
+       osm_log_t                               *p_log;
+       osm_state_mgr_t                         *p_state_mgr;
+       cl_plock_t                              *p_lock;
+
+} osm_ni_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_gen_req_ctrl
+*              Pointer to the generic request controller.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_state_mgr
+*              Pointer to the State Manager object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+* SEE ALSO
+*      Node Info Receiver object
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_ni_rcv_construct
+* NAME
+*      osm_ni_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a Node Info Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_ni_rcv_construct(
+       IN osm_ni_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Node Info Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_ni_rcv_init, osm_ni_rcv_destroy,
+*      and osm_ni_rcv_is_inited.
+*
+*      Calling osm_ni_rcv_construct is a prerequisite to calling any other
+*      method except osm_ni_rcv_init.
+*
+* SEE ALSO
+*      Node Info Receiver object, osm_ni_rcv_init,
+*      osm_ni_rcv_destroy, osm_ni_rcv_is_inited
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_ni_rcv_destroy
+* NAME
+*      osm_ni_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_ni_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_ni_rcv_destroy(
+       IN osm_ni_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Node Info Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_ni_rcv_construct or osm_ni_rcv_init.
+*
+* SEE ALSO
+*      Node Info Receiver object, osm_ni_rcv_construct,
+*      osm_ni_rcv_init
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_ni_rcv_init
+* NAME
+*      osm_ni_rcv_init
+*
+* DESCRIPTION
+*      The osm_ni_rcv_init function initializes a
+*      Node Info Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_ni_rcv_init(
+       IN osm_ni_rcv_t* const p_ctrl,
+       IN osm_req_t* const p_req,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN osm_state_mgr_t* const p_state_mgr,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_ni_rcv_t object to initialize.
+*
+*      p_req
+*              [in] Pointer to an osm_req_t object.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_state_mgr
+*              [in] Pointer to the State Manager object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Node Info Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Node Info Receiver methods.
+*
+* SEE ALSO
+*      Node Info Receiver object, osm_ni_rcv_construct,
+*      osm_ni_rcv_destroy, osm_ni_rcv_is_inited
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_ni_rcv_is_inited
+* NAME
+*      osm_ni_rcv_is_inited
+*
+* DESCRIPTION
+*      Indicates if the object has been initialized with osm_ni_rcv_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_ni_rcv_is_inited(
+       IN const osm_ni_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_ni_rcv_t object.
+*
+* RETURN VALUES
+*      TRUE if the object was initialized successfully,
+*      FALSE otherwise.
+*
+* NOTES
+*      The osm_ni_rcv_construct or osm_ni_rcv_init must be
+*      called before using this function.
+*
+* SEE ALSO
+*      Node Info Receiver object, osm_ni_rcv_construct,
+*      osm_ni_rcv_init
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_ni_rcv_process
+* NAME
+*      osm_ni_rcv_process
+*
+* DESCRIPTION
+*      Process the NodeInfo attribute.
+*
+* SYNOPSIS
+*/
+void osm_ni_rcv_process(
+       IN const osm_ni_rcv_t* const p_ctrl,
+       IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_ni_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the node's NodeInfo attribute.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the NodeInfo processing was successful.
+*
+* NOTES
+*      This function processes a NodeInfo attribute.
+*
+* SEE ALSO
+*      Node Info Receiver, Node Info Response Controller
+*********/
+       
+END_C_DECLS
+
+#endif /* _OSM_NI_RCV_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_info_rcv_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_node_info_rcv_ctrl.h
new file mode 100644 (file)
index 0000000..3f2a71d
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_node_info_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_ni_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA NodeInfo
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_NI_RCV_CTRL_H_
+#define _OSM_NI_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node_info_rcv.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Node Info Receive Controller
+* NAME
+*      Node Info Receive Controller
+*
+* DESCRIPTION
+*      The Node Info Receive Controller object encapsulates
+*      the information needed to receive the NodeInfo attribute from a node.
+*
+*      The Node Info Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Node Info Receive Controller/osm_ni_rcv_ctrl_t
+* NAME
+*      osm_ni_rcv_ctrl_t
+*
+* DESCRIPTION
+*      Node Info Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_ni_rcv_ctrl
+{
+       osm_ni_rcv_t                    *p_rcv;
+       osm_log_t                       *p_log;
+       cl_dispatcher_t                 *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_ni_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the Node Info Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      Node Info Receive Controller object
+*      Node Info Receiver object
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_ni_rcv_ctrl_construct
+* NAME
+*      osm_ni_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Node Info Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_ni_rcv_ctrl_construct(
+       IN osm_ni_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Node Info Receive Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_ni_rcv_ctrl_init, osm_ni_rcv_ctrl_destroy,
+*      and osm_ni_rcv_ctrl_is_inited.
+*
+*      Calling osm_ni_rcv_ctrl_construct is a prerequisite to calling any other
+*      method except osm_ni_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Node Info Receive Controller object, osm_ni_rcv_ctrl_init,
+*      osm_ni_rcv_ctrl_destroy, osm_ni_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_ni_rcv_ctrl_destroy
+* NAME
+*      osm_ni_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_ni_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_ni_rcv_ctrl_destroy(
+       IN osm_ni_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Node Info Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_ni_rcv_ctrl_construct or osm_ni_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Node Info Receive Controller object, osm_ni_rcv_ctrl_construct,
+*      osm_ni_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_ni_rcv_ctrl_init
+* NAME
+*      osm_ni_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_ni_rcv_ctrl_init function initializes a
+*      Node Info Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_ni_rcv_ctrl_init(
+       IN osm_ni_rcv_ctrl_t* const p_ctrl,
+       IN osm_ni_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_ni_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_ni_rcv_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Node Info Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Node Info Receive Controller methods.
+*
+* SEE ALSO
+*      Node Info Receive Controller object, osm_ni_rcv_ctrl_construct,
+*      osm_ni_rcv_ctrl_destroy, osm_ni_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_ni_rcv_ctrl_is_inited
+* NAME
+*      osm_ni_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+*      Indicates if the object has been initialized with osm_ni_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_ni_rcv_ctrl_is_inited(
+       IN const osm_ni_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_ni_rcv_ctrl_t object.
+*
+* RETURN VALUES
+*      TRUE if the object was initialized successfully,
+*      FALSE otherwise.
+*
+* NOTES
+*      The osm_ni_rcv_ctrl_construct or osm_ni_rcv_ctrl_init must be
+*      called before using this function.
+*
+* SEE ALSO
+*      Node Info Receive Controller object, osm_ni_rcv_ctrl_construct,
+*      osm_ni_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_NI_RCV_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_opensm.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_opensm.h
new file mode 100644 (file)
index 0000000..488d43b
--- /dev/null
@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_opensm.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_opensm_t.
+ *     This object represents the OpenSM super object.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#ifndef _OSM_OPENSM_H_
+#define _OSM_OPENSM_H_
+
+#include <signal.h>
+#include <complib/cl_dispatcher.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_atomic.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sm.h>
+#include <opensm/osm_sa.h>
+#include <opensm/osm_db.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_vl15intf.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/OpenSM
+* NAME
+*      OpenSM
+*
+* DESCRIPTION
+*      The OpenSM object encapsulates the information needed by the
+*      OpenSM to govern itself.  The OpenSM is one OpenSM object.
+*
+*      The OpenSM object is thread safe.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: OpenSM/osm_routing_engine
+* NAME
+*      struct osm_routing_engine
+*
+* DESCRIPTION
+*      OpenSM routing engine module definition.
+* NOTES
+*      routing engine structure - yet limited by ucast_fdb_assign and
+*      ucast_build_fwd_tables (multicast callbacks may be added later)
+*/
+struct osm_routing_engine {
+       const char *name;
+       void *context;
+       int (*build_lid_matrices)(void *context);
+       int (*ucast_build_fwd_tables)(void *context);
+       void (*ucast_dump_tables)(void *context);
+       void (*delete)(void *context);
+};
+/*
+* FIELDS
+*      name
+*              The routing engine name (will be used in logs).
+*
+*      context 
+*              The routing engine context. Will be passed as parameter
+*              to the callback functions.
+*
+*      build_lid_matrices
+*              The callback for lid matrices generation.
+*
+*      ucast_build_fwd_tables
+*              The callback for unicast forwarding table generation.
+*
+*      ucast_dump_tables
+*              The callback for dumping unicast routing tables.
+*
+*      delete
+*              The delete method, may be used for routing engine
+*              internals cleanup.
+*/
+
+/****s* OpenSM: OpenSM/osm_opensm_t
+* NAME
+*      osm_opensm_t
+*
+* DESCRIPTION
+*      OpenSM structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_opensm_t
+{
+  osm_subn_t           subn;
+  osm_sm_t             sm;
+  osm_sa_t             sa;
+  osm_db_t             db;
+  osm_mad_pool_t       mad_pool;
+  osm_vendor_t         *p_vendor;
+  osm_vl15_t           vl15;
+  osm_log_t            log;
+  cl_dispatcher_t      disp;
+  cl_plock_t           lock;
+  struct osm_routing_engine routing_engine;
+  osm_stats_t          stats;
+} osm_opensm_t;
+/*
+* FIELDS
+*      subn
+*              Subnet object for this subnet.
+*
+*      sm
+*              The Subnet Manager (SM) object for this subnet.
+*
+*      sa
+*              The Subnet Administration (SA) object for this subnet.
+*
+*      db 
+*              Persistant storage of some data required between sessions.
+*
+*      mad_pool
+*              Pool of Management Datagram (MAD) objects.
+*
+*      p_vendor
+*              Pointer to the Vendor specific adapter for various
+*              transport interfaces, such as UMADT, AL, etc.  The
+*              particular interface is set at compile time.
+*
+*      vl15
+*              The VL15 interface.
+*
+*      log
+*              Log facility used by all OpenSM components.
+*
+*      disp
+*              Central dispatcher containing the OpenSM worker threads.
+*
+*      lock
+*              Shared lock guarding most OpenSM structures.
+*
+*      routing_engine
+*              Routing engine; will be initialized then used.
+*
+*      stats
+*              Open SM statistics block
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: OpenSM/osm_opensm_construct
+* NAME
+*      osm_opensm_construct
+*
+* DESCRIPTION
+*      This function constructs an OpenSM object.
+*
+* SYNOPSIS
+*/
+void osm_opensm_construct(
+       IN osm_opensm_t* const p_osm );
+/*
+* PARAMETERS
+*      p_osm
+*              [in] Pointer to a OpenSM object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_opensm_init, osm_opensm_destroy
+*
+*      Calling osm_opensm_construct is a prerequisite to calling any other
+*      method except osm_opensm_init.
+*
+* SEE ALSO
+*      SM object, osm_opensm_init, osm_opensm_destroy
+*********/
+
+/****f* OpenSM: OpenSM/osm_opensm_destroy
+* NAME
+*      osm_opensm_destroy
+*
+* DESCRIPTION
+*      The osm_opensm_destroy function destroys an SM, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_opensm_destroy(
+       IN osm_opensm_t* const p_osm );
+/*
+* PARAMETERS
+*      p_osm
+*              [in] Pointer to a OpenSM object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified OpenSM object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to osm_opensm_construct or
+*      osm_opensm_init.
+*
+* SEE ALSO
+*      SM object, osm_opensm_construct, osm_opensm_init
+*********/
+
+/****f* OpenSM: OpenSM/osm_opensm_init
+* NAME
+*      osm_opensm_init
+*
+* DESCRIPTION
+*      The osm_opensm_init function initializes a OpenSM object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_opensm_init(
+       IN osm_opensm_t* const p_osm,
+       IN const osm_subn_opt_t* const p_opt );
+/*
+* PARAMETERS
+*      p_osm
+*              [in] Pointer to an osm_opensm_t object to initialize.
+*
+*      p_opt
+*              [in] Pointer to the subnet options structure.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the OpenSM object was initialized successfully.
+*
+* NOTES
+*      Allows calling other OpenSM methods.
+*
+* SEE ALSO
+*      SM object, osm_opensm_construct, osm_opensm_destroy
+*********/
+
+/****f* OpenSM: OpenSM/osm_opensm_sweep
+* NAME
+*      osm_opensm_sweep
+*
+* DESCRIPTION
+*      Initiates a subnet sweep.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_opensm_sweep(
+       IN osm_opensm_t* const p_osm )
+{
+       osm_sm_sweep( &p_osm->sm );
+}
+/*
+* PARAMETERS
+*      p_osm
+*              [in] Pointer to an osm_opensm_t object on which to 
+*              initiate a sweep.
+*
+* RETURN VALUES
+*      None
+*
+* NOTES
+*      If the OpenSM object is not bound to a port, this function
+*      does nothing.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: OpenSM/osm_opensm_set_log_flags
+* NAME
+*      osm_opensm_set_log_flags
+*
+* DESCRIPTION
+*      Sets the log level.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_opensm_set_log_flags(
+       IN osm_opensm_t* const p_osm,
+       IN const osm_log_level_t log_flags )
+{
+       osm_log_set_level( &p_osm->log, log_flags );
+}
+/*
+* PARAMETERS
+*      p_osm
+*              [in] Pointer to an osm_opensm_t object.
+*
+*      log_flags
+*              [in] Log level flags to set.
+*
+* RETURN VALUES
+*      None
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: OpenSM/osm_opensm_bind
+* NAME
+*      osm_opensm_bind
+*
+* DESCRIPTION
+*      Binds the opensm object to a port guid.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_opensm_bind(
+       IN osm_opensm_t* const p_osm,
+       IN const ib_net64_t guid );
+/*
+* PARAMETERS
+*      p_osm
+*              [in] Pointer to an osm_opensm_t object to bind.
+*
+*      guid
+*              [in] Local port GUID with which to bind.
+*
+* RETURN VALUES
+*      None
+*
+* NOTES
+*      A given opensm object can only be bound to one port at a time.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: OpenSM/osm_opensm_wait_for_subnet_up
+* NAME
+*      osm_opensm_wait_for_subnet_up
+*
+* DESCRIPTION
+*      Blocks the calling thread until the subnet is up.
+*
+* SYNOPSIS
+*/
+static inline cl_status_t
+osm_opensm_wait_for_subnet_up(
+       IN osm_opensm_t*                        const p_osm,
+       IN uint32_t                             const wait_us,
+       IN boolean_t                            const interruptible )
+{
+       return( osm_sm_wait_for_subnet_up( &p_osm->sm, wait_us, interruptible ) );
+}
+/*
+* PARAMETERS
+*      p_osm
+*              [in] Pointer to an osm_opensm_t object.
+*
+*      wait_us 
+*              [in] Number of microseconds to wait.
+*
+*      interruptible
+*              [in] Indicates whether the wait operation can be interrupted
+*              by external signals.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the wait operation succeeded in response to the event 
+*      being set.
+*
+*      CL_TIMEOUT if the specified time period elapses.
+*
+*      CL_NOT_DONE if the wait was interrupted by an external signal.
+*
+*      CL_ERROR if the wait operation failed.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****v* OpenSM/osm_exit_flag 
+*/
+extern volatile unsigned int osm_exit_flag;
+/* 
+* DESCRIPTION 
+*  Set to one to cause all threads to leave 
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_OPENSM_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_partition.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_partition.h
new file mode 100644 (file)
index 0000000..b45d44b
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_partition.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_prtn_t.
+ *     This object represents an IBA Partition.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_PARTITION_H_
+#define _OSM_PARTITION_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_map.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_subnet.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Partition
+* NAME
+*      Partition
+*
+* DESCRIPTION
+*      The Partition object encapsulates the information needed by the
+*      OpenSM to manage Partitions.  The OpenSM allocates one Partition
+*      object per Partition in the IBA subnet.
+*
+*      The Partition is not thread safe, thus callers must provide
+*      serialization.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Partition/osm_prtn_t
+* NAME
+*      osm_prtn_t
+*
+* DESCRIPTION
+*      Partition structure.
+*
+*      The osm_prtn_t object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_prtn
+{
+       cl_map_item_t   map_item;
+       uint16_t        pkey;
+       uint8_t         sl; 
+       cl_map_t        full_guid_tbl;
+       cl_map_t        part_guid_tbl;
+       char            name[32];
+} osm_prtn_t;
+/*
+* FIELDS
+*      map_item
+*              Linkage structure for cl_qmap.  MUST BE FIRST MEMBER!
+*
+*      pkey
+*              The IBA defined P_KEY of this Partition.
+*
+*      sl
+*              The Service Level (SL) associated with this Partiton.
+*
+*      full_guid_tbl
+*              Container of pointers to all Port objects in the Partition
+*              with full membership, indexed by port GUID.
+*
+*      part_guid_tbl
+*              Container of pointers to all Port objects in the Partition
+*              with limited membership, indexed by port GUID.
+*
+*      name
+*              Name of the Partition as specified in partition
+*              configuration.
+*
+* SEE ALSO
+*      Partition
+*********/
+
+/****f* OpenSM: Partition/osm_prtn_delete
+* NAME
+*      osm_prtn_delete
+*
+* DESCRIPTION
+*      This function destroys and deallocates a Partition object.
+*
+* SYNOPSIS
+*/
+void osm_prtn_delete(
+       IN OUT osm_prtn_t** const pp_prtn );
+/*
+* PARAMETERS
+*      pp_prtn
+*              [in][out] Pointer to a pointer to a Partition object to
+*              delete. On return, this pointer is NULL.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified Partition object.
+*
+* SEE ALSO
+*      Partition, osm_prtn_new
+*********/
+
+/****f* OpenSM: Partition/osm_prtn_new
+* NAME
+*      osm_prtn_new
+*
+* DESCRIPTION
+*      This function allocates and initializes a Partition object.
+*
+* SYNOPSIS
+*/
+osm_prtn_t* osm_prtn_new(
+       IN const char *name,
+       IN const uint16_t pkey );
+/*
+* PARAMETERS
+*      name
+*              [in] Partition name string
+*
+*      pkey
+*              [in] Partition P_Key value
+*
+* RETURN VALUE
+*      Pointer to the initialize Partition object.
+*
+* NOTES
+*      Allows calling other partition methods.
+*
+* SEE ALSO
+*      Partition
+*********/
+
+/****f* OpenSM: Partition/osm_prtn_is_guid
+* NAME
+*      osm_prtn_is_guid
+*
+* DESCRIPTION
+*      Indicates if a port is a member of the partition.
+*
+* SYNOPSIS
+*/
+static inline
+boolean_t osm_prtn_is_guid(
+       IN const osm_prtn_t* const p_prtn,
+       IN const ib_net64_t guid )
+{
+       return (cl_map_get(&p_prtn->full_guid_tbl, guid) != NULL) ||
+               (cl_map_get(&p_prtn->part_guid_tbl, guid) != NULL);
+}
+/*
+* PARAMETERS
+*      p_prtn
+*              [in] Pointer to an osm_prtn_t object.
+*
+*      guid
+*              [in] Port GUID.
+*
+* RETURN VALUES
+*      TRUE if the specified port GUID is a member of the partition,
+*      FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Partition/osm_prtn_make_partitions
+* NAME
+*      osm_prtn_make_partitions
+*
+* DESCRIPTION
+*      Makes all partitions in subnet.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_prtn_make_partitions(
+       IN osm_log_t * const p_log,
+       IN osm_subn_t * const p_subn);
+/*
+* PARAMETERS
+*      p_log
+*              [in] Pointer to a log object.
+*
+*      p_subn
+*              [in] Pointer to subnet object.
+*
+* RETURN VALUES
+*      IB_SUCCESS value on success.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PARTITION_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_path.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_path.h
new file mode 100644 (file)
index 0000000..49ed040
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_path.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_PATH_H_
+#define _OSM_PATH_H_
+
+#include <string.h>
+#include <opensm/osm_base.h>
+#include <vendor/osm_vendor.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/*
+ * Abstract:
+ *     Declaration of path related objects.
+ *     These objects are part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+/****h* OpenSM/DR Path
+* NAME
+*      DR Path
+*
+* DESCRIPTION
+*      The DR Path structure encapsulates a directed route through the subnet.
+*
+*      This structure allows direct access to member variables.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: DR Path/osm_dr_path_t
+* NAME
+*      osm_dr_path_t
+*
+* DESCRIPTION
+*      Directed Route structure.
+*
+*      This structure allows direct access to member variables.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_dr_path
+{
+       osm_bind_handle_t               h_bind;
+       uint8_t                                 hop_count;
+       uint8_t                                 path[IB_SUBNET_PATH_HOPS_MAX];
+
+} osm_dr_path_t;
+/*
+* FIELDS
+*      h_bind
+*              Bind handle for port to which this path applies.
+*
+*      hop_count
+*              The number of hops in this path.
+*
+*      path
+*              The array of port numbers that comprise this path.
+*
+* SEE ALSO
+*      DR Path structure
+*********/
+/****f* OpenSM: DR Path/osm_dr_path_construct
+* NAME
+*      osm_dr_path_construct
+*
+* DESCRIPTION
+*      This function constructs a directed route path object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_dr_path_construct(
+       IN osm_dr_path_t* const p_path )
+{
+       /* The first location in the path array is reserved. */
+       memset( p_path, 0, sizeof(*p_path) );
+       p_path->h_bind = OSM_BIND_INVALID_HANDLE;
+}
+
+/*
+* PARAMETERS
+*      p_path
+*              [in] Pointer to a directed route path object to initialize.
+*
+*      h_bind
+*              [in] Bind handle for the port on which this path applies.
+*
+*      hop_count
+*              [in] Hop count needed to reach this node.
+*
+*      path
+*              [in] Directed route path to reach this node.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: DR Path/osm_dr_path_init
+* NAME
+*      osm_dr_path_init
+*
+* DESCRIPTION
+*      This function initializes a directed route path object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_dr_path_init(
+       IN osm_dr_path_t* const p_path,
+       IN const osm_bind_handle_t h_bind,
+       IN const uint8_t hop_count,
+       IN const uint8_t path[IB_SUBNET_PATH_HOPS_MAX] )
+{
+       /* The first location in the path array is reserved. */
+       CL_ASSERT( path[0] == 0 );
+       CL_ASSERT( hop_count < IB_SUBNET_PATH_HOPS_MAX );
+       p_path->h_bind = h_bind;
+       p_path->hop_count = hop_count;
+       memcpy( p_path->path, path, IB_SUBNET_PATH_HOPS_MAX );
+}
+
+/*
+* PARAMETERS
+*      p_path
+*              [in] Pointer to a directed route path object to initialize.
+*
+*      h_bind
+*              [in] Bind handle for the port on which this path applies.
+*
+*      hop_count
+*              [in] Hop count needed to reach this node.
+*
+*      path
+*              [in] Directed route path to reach this node.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* OpenSM: DR Path/osm_dr_path_extend
+* NAME
+*      osm_dr_path_extend
+*
+* DESCRIPTION
+*      Adds a new hop to a path.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_dr_path_extend(
+       IN osm_dr_path_t* const p_path,
+       IN const uint8_t port_num )
+{
+       p_path->hop_count++;
+       CL_ASSERT( p_path->hop_count < IB_SUBNET_PATH_HOPS_MAX );
+       /*
+               Location 0 in the path array is reserved per IB spec.
+       */
+       p_path->path[p_path->hop_count] = port_num;
+}
+
+/*
+* PARAMETERS
+*      p_path
+*              [in] Pointer to a directed route path object to initialize.
+*
+*      port_num
+*              [in] Additional port to add to the DR path.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: DR Path/osm_dr_path_get_bind_handle
+* NAME
+*      osm_dr_path_get_bind_handle
+*
+* DESCRIPTION
+*      Gets the bind handle from a path.
+*
+* SYNOPSIS
+*/
+static inline osm_bind_handle_t
+osm_dr_path_get_bind_handle(
+       IN const osm_dr_path_t* const p_path )
+{
+       return( p_path->h_bind );
+}
+
+/*
+* PARAMETERS
+*      p_path
+*              [in] Pointer to a directed route path object to initialize.
+*
+*      port_num
+*              [in] Additional port to add to the DR path.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif         /* _OSM_PATH_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey.h
new file mode 100644 (file)
index 0000000..7f4abbe
--- /dev/null
@@ -0,0 +1,755 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_pkey.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_PKEY_H_
+#define _OSM_PKEY_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_req.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/*
+   Forward references.
+*/
+struct _osm_physp;
+struct _osm_port;
+struct _osm_subn;
+struct _osm_node;
+struct _osm_physp;
+
+/*
+ * Abstract:
+ *     Declaration of pkey manipulation functions.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.1 $
+ */
+
+/****s* OpenSM: osm_pkey_tbl_t
+* NAME
+*      osm_pkey_tbl_t
+*
+* DESCRIPTION
+*      This object represents a pkey table. The need for a special object
+*  is required to optimize search performance of a PKey in the IB standard
+*  non sorted table.
+*
+*      The osm_pkey_tbl_t object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pkey_tbl
+{
+  cl_ptr_vector_t blocks;
+  cl_ptr_vector_t new_blocks;
+  cl_map_t        keys;
+  cl_qlist_t      pending;
+  uint16_t        used_blocks;
+  uint16_t        max_blocks;
+} osm_pkey_tbl_t;
+/*
+* FIELDS
+*      blocks
+*              The IBA defined blocks of pkey values, updated from the subnet
+*
+*      new_blocks
+*              The blocks of pkey values, will be used for updates by SM
+*
+*      keys
+*              A set holding all keys
+*
+*      pending
+*              A list of osm_pending_pkey structs that is temporarily set by
+*              the pkey mgr and used during pkey mgr algorithm only
+*
+*      used_blocks
+*              Tracks the number of blocks having non-zero pkeys
+*
+*      max_blocks
+*              The maximal number of blocks this partition table might hold
+*              this value is based on node_info (for port 0 or CA) or
+*              switch_info updated on receiving the node_info or switch_info
+*              GetResp
+*
+* NOTES
+* 'blocks' vector should be used to store pkey values obtained from
+* the port and SM pkey manager should not change it directly, for this
+* purpose 'new_blocks' should be used.
+*
+* The only pkey values stored in 'blocks' vector will be mapped with
+* 'keys' map
+*
+*********/
+
+/****s* OpenSM: osm_pending_pkey_t
+* NAME
+*      osm_pending_pkey_t
+*
+* DESCRIPTION
+*      This objects stores temporary information on pkeys, their target block,
+*  and index during the pkey manager operation
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pending_pkey {
+  cl_list_item_t       list_item;
+  uint16_t             pkey;
+  uint16_t             block;
+  uint8_t              index;
+  boolean_t            is_new;
+} osm_pending_pkey_t;
+/*
+* FIELDS
+*      pkey
+*              The actual P_Key
+*
+*      block
+*              The block index based on the previous table extracted from the
+*              device
+*
+*      index
+*              The index of the pkey within the block
+*
+*      is_new
+*              TRUE for new P_Keys such that the block and index are invalid
+*              in that case
+*
+*********/
+
+/****f* OpenSM: osm_pkey_tbl_construct
+* NAME
+*  osm_pkey_tbl_construct
+*
+* DESCRIPTION
+*  Constructs the PKey table object
+*
+* SYNOPSIS
+*/
+void osm_pkey_tbl_construct( 
+  IN osm_pkey_tbl_t *p_pkey_tbl);
+/*
+*  p_pkey_tbl
+*     [in] Pointer to osm_pkey_tbl_t object.
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_pkey_tbl_init
+* NAME
+*  osm_pkey_tbl_init
+*
+* DESCRIPTION
+*  Inits the PKey table object
+*
+* SYNOPSIS
+*/
+ib_api_status_t 
+osm_pkey_tbl_init( 
+  IN osm_pkey_tbl_t *p_pkey_tbl);
+/*
+*  p_pkey_tbl
+*     [in] Pointer to osm_pkey_tbl_t object.
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_pkey_tbl_destroy
+* NAME
+*  osm_pkey_tbl_destroy
+*
+* DESCRIPTION
+*  Destroys the PKey table object
+*
+* SYNOPSIS
+*/
+void osm_pkey_tbl_destroy( 
+  IN osm_pkey_tbl_t *p_pkey_tbl);
+/*
+*  p_pkey_tbl
+*     [in] Pointer to osm_pkey_tbl_t object.
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_pkey_get_num_blocks
+* NAME
+*  osm_pkey_get_num_blocks
+*
+* DESCRIPTION
+*  Obtain the number of blocks in IB PKey table 
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_pkey_tbl_get_num_blocks( 
+  IN const osm_pkey_tbl_t *p_pkey_tbl )
+{
+  return((uint16_t)(cl_ptr_vector_get_size( &p_pkey_tbl->blocks )));
+}
+/*
+*  p_pkey_tbl
+*     [in] Pointer to osm_pkey_tbl_t object.
+*
+* RETURN VALUES
+*  The IB pkey table of that pkey table element
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_pkey_tbl_block_get
+* NAME
+*  osm_pkey_tbl_block_get
+*
+* DESCRIPTION
+*  Obtain the pointer to the IB PKey table block stored in the object
+*
+* SYNOPSIS
+*/
+static inline ib_pkey_table_t *osm_pkey_tbl_block_get( 
+  const osm_pkey_tbl_t *p_pkey_tbl, uint16_t block)
+{
+  return( (block < cl_ptr_vector_get_size(&p_pkey_tbl->blocks)) ?
+          cl_ptr_vector_get(&p_pkey_tbl->blocks, block) : NULL );
+};
+/*
+*  p_pkey_tbl
+*     [in] Pointer to osm_pkey_tbl_t object.
+*
+*  block 
+*     [in] The lock number to get
+*
+* RETURN VALUES
+*  The IB pkey table of that pkey table element
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_pkey_tbl_new_block_get
+* NAME
+*  osm_pkey_tbl_new_block_get
+*
+* DESCRIPTION
+*  The same as above but for new block
+*
+* SYNOPSIS
+*/
+static inline ib_pkey_table_t *osm_pkey_tbl_new_block_get( 
+  const osm_pkey_tbl_t *p_pkey_tbl, uint16_t block)
+{
+  return (block < cl_ptr_vector_get_size(&p_pkey_tbl->new_blocks)) ?
+          cl_ptr_vector_get(&p_pkey_tbl->new_blocks, block) : NULL;
+};
+
+/****f* OpenSM: osm_pkey_tbl_set_new_entry
+* NAME
+*  osm_pkey_tbl_set_new_entry
+*
+* DESCRIPTION
+*   Stores the given pkey in the "new" blocks array and update
+*   the "map" to show that on the "old" blocks
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_pkey_tbl_set_new_entry( 
+       IN osm_pkey_tbl_t *p_pkey_tbl,
+       IN uint16_t        block_idx,
+       IN uint8_t         pkey_idx,
+       IN uint16_t        pkey);
+/*
+* p_pkey_tbl
+*   [in] Pointer to the PKey table 
+*
+* block_idx
+*   [in] The block index to use
+*
+* pkey_idx
+*   [in] The index within the block
+*
+* pkey
+*   [in] PKey to store
+*
+* RETURN VALUES
+*   IB_SUCCESS if OK
+*   IB_ERROR if failed
+* 
+*********/
+
+/****f* OpenSM: osm_pkey_find_next_free_entry
+* NAME
+*  osm_pkey_find_next_free_entry
+*
+* DESCRIPTION
+*  Find the next free entry in the PKey table starting at the given
+*  index and block number. The user should increment pkey_idx before 
+*  next call
+*  Inspect the "new" blocks array for empty space.
+*
+* SYNOPSIS
+*/
+boolean_t
+osm_pkey_find_next_free_entry(
+       IN osm_pkey_tbl_t *p_pkey_tbl, 
+       OUT uint16_t      *p_block_idx,
+       OUT uint8_t       *p_pkey_idx);
+/*
+* p_pkey_tbl
+*   [in] Pointer to the PKey table 
+*
+* p_block_idx
+*   [out] The block index to use
+*
+* p_pkey_idx
+*   [out] The index within the block to use
+*
+* RETURN VALUES
+*   TRUE if found
+*   FALSE if did not find
+* 
+*********/
+
+/****f* OpenSM: osm_pkey_tbl_init_new_blocks
+* NAME
+*  osm_pkey_tbl_init_new_blocks
+*
+* DESCRIPTION
+*  Initializes new_blocks vector content (allocate and clear)
+*
+* SYNOPSIS
+*/
+void osm_pkey_tbl_init_new_blocks( 
+  const osm_pkey_tbl_t *p_pkey_tbl);
+/*
+*  p_pkey_tbl
+*     [in] Pointer to osm_pkey_tbl_t object.
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_pkey_tbl_get_block_and_idx
+* NAME
+*  osm_pkey_tbl_get_block_and_idx
+*
+* DESCRIPTION
+*  Set the block index and pkey index the given
+*  pkey is found in. Return IB_NOT_FOUND if could
+*  not find it, IB_SUCCESS if OK
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_pkey_tbl_get_block_and_idx(
+  IN  osm_pkey_tbl_t *p_pkey_tbl, 
+  IN  uint16_t       *p_pkey,
+  OUT uint16_t       *block_idx,
+  OUT uint8_t        *pkey_index);
+/*
+*  p_pkey_tbl
+*     [in] Pointer to osm_pkey_tbl_t object.
+*  
+*  p_pkey
+*     [in] Pointer to the P_Key entry searched
+*
+*  p_block_idx
+*     [out] Pointer to the block index to be updated
+*
+*  p_pkey_idx 
+*     [out] Pointer to the pkey index (in the block) to be updated
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_pkey_tbl_set
+* NAME
+*  osm_pkey_tbl_set
+*
+* DESCRIPTION
+*  Set the PKey table block provided in the PKey object.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_pkey_tbl_set( 
+  IN osm_pkey_tbl_t *p_pkey_tbl,
+  IN uint16_t block, 
+  IN ib_pkey_table_t *p_tbl);
+/*
+*  p_pkey_tbl
+*     [in] Pointer to osm_pkey_tbl_t object.
+*  
+*  block 
+*     [in] The block number to set
+*
+*  p_tbl
+*     [in] The IB PKey block to copy to the object
+*
+* RETURN VALUES
+*  IB_SUCCESS or IB_ERROR
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_physp_share_this_pkey
+* NAME
+*  osm_physp_share_this_pkey
+*
+* DESCRIPTION
+*  Checks if the given physical ports share the specified pkey.
+*
+* SYNOPSIS
+*/
+boolean_t osm_physp_share_this_pkey(
+  IN const struct _osm_physp * const p_physp1,
+  IN const struct _osm_physp * const p_physp2,
+  IN const ib_net16_t    pkey);
+/*
+* PARAMETERS
+*
+*  p_physp1
+*     [in] Pointer to an osm_physp_t object.
+*
+*  p_physp2
+*     [in] Pointer to an osm_physp_t object.
+*
+*  pkey
+*     [in] value of P_Key to check.
+*
+* RETURN VALUES
+*  Returns TRUE if the two ports are matching.
+*  FALSE otherwise.
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_physp_find_common_pkey
+* NAME
+*  osm_physp_find_common_pkey
+*
+* DESCRIPTION
+*  Returns first matching P_Key values for specified physical ports.
+*
+* SYNOPSIS
+*/
+ib_net16_t osm_physp_find_common_pkey(
+  IN const struct _osm_physp * const p_physp1,
+  IN const struct _osm_physp * const p_physp2 );
+/*
+* PARAMETERS
+*
+*  p_physp1
+*     [in] Pointer to an osm_physp_t object.
+*
+*  p_physp2
+*     [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+*  Returns value of first shared P_Key or INVALID P_Key (0x0) if not
+*  found.
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_physp_share_pkey
+* NAME
+*  osm_physp_share_pkey
+*
+* DESCRIPTION
+*  Checks if the given physical ports share a pkey.
+*  The meaning P_Key matching:
+*  10.9.3 :
+*   In the following, let M_P_Key(Message P_Key) be the P_Key in the incoming 
+*   packet and E_P_Key(Endnode P_Key) be the P_Key it is being compared against
+*   in the packet's destination endnode.
+*
+*    If:
+*    * neither M_P_Key nor E_P_Key are the invalid P_Key
+*    * and the low-order 15 bits of the M_P_Key match the low order 15
+*      bits of the E_P_Key
+*    * and the high order bit(membership type) of both the M_P_Key and
+*      E_P_Key are not both 0 (i.e., both are not Limited members of
+*      the partition)
+*
+*    then the P_Keys are said to match. 
+*
+* SYNOPSIS
+*/
+boolean_t osm_physp_share_pkey(
+  IN osm_log_t*          p_log,
+  IN const struct _osm_physp*  const p_physp_1,
+  IN const struct _osm_physp*  const p_physp_2 );
+
+/*
+* PARAMETERS
+*  p_log
+*     [in] Pointer to a log object.
+*
+*  p_physp_1
+*     [in] Pointer to an osm_physp_t object.
+*
+*  p_physp_2
+*     [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+*  Returns TRUE if the 2 physical ports are matching.
+*  FALSE otherwise.
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_port_share_pkey
+* NAME
+*  osm_port_share_pkey
+*
+* DESCRIPTION
+*  Checks if the given ports (on their default physical port) share a pkey.
+*  The meaning P_Key matching:
+*  10.9.3 :
+*   In the following, let M_P_Key(Message P_Key) be the P_Key in the incoming 
+*   packet and E_P_Key(Endnode P_Key) be the P_Key it is being compared against
+*   in the packet's destination endnode.
+*
+*    If:
+*    * neither M_P_Key nor E_P_Key are the invalid P_Key
+*    * and the low-order 15 bits of the M_P_Key match the low order 15
+*      bits of the E_P_Key
+*    * and the high order bit(membership type) of both the M_P_Key and
+*      E_P_Key are not both 0 (i.e., both are not Limited members of
+*      the partition)
+*
+*    then the P_Keys are said to match. 
+*
+* SYNOPSIS
+*/
+boolean_t osm_port_share_pkey(
+  IN osm_log_t*          p_log,
+  IN const struct _osm_port*   const p_port_1,
+  IN const struct _osm_port*   const p_port_2 );
+
+/*
+* PARAMETERS
+*  p_log
+*     [in] Pointer to a log object.
+*
+*  p_port_1
+*     [in] Pointer to an osm_port_t object.
+*
+*  p_port_2
+*     [in] Pointer to an osm_port_t object.
+*
+* RETURN VALUES
+*  Returns TRUE if the 2 ports are matching.
+*  FALSE otherwise.
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_lid_share_pkey
+* NAME
+*  osm_lid_share_pkey
+*
+* DESCRIPTION
+*  Checks if the given lids and port_numbers share a pkey.
+*  The meaning P_Key matching:
+*  10.9.3 :
+*   In the following, let M_P_Key(Message P_Key) be the P_Key in the incoming 
+*   packet and E_P_Key(Endnode P_Key) be the P_Key it is being compared against
+*   in the packet's destination endnode.
+*
+*    If:
+*    * neither M_P_Key nor E_P_Key are the invalid P_Key
+*    * and the low-order 15 bits of the M_P_Key match the low order 15
+*      bits of the E_P_Key
+*    * and the high order bit(membership type) of both the M_P_Key and
+*      E_P_Key are not both 0 (i.e., both are not Limited members of
+*      the partition)
+*
+*    then the P_Keys are said to match. 
+*
+* SYNOPSIS
+*/
+boolean_t osm_lid_share_pkey(
+  IN osm_log_t*          p_log,
+  IN const struct _osm_subn*  const p_subn,
+  IN const ib_net16_t    lid1,
+  IN const uint8_t       port_num1,
+  IN const ib_net16_t    lid2,
+  IN const uint8_t       port_num2 );
+
+/*
+* PARAMETERS
+*  p_log
+*     [in] Pointer to a log object.
+*
+*  p_subn
+*     [in] Pointer to the subnet object for accessing of the options.
+*
+*  lid1
+*     [in] lid number of first port.
+*
+*  port_num1
+*     [in] port number of first port.
+*
+*  lid2
+*     [in] lid number of second port.
+*
+*  port_num2
+*     [in] port number of second port.
+*
+* RETURN VALUES
+*  Returns TRUE if the 2 physical ports that belong to these lids/port_numbers
+*  are matching. FALSE otherwise.
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_physp_has_pkey
+* NAME
+*  osm_physp_has_pkey
+*
+* DESCRIPTION
+*  Checks if the given lids and port_numbers share a pkey.
+*  The meaning P_Key matching:
+*  10.9.3 :
+*   In the following, let M_P_Key(Message P_Key) be the P_Key in the incoming 
+*   packet and E_P_Key(Endnode P_Key) be the P_Key it is being compared against
+*   in the packet's destination endnode.
+*
+*    If:
+*    * neither M_P_Key nor E_P_Key are the invalid P_Key
+*    * and the low-order 15 bits of the M_P_Key match the low order 15
+*      bits of the E_P_Key
+*    * and the high order bit(membership type) of both the M_P_Key and
+*      E_P_Key are not both 0 (i.e., both are not Limited members of
+*      the partition)
+*
+*    then the P_Keys are said to match. 
+*
+* SYNOPSIS
+*/
+boolean_t osm_physp_has_pkey(
+  IN osm_log_t*               p_log,
+  IN const ib_net16_t         pkey,
+  IN const struct _osm_physp* const p_physp );
+
+/*
+* PARAMETERS
+*  p_log
+*     [in] Pointer to a log object.
+*
+*  pkey
+*     [in] pkey number to look for.
+*
+*  p_physp
+*     [in] Pointer to osm_physp_t object.
+*
+* RETURN VALUES
+*  Returns TRUE if the p_physp has the pkey given. False otherwise.
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_pkey_get_tables
+* NAME
+*  osm_pkey_get_tables
+*
+* DESCRIPTION
+*  Sends a request for getting the pkey tables of the given physp.
+*
+* SYNOPSIS
+*/
+void osm_pkey_get_tables(
+  IN osm_log_t                   *p_log, 
+  IN osm_req_t                   *p_req, 
+  IN osm_subn_t* const  p_subn,
+  IN struct _osm_node* const  p_node,
+  IN struct _osm_physp* const p_physp );
+
+/*
+* PARAMETERS
+*  p_log
+*     [in] Pointer to osm_log object.
+*
+*  p_req
+*     [in] Pointer to osm_req object.
+*
+*  p_subn
+*     [in] Pointer to osm_subn object.
+*
+*  p_node
+*     [in] Pointer to osm_node object.
+*
+*  p_physp
+*     [in] Pointer to osm_physp_t object.
+*
+* RETURN VALUES
+*  None
+*
+* NOTES
+*
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PKEY_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey_mgr.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey_mgr.h
new file mode 100644 (file)
index 0000000..4298017
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_pkey_mgr.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Prototype for osm_pkey_mgr_process() function
+ *     This is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_PKEY_MGR_H_
+#define _OSM_PKEY_MGR_H_
+
+#include <opensm/osm_base.h>
+#include <opensm/osm_opensm.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****f* OpenSM: P_Key Manager/osm_pkey_mgr_process
+* NAME
+*      osm_pkey_mgr_process
+*
+* DESCRIPTION
+*      This function enforces the pkey rules on the SM DB.
+*
+* SYNOPSIS
+*/
+osm_signal_t 
+osm_pkey_mgr_process(
+       IN osm_opensm_t *p_osm );
+/*
+* PARAMETERS
+*      p_osm
+*              [in] Pointer to an osm_opensm_t object.
+*
+* RETURN VALUES
+*      None
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PKEY_MGR_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey_rcv.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey_rcv.h
new file mode 100644 (file)
index 0000000..8e23505
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_pkey_rcv.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_PKEY_RCV_H_
+#define _OSM_PKEY_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/P_Key Receiver
+* NAME
+*  P_Key Receiver
+*
+* DESCRIPTION
+*  The P_Key Receiver object encapsulates the information
+*  needed to set or get the vl arbitration attribute from a port.
+*
+*  The P_Key Receiver object is thread safe.
+*
+*  This object should be treated as opaque and should be
+*  manipulated only through the provided functions.
+*
+* AUTHOR
+*  Yael Kalka, Mellanox
+*
+*********/
+
+/****s* OpenSM: P_Key Receiver/osm_pkey_rcv_t
+* NAME
+*  osm_pkey_rcv_t
+*
+* DESCRIPTION
+*  P_Key Receiver structure.
+*
+*  This object should be treated as opaque and should
+*  be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pkey_rcv
+{
+  osm_subn_t               *p_subn;
+  osm_req_t             *p_req;
+  osm_log_t             *p_log;
+  cl_plock_t               *p_lock;
+
+} osm_pkey_rcv_t;
+/*
+* FIELDS
+*  p_subn
+*     Pointer to the Subnet object for this subnet.
+*
+*  p_req
+*     Pointer to the generic attribute request object.
+*
+*  p_log
+*     Pointer to the log object.
+*
+*  p_lock
+*     Pointer to the serializing lock.
+*
+* SEE ALSO
+*  P_Key Receiver object
+*********/
+
+/****f* OpenSM: P_Key Receiver/osm_pkey_rcv_construct
+* NAME
+*  osm_pkey_rcv_construct
+*
+* DESCRIPTION
+*  This function constructs a P_Key Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_pkey_rcv_construct(
+  IN osm_pkey_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+*  p_ctrl
+*     [in] Pointer to a P_Key Receiver object to construct.
+*
+* RETURN VALUE
+*  This function does not return a value.
+*
+* NOTES
+*  Allows calling osm_pkey_rcv_destroy
+*
+*  Calling osm_pkey_rcv_construct is a prerequisite to calling any other
+*  method except osm_pkey_rcv_init.
+*
+* SEE ALSO
+*  P_Key Receiver object, osm_pkey_rcv_init,
+*  osm_pkey_rcv_destroy
+*********/
+
+/****f* OpenSM: P_Key Receiver/osm_pkey_rcv_destroy
+* NAME
+*  osm_pkey_rcv_destroy
+*
+* DESCRIPTION
+*  The osm_pkey_rcv_destroy function destroys the object, releasing
+*  all resources.
+*
+* SYNOPSIS
+*/
+void osm_pkey_rcv_destroy(
+  IN osm_pkey_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+*  p_ctrl
+*     [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*  This function does not return a value.
+*
+* NOTES
+*  Performs any necessary cleanup of the specified
+*  P_Key Receiver object.
+*  Further operations should not be attempted on the destroyed object.
+*  This function should only be called after a call to
+*  osm_pkey_rcv_construct or osm_pkey_rcv_init.
+*
+* SEE ALSO
+*  P_Key Receiver object, osm_pkey_rcv_construct,
+*  osm_pkey_rcv_init
+*********/
+
+/****f* OpenSM: P_Key Receiver/osm_pkey_rcv_init
+* NAME
+*  osm_pkey_rcv_init
+*
+* DESCRIPTION
+*  The osm_pkey_rcv_init function initializes a
+*  P_Key Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pkey_rcv_init(
+  IN osm_pkey_rcv_t* const p_ctrl,
+  IN osm_req_t* const p_req,
+  IN osm_subn_t* const p_subn,
+  IN osm_log_t* const p_log,
+  IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*  p_ctrl
+*     [in] Pointer to an osm_pkey_rcv_t object to initialize.
+*
+*  p_req
+*     [in] Pointer to an osm_req_t object.
+*
+*  p_subn
+*     [in] Pointer to the Subnet object for this subnet.
+*
+*  p_log
+*     [in] Pointer to the log object.
+*
+*  p_lock
+*     [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*  CL_SUCCESS if the P_Key Receiver object was initialized
+*  successfully.
+*
+* NOTES
+*  Allows calling other P_Key Receiver methods.
+*
+* SEE ALSO
+*  P_Key Receiver object, osm_pkey_rcv_construct,
+*  osm_pkey_rcv_destroy
+*********/
+
+/****f* OpenSM: P_Key Receiver/osm_pkey_rcv_process
+* NAME
+*  osm_pkey_rcv_process
+*
+* DESCRIPTION
+*  Process the vl arbitration attribute.
+*
+* SYNOPSIS
+*/
+void osm_pkey_rcv_process(
+  IN const osm_pkey_rcv_t* const p_ctrl,
+  IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*  p_ctrl
+*     [in] Pointer to an osm_pkey_rcv_t object.
+*
+*  p_madw
+*     [in] Pointer to the MAD Wrapper containing the MAD
+*     that contains the node's SLtoVL attribute.
+*
+* RETURN VALUES
+*  CL_SUCCESS if the SLtoVL processing was successful.
+*
+* NOTES
+*  This function processes a SLtoVL attribute.
+*
+* SEE ALSO
+*  P_Key Receiver, P_Key Response Controller
+*********/
+
+END_C_DECLS
+
+#endif   /* _OSM_PKEY_RCV_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey_rcv_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_pkey_rcv_ctrl.h
new file mode 100644 (file)
index 0000000..dfb7ea0
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_pkey_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_PKEY_RCV_CTRL_H_
+#define _OSM_PKEY_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_pkey_rcv.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/P_Key Table Receive Controller
+* NAME
+*  P_Key Receive Controller
+*
+* DESCRIPTION
+*  The P_Key Receive Controller object encapsulates
+*  the information needed to get or set P_Key table of a port.
+*
+*  The P_Key Receive Controller object is thread safe.
+*
+*  This object should be treated as opaque and should be
+*  manipulated only through the provided functions.
+*
+* AUTHOR
+*  Yael Kalka, Mellanox
+*
+*********/
+
+/****s* OpenSM: P_Key Receive Controller/osm_pkey_rcv_ctrl_t
+* NAME
+*  osm_pkey_rcv_ctrl_t
+*
+* DESCRIPTION
+*  P_Key Receive Controller structure.
+*
+*  This object should be treated as opaque and should
+*  be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pkey_rcv_ctrl
+{
+  osm_pkey_rcv_t        *p_rcv;
+  osm_log_t             *p_log;
+  cl_dispatcher_t       *p_disp;
+  cl_disp_reg_handle_t  h_disp;
+
+} osm_pkey_rcv_ctrl_t;
+/*
+* FIELDS
+*  p_rcv
+*     Pointer to the P_Key Receiver object.
+*
+*  p_log
+*     Pointer to the log object.
+*
+*  p_disp
+*     Pointer to the Dispatcher.
+*
+*  h_disp
+*     Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*  P_Key Receive Controller object
+*  P_Key Receiver object
+*********/
+
+/****f* OpenSM: P_Key Receive Controller/osm_pkey_rcv_ctrl_construct
+* NAME
+*  osm_pkey_rcv_ctrl_construct
+*
+* DESCRIPTION
+*  This function constructs a P_Key Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_pkey_rcv_ctrl_construct(
+  IN osm_pkey_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*  p_ctrl
+*     [in] Pointer to a P_Key Receive Controller
+*     object to construct.
+*
+* RETURN VALUE
+*  This function does not return a value.
+*
+* NOTES
+*  Allows calling osm_pkey_rcv_ctrl_init, osm_pkey_rcv_ctrl_destroy,
+*  and osm_pkey_rcv_ctrl_is_inited.
+*
+*  Calling osm_pkey_rcv_ctrl_construct is a prerequisite to calling any other
+*  method except osm_pkey_rcv_ctrl_init.
+*
+* SEE ALSO
+*  P_Key Receive Controller object, osm_pkey_rcv_ctrl_init,
+*  osm_pkey_rcv_ctrl_destroy, osm_pkey_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: P_Key Receive Controller/osm_pkey_rcv_ctrl_destroy
+* NAME
+*  osm_pkey_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*  The osm_pkey_rcv_ctrl_destroy function destroys the object, releasing
+*  all resources.
+*
+* SYNOPSIS
+*/
+void osm_pkey_rcv_ctrl_destroy(
+  IN osm_pkey_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*  p_ctrl
+*     [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*  This function does not return a value.
+*
+* NOTES
+*  Performs any necessary cleanup of the specified
+*  P_Key Receive Controller object.
+*  Further operations should not be attempted on the destroyed object.
+*  This function should only be called after a call to
+*  osm_pkey_rcv_ctrl_construct or osm_pkey_rcv_ctrl_init.
+*
+* SEE ALSO
+*  P_Key Receive Controller object, osm_pkey_rcv_ctrl_construct,
+*  osm_pkey_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: P_Key Receive Controller/osm_pkey_rcv_ctrl_init
+* NAME
+*  osm_pkey_rcv_ctrl_init
+*
+* DESCRIPTION
+*  The osm_pkey_rcv_ctrl_init function initializes a
+*  P_Key Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pkey_rcv_ctrl_init(
+  IN osm_pkey_rcv_ctrl_t* const p_ctrl,
+  IN osm_pkey_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*  p_ctrl
+*     [in] Pointer to an osm_pkey_rcv_ctrl_t object to initialize.
+*
+*  p_rcv
+*     [in] Pointer to an osm_pkey_rcv_t object.
+*
+*  p_log
+*     [in] Pointer to the log object.
+*
+*  p_disp
+*     [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*  CL_SUCCESS if the P_Key Receive Controller object was initialized
+*  successfully.
+*
+* NOTES
+*  Allows calling other P_Key Receive Controller methods.
+*
+* SEE ALSO
+*  P_Key Receive Controller object, osm_pkey_rcv_ctrl_construct,
+*  osm_pkey_rcv_ctrl_destroy, osm_pkey_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: P_Key Receive Controller/osm_pkey_rcv_ctrl_is_inited
+* NAME
+*  osm_pkey_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+*  Indicates if the object has been initialized with osm_pkey_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_pkey_rcv_ctrl_is_inited(
+  IN const osm_pkey_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*  p_ctrl
+*     [in] Pointer to an osm_pkey_rcv_ctrl_t object.
+*
+* RETURN VALUES
+*  TRUE if the object was initialized successfully,
+*  FALSE otherwise.
+*
+* NOTES
+*  The osm_pkey_rcv_ctrl_construct or osm_pkey_rcv_ctrl_init must be
+*  called before using this function.
+*
+* SEE ALSO
+*  P_Key Receive Controller object, osm_pkey_rcv_ctrl_construct,
+*  osm_pkey_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif   /* _OSM_PKEY_RCV_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port.h
new file mode 100644 (file)
index 0000000..5d9ecf4
--- /dev/null
@@ -0,0 +1,2122 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_port.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of port related objects.
+ *     These objects comprise an IBA port.
+ *     These objects are part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.8 $
+ */
+
+#ifndef _OSM_PORT_H_
+#define _OSM_PORT_H_
+
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_qmap.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_path.h>
+#include <opensm/osm_pkey.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/*
+       Forward references.
+*/
+struct _osm_port;
+struct _osm_node;
+
+/****h* OpenSM/Physical Port
+* NAME
+*      Physical Port
+*
+* DESCRIPTION
+*      The Physical Port object encapsulates the information needed by the
+*      OpenSM to manage physical ports.  The OpenSM allocates one Physical Port
+*      per physical port in the IBA subnet.
+*
+*      In a switch, one multiple Physical Port objects share the same port GUID.
+*      In an end-point, Physical Ports do not share GUID values.
+*
+*      The Physical Port is not thread safe, thus callers must provide
+*      serialization.
+*
+*      These objects should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Physical Port/osm_physp_t
+* NAME
+*      osm_physp_t
+*
+* DESCRIPTION
+*      This object represents a physical port on a switch, router or end-point.
+*
+*      The osm_physp_t object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_physp
+{
+  ib_port_info_t                port_info;
+  ib_net64_t                    port_guid;
+  uint8_t                       port_num;
+  struct _osm_node             *p_node;
+  struct _osm_physp            *p_remote_physp;
+  boolean_t                      healthy;
+  osm_dr_path_t                         dr_path;
+  osm_pkey_tbl_t                 pkeys;
+  ib_vl_arb_table_t              vl_arb[4];
+  cl_ptr_vector_t                slvl_by_port;
+  boolean_t                      got_set_resp;
+} osm_physp_t;
+/*
+* FIELDS
+*      port_info
+*              The IBA defined PortInfo data for this port.
+*
+*      port_guid
+*              Port GUID value of this port.  For switches,
+*              all ports share the same GUID value.
+*
+*      port_num
+*              The port number of this port.  The PortInfo also
+*              contains a port_number, but that number is not
+*              the port number of this port, but rather the number
+*              of the port that received the SMP during discovery.
+*              Therefore, we must keep a separate record for this
+*              port's port number.
+*
+*      p_node
+*              Pointer to the parent Node object of this Physical Port.
+*
+*      p_remote_physp
+*              Pointer to the Physical Port on the other side of the wire.
+*              If this pointer is NULL no link exists at this port.
+*
+*      healthy
+*              Tracks the health of the port. Normally should be TRUE but 
+*              might change as a result of incoming traps indicating the port
+*              healthy is questionable.
+*
+*      dr_path
+*              The directed route path to this port.
+*
+*      pkeys
+*              osm_pkey_tbl_t object holding the port PKeys.
+*
+*      vl_arb[]
+*              Each Physical Port has 4 sections of VL Arbitration table.
+*
+*      slvl_by_port
+*              A vector of pointers to the sl2vl tables (ordered by input port).
+*              On switches have an entry for every other input port (inc SMA=0).
+*              On CAs only one per port.
+*
+*      got_set_resp
+*              Marks whether or not we got a PortInfoSetResp from this port or not.
+*              This is used for minimizing the number of PortInfoSet requests sent.
+*              If we already got a set response from this port, then we will
+*              send a PortInfoSet only if the values we are updating are
+*              different than the ones on the port. If the haven't gotten a set
+*              response - then we want to send the request anyways - since
+*              every we need at least one PortInfoSet request for every port
+*              (by a new SM).
+*
+* SEE ALSO
+*      Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_construct
+* NAME
+*      osm_physp_construct
+*
+* DESCRIPTION
+*      Constructs a Physical Port.
+*
+* SYNOPSIS
+*/
+void
+osm_physp_construct(
+       IN osm_physp_t* const p_physp );
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object to initialize.
+*
+* RETURN VALUES
+*      This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_init
+* NAME
+*      osm_physp_init
+*
+* DESCRIPTION
+*      Initializes a Physical Port for use.
+*
+* SYNOPSIS
+*/
+void
+osm_physp_init(
+       IN osm_physp_t* const p_physp,
+       IN const ib_net64_t port_guid,
+       IN const uint8_t port_num,
+       IN const struct _osm_node* const p_node,
+       IN const osm_bind_handle_t h_bind,
+       IN const uint8_t hop_count,
+       IN const uint8_t* const p_initial_path );
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object to initialize.
+*
+*      port_guid
+*              [in] GUID value of this port.  Switch ports all share
+*              the same value.
+*              Caller should use 0 if the guid is unknown.
+*
+*      port_num
+*              [in] The port number of this port.
+*
+*      p_node
+*              [in] Pointer to the parent Node object of this Physical Port.
+*
+*      h_bind
+*              [in] Bind handle on which this port is accessed.
+*              Caller should use OSM_INVALID_BIND_HANDLE if the bind
+*              handle to this port is unknown.
+*
+*      hop_count
+*              [in] Directed route hop count to reach this port.
+*              Caller should use 0 if the hop count is unknown.
+*
+*      p_initial_path
+*              [in] Pointer to the directed route path to reach this node.
+*              Caller should use NULL if the path is unknown.
+*
+* RETURN VALUES
+*      This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port, Physical Port
+*********/
+
+/****f* OpenSM: Port/void osm_physp_destroy
+* NAME
+*      osm_physp_destroy
+*
+* DESCRIPTION
+*      This function destroys a Port object.
+*
+* SYNOPSIS
+*/
+void
+osm_physp_destroy(
+  IN osm_physp_t* const p_physp );
+/*
+* PARAMETERS
+*      p_port
+*              [in] Pointer to a PhysPort object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified PhysPort object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to osm_physp_construct or
+*      osm_physp_init.
+*
+* SEE ALSO
+*      Port, osm_port_init, osm_port_destroy
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_is_valid
+* NAME
+*      osm_physp_is_valid
+*
+* DESCRIPTION
+*      Returns TRUE if the Physical Port has been successfully initialized.
+*      FALSE otherwise.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_physp_is_valid(
+       IN const osm_physp_t* const p_physp )
+{
+       CL_ASSERT( p_physp );
+       return( p_physp->port_guid != 0 );
+}
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+*      Returns TRUE if the Physical Port has been successfully initialized.
+*      FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_is_healthy
+* NAME
+*      osm_physp_is_healthy
+*
+* DESCRIPTION
+*      Returns TRUE if the Physical Port has been maked as healthy
+*      FALSE otherwise.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_physp_is_healthy(
+       IN const osm_physp_t* const p_physp )
+{
+       CL_ASSERT( p_physp );
+       return( p_physp->healthy );
+}
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+*      Returns TRUE if the Physical Port has been maked as healthy
+*      FALSE otherwise.
+*  All physical ports are initialized as "healthy" but may be marked 
+*  otherwise if a received trap claims otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_link_is_healthy
+* NAME
+*      osm_link_is_healthy
+*
+* DESCRIPTION
+*      Returns TRUE if the link given by the physical port is health,
+*  and FALSE otherwise. Link is healthy if both its physical ports are 
+*  healthy
+*
+* SYNOPSIS
+*/
+boolean_t
+osm_link_is_healthy(
+  IN const osm_physp_t* const p_physp );
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+*      TRUE if both physical ports on the link are healthy, and FALSE otherwise.
+*  All physical ports are initialized as "healthy" but may be marked 
+*  otherwise if a received trap claiming otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_set_health
+* NAME
+*      osm_physp_set_health
+*
+* DESCRIPTION
+*      Sets the port health flag. TRUE means the port is healthy and 
+*  should be used for packet routing. FALSE means it should be avoided.
+*
+* SYNOPSIS
+*/
+static inline void 
+osm_physp_set_health(
+  IN osm_physp_t* const p_physp,
+  IN boolean_t is_healthy )
+{
+       CL_ASSERT( p_physp );
+       p_physp->healthy = is_healthy;
+}
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+*      is_healthy
+*              [in] The health value to be assigned to the port.
+*                   TRUE if the Physical Port should been maked as healthy
+*                   FALSE otherwise.
+*
+* RETURN VALUES
+*  NONE 
+*
+* NOTES
+*
+* SEE ALSO
+*      Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_set_port_info
+* NAME
+*      osm_physp_set_port_info
+*
+* DESCRIPTION
+*      Copies the PortInfo attribute into the Physical Port object
+*      based on the PortState.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_physp_set_port_info(
+       IN osm_physp_t* const p_physp,
+       IN const ib_port_info_t* const p_pi )
+{
+       CL_ASSERT( p_pi );
+       CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+       if (ib_port_info_get_port_state(p_pi) == IB_LINK_DOWN)
+       {
+         /* If PortState is down, only copy PortState */
+         /* and PortPhysicalState per C14-24-2.1 */
+         ib_port_info_set_port_state(&p_physp->port_info, IB_LINK_DOWN);
+         ib_port_info_set_port_phys_state(
+               ib_port_info_get_port_phys_state(p_pi), &p_physp->port_info);
+       }
+       else
+       {
+         p_physp->port_info = *p_pi;
+       }
+}
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+*      p_pi
+*              [in] Pointer to the IBA defined PortInfo at this port number.
+*
+* RETURN VALUES
+*      This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_trim_base_lid_to_valid_range
+* NAME
+*  osm_physp_trim_base_lid_to_valid_range 
+*
+* DESCRIPTION
+*  Validates the base LID in the Physical Port object
+*  and resets it if the base LID is invalid.
+*
+* SYNOPSIS
+*/
+static inline ib_net16_t 
+osm_physp_trim_base_lid_to_valid_range(
+       IN osm_physp_t* const p_physp )
+{
+       ib_net16_t orig_lid = 0;
+
+       CL_ASSERT( osm_physp_is_valid( p_physp ) );
+       if ( ( cl_ntoh16( p_physp->port_info.base_lid ) > IB_LID_UCAST_END_HO ) ||
+             ( cl_ntoh16( p_physp->port_info.base_lid ) < IB_LID_UCAST_START_HO ) )
+       {
+               orig_lid = p_physp->port_info.base_lid;
+               p_physp->port_info.base_lid = 0;
+       }
+       return orig_lid;
+}
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+*      Returns 0 if the base LID in the Physical port object is valid.
+*      Returns original invalid LID otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_set_pkey_tbl
+* NAME
+*  osm_physp_set_pkey_tbl
+*
+* DESCRIPTION
+*  Copies the P_Key table into the Physical Port object.
+*
+* SYNOPSIS
+*/
+void 
+osm_physp_set_pkey_tbl( IN osm_log_t* p_log,
+                        IN const osm_subn_t* p_subn,
+                        IN osm_physp_t* const p_physp,
+                        IN ib_pkey_table_t *p_pkey_tbl,
+                        IN uint16_t block_num );
+/*
+* PARAMETERS
+*      p_log
+*              [in] Pointer to a log object.
+*
+*      p_subn
+*              [in] Pointer to the subnet data structure.
+*
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+*      p_pkey_tbl
+*              [in] Pointer to the IBA defined P_Key table for this port
+*                   number.
+*
+*      block_num
+*              [in] The part of the P_Key table as defined in the IBA
+*                   (valid values 0-2047, and is further limited by the
+*                   partitionCap).
+*
+* RETURN VALUES
+*  This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+*  Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_get_pkey_tbl
+* NAME
+*  osm_physp_get_pkey_tbl
+*
+* DESCRIPTION
+*  Returns a pointer to the P_Key table object of the Physical Port object.
+*
+* SYNOPSIS
+*/
+static inline const osm_pkey_tbl_t *
+osm_physp_get_pkey_tbl( IN const osm_physp_t* const p_physp )
+{
+  CL_ASSERT( osm_physp_is_valid( p_physp ) );
+  /*
+    (14.2.5.7) - the block number valid values are 0-2047, and are further
+    limited by the size of the P_Key table specified by the PartitionCap on the node. 
+  */
+  return( &p_physp->pkeys );
+};
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+*  The pointer to the P_Key table object.
+*
+* NOTES
+*
+* SEE ALSO
+*  Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_get_mod_pkey_tbl
+* NAME
+*  osm_physp_get_mod_pkey_tbl
+*
+* DESCRIPTION
+*  Returns a NON CONST pointer to the P_Key table object of the Physical Port object.
+*
+* SYNOPSIS
+*/
+static inline osm_pkey_tbl_t *
+osm_physp_get_mod_pkey_tbl( IN osm_physp_t* const p_physp )
+{
+  CL_ASSERT( osm_physp_is_valid( p_physp ) );
+  /*
+    (14.2.5.7) - the block number valid values are 0-2047, and are further
+    limited by the size of the P_Key table specified by the PartitionCap on the node. 
+  */
+  return( &p_physp->pkeys );
+};
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+*  The pointer to the P_Key table object.
+*
+* NOTES
+*
+* SEE ALSO
+*  Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_set_slvl_tbl
+* NAME
+*      osm_physp_set_slvl_tbl
+*
+* DESCRIPTION
+*      Copies the SLtoVL attribute into the Physical Port object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_physp_set_slvl_tbl( IN osm_physp_t* const p_physp,
+                       IN ib_slvl_table_t *p_slvl_tbl, 
+                       IN uint8_t in_port_num )
+{
+  ib_slvl_table_t *p_tbl;
+
+  CL_ASSERT( p_slvl_tbl );
+  CL_ASSERT( osm_physp_is_valid( p_physp ) );
+  p_tbl = cl_ptr_vector_get(&p_physp->slvl_by_port, in_port_num);
+  *p_tbl = *p_slvl_tbl;
+}
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+*      p_slvl_tbl
+*              [in] Pointer to the IBA defined SLtoVL map table for this port number.
+*
+*      in_port_num
+*              [in] Input Port Number for this SLtoVL.
+*
+* RETURN VALUES
+*      This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_get_slvl_tbl
+* NAME
+*      osm_physp_get_slvl_tbl
+*
+* DESCRIPTION
+*      Returns a pointer to the SLtoVL attribute of the Physical Port object.
+*
+* SYNOPSIS
+*/
+static inline ib_slvl_table_t *
+osm_physp_get_slvl_tbl( IN const osm_physp_t* const p_physp,
+                       IN uint8_t in_port_num )
+{
+  ib_slvl_table_t *p_tbl;
+
+  CL_ASSERT( osm_physp_is_valid( p_physp ) );
+  p_tbl = cl_ptr_vector_get(&p_physp->slvl_by_port, in_port_num);
+  return(p_tbl);
+}
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+*      in_port_num
+*              [in] Input Port Number for this SLtoVL.
+*
+* RETURN VALUES
+*      The pointer to the slvl table
+*
+* NOTES
+*
+* SEE ALSO
+*      Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_set_vla_tbl
+* NAME
+*      osm_physp_set_vla_tbl
+*
+* DESCRIPTION
+*      Copies the VL Arbitration attribute into the Physical Port object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_physp_set_vla_tbl( IN osm_physp_t* const p_physp,
+                      IN ib_vl_arb_table_t *p_vla_tbl, 
+                      IN uint8_t block_num )
+{
+  CL_ASSERT( p_vla_tbl );
+  CL_ASSERT( osm_physp_is_valid( p_physp ) );
+  CL_ASSERT( (1 <= block_num) && (block_num <= 4));
+  p_physp->vl_arb[block_num - 1] = *p_vla_tbl;
+}
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+*      p_vla_tbl
+*              [in] Pointer to the IBA defined VL Arbitration table for this port number.
+*
+*      block_num
+*              [in] The part of the VL arbitration as defined in the IBA
+*                   (valid values 1-4)
+*
+* RETURN VALUES
+*      This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_get_vla_tbl
+* NAME
+*      osm_physp_get_vla_tbl
+*
+* DESCRIPTION
+*      Returns a pointer to the VL Arbitration table of the Physical Port object.
+*
+* SYNOPSIS
+*/
+static inline ib_vl_arb_table_t *
+osm_physp_get_vla_tbl( IN osm_physp_t* const p_physp,
+                      IN uint8_t block_num )
+{
+  CL_ASSERT( osm_physp_is_valid( p_physp ) );
+  CL_ASSERT( (1 <= block_num) && (block_num <= 4));
+  return(& (p_physp->vl_arb[block_num - 1]));
+}
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+*      block_num
+*              [in] The part of the VL arbitration as defined in the IBA
+*                   (valid values 1-4)
+*
+* RETURN VALUES
+*  The pointer to the VL Arbitration table
+*
+* NOTES
+*
+* SEE ALSO
+*      Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_get_remote
+* NAME
+*      osm_physp_get_remote
+*
+* DESCRIPTION
+*      Returns a pointer to the Physical Port on the other side the wire.
+*
+* SYNOPSIS
+*/
+static inline osm_physp_t*
+osm_physp_get_remote(
+       IN const osm_physp_t* const p_physp )
+{
+       CL_ASSERT( osm_physp_is_valid( p_physp ) );
+       return( p_physp->p_remote_physp );
+}
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+*      Returns a pointer to the Physical Port on the other side of
+*      the wire.  A return value of NULL means there is no link at this port.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_get_port_guid
+* NAME
+*      osm_physp_get_port_guid
+*
+* DESCRIPTION
+*      Returns the port guid of this physical port.
+*
+* SYNOPSIS
+*/
+static inline ib_net64_t
+osm_physp_get_port_guid(
+       IN const osm_physp_t* const p_physp )
+{
+       CL_ASSERT( osm_physp_is_valid( p_physp ) );
+       return( p_physp->port_guid );
+}
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+*      Returns the port guid of this physical port.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_get_subnet_prefix
+* NAME
+*      osm_physp_get_subnet_prefix
+*
+* DESCRIPTION
+*      Returns the subnet prefix for this physical port.
+*
+* SYNOPSIS
+*/
+static inline ib_net64_t
+osm_physp_get_subnet_prefix(
+       IN const osm_physp_t* const p_physp )
+{
+       CL_ASSERT( osm_physp_is_valid( p_physp ) );
+       return( p_physp->port_info.subnet_prefix );
+}
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+*      Returns the subnet prefix for this physical port.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_link_exists
+* NAME
+*      osm_physp_link_exists
+*
+* DESCRIPTION
+*      Returns TRUE if the Physical Port has a link to the specified port.
+*      FALSE otherwise.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_physp_link_exists(
+       IN const osm_physp_t* const p_physp,
+       IN const osm_physp_t* const p_remote_physp )
+{
+       CL_ASSERT( p_physp );
+       CL_ASSERT( osm_physp_is_valid( p_physp ) );
+       CL_ASSERT( p_remote_physp );
+       CL_ASSERT( osm_physp_is_valid( p_remote_physp ) );
+       return(  (p_physp->p_remote_physp == p_remote_physp ) &&
+                       (p_remote_physp->p_remote_physp == p_physp ) );
+}
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+*      p_remote_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+*      Returns TRUE if the Physical Port has a link to another port.
+*      FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_link
+* NAME
+*      osm_physp_link
+*
+* DESCRIPTION
+*      Sets the pointers to the Physical Ports on the other side the wire.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_physp_link(
+       IN osm_physp_t* const p_physp,
+       IN osm_physp_t* const p_remote_physp )
+{
+       CL_ASSERT( p_physp );
+       CL_ASSERT( p_remote_physp );
+       p_physp->p_remote_physp = p_remote_physp;
+       p_remote_physp->p_remote_physp = p_physp;
+}
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object to link.
+*
+*      p_remote_physp
+*              [in] Pointer to the adjacent osm_physp_t object to link.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_unlink
+* NAME
+*      osm_physp_unlink
+*
+* DESCRIPTION
+*      Clears the pointers to the Physical Port on the other side the wire.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_physp_unlink(
+       IN osm_physp_t* const p_physp,
+       IN osm_physp_t* const p_remote_physp )
+{
+       CL_ASSERT( p_physp );
+       CL_ASSERT( p_remote_physp );
+       CL_ASSERT( osm_physp_link_exists( p_physp, p_remote_physp ) );
+       p_physp->p_remote_physp = NULL;
+       p_remote_physp->p_remote_physp = NULL;
+}
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object to link.
+*
+*      p_remote_physp
+*              [in] Pointer to the adjacent osm_physp_t object to link.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_has_any_link
+* NAME
+*      osm_physp_has_any_link
+*
+* DESCRIPTION
+*      Returns TRUE if the Physical Port has a link to another port.
+*      FALSE otherwise.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_physp_has_any_link(
+       IN const osm_physp_t* const p_physp )
+{
+       CL_ASSERT( p_physp );
+       if( osm_physp_is_valid( p_physp ) )
+               return( p_physp->p_remote_physp != NULL );
+       else
+               return( FALSE );
+}
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+*      Returns TRUE if the Physical Port has a link to another port.
+*      FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_get_port_num
+* NAME
+*      osm_physp_get_port_num
+*
+* DESCRIPTION
+*      Returns the local port number of this Physical Port.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_physp_get_port_num(
+       IN const osm_physp_t* const p_physp )
+{
+       CL_ASSERT( p_physp );
+       CL_ASSERT( osm_physp_is_valid( p_physp ) );
+       return( p_physp->port_num );
+}
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+*      Returns the local port number of this Physical Port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_get_port_info_ptr
+* NAME
+*      osm_physp_get_port_info_ptr
+*
+* DESCRIPTION
+*      Returns a pointer to the PortInfo attribute for this port.
+*
+* SYNOPSIS
+*/
+static inline ib_port_info_t*
+osm_physp_get_port_info_ptr(
+       IN const osm_physp_t* const p_physp )
+{
+       CL_ASSERT( p_physp );
+       CL_ASSERT( osm_physp_is_valid( p_physp ) );
+       return( (ib_port_info_t*)&p_physp->port_info );
+}
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+*      Returns a pointer to the PortInfo attribute for this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_get_node_ptr
+* NAME
+*      osm_physp_get_node_ptr
+*
+* DESCRIPTION
+*      Returns a pointer to the parent Node object for this port.
+*
+* SYNOPSIS
+*/
+static inline struct _osm_node*
+osm_physp_get_node_ptr(
+       IN const osm_physp_t* const p_physp )
+{
+       CL_ASSERT( p_physp );
+       CL_ASSERT( osm_physp_is_valid( p_physp ) );
+       return( (struct _osm_node*)p_physp->p_node );
+}
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+*      Returns a pointer to the parent Node object for this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_get_port_state
+* NAME
+*      osm_physp_get_port_state
+*
+* DESCRIPTION
+*      Returns the port state of this Physical Port.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_physp_get_port_state(
+       IN const osm_physp_t* const p_physp )
+{
+       CL_ASSERT( p_physp );
+       CL_ASSERT( osm_physp_is_valid( p_physp ) );
+       return( ib_port_info_get_port_state( &p_physp->port_info ));
+}
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+*      Returns the local port number of this Physical Port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_get_base_lid
+* NAME
+*      osm_physp_get_base_lid
+*
+* DESCRIPTION
+*      Returns the base lid of this Physical Port.
+*
+* SYNOPSIS
+*/
+static inline ib_net16_t
+osm_physp_get_base_lid(
+       IN const osm_physp_t* const p_physp )
+{
+       CL_ASSERT( p_physp );
+       CL_ASSERT( osm_physp_is_valid( p_physp ) );
+       return( p_physp->port_info.base_lid );
+}
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+*      Returns the base lid of this Physical Port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_get_lmc
+* NAME
+*      osm_physp_get_lmc
+*
+* DESCRIPTION
+*      Returns the LMC value of this Physical Port.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_physp_get_lmc(
+       IN const osm_physp_t* const p_physp )
+{
+       CL_ASSERT( p_physp );
+       CL_ASSERT( osm_physp_is_valid( p_physp ) );
+       return( ib_port_info_get_lmc( &p_physp->port_info ) );
+}
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+*      Returns the LMC value of this Physical Port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_get_dr_path_ptr
+* NAME
+*      osm_physp_get_dr_path_ptr
+*
+* DESCRIPTION
+*      Returns a pointer to the directed route path for this port.
+*
+* SYNOPSIS
+*/
+static inline osm_dr_path_t*
+osm_physp_get_dr_path_ptr(
+       IN const osm_physp_t* const p_physp )
+{
+       CL_ASSERT( p_physp );
+       CL_ASSERT( osm_physp_is_valid( p_physp ) );
+       return( (osm_dr_path_t*)&p_physp->dr_path );
+}
+/*
+* PARAMETERS
+*      p_physp
+*              [in] Pointer to a Physical Port object.
+*
+* RETURN VALUES
+*      Returns a pointer to the directed route path for this port.
+*
+* NOTES
+*
+* SEE ALSO
+*      Physical Port object
+*********/
+
+/****h* OpenSM/Port
+* NAME
+*      Port
+*
+* DESCRIPTION
+*      The Port object encapsulates the information needed by the
+*      OpenSM to manage ports.  The OpenSM allocates one Port object
+*      per port in the IBA subnet.
+*
+*      Each Port object is associated with a single port GUID.  A Port object
+*      contains 1 or more Physical Port objects.  An end point node has
+*      one Physical Port per Port.  A switch node has more than
+*      one Physical Port per Port.
+*
+*      The Port object is not thread safe, thus callers must provide
+*      serialization.
+*
+*      These objects should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****d* OpenSM: Port/osm_port_lid_category_t
+* NAME
+*      osm_port_lid_category_t
+*
+* DESCRIPTION
+*      Enumerated values for LID disposition.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_port_lid_category
+{
+       OSM_PORT_LID_ASSIGNED = 0,
+       OSM_PORT_LID_UNASSIGNED,
+       OSM_PORT_LID_CONFLICT,
+       OSM_PORT_LID_FOREIGN,
+
+} osm_port_lid_category_t;
+/*
+* FIELDS
+*      OSM_PORT_LID_ASSIGNED
+*              Indicates the Port has a known LID value.
+*
+*      OSM_PORT_LID_UNASSIGNED
+*              Indicates the Port does not have a LID value.
+*
+*      OSM_PORT_LID_CONFLICT
+*              Indicates the Port's LID conflicts with an assigned LID.
+*
+*      OSM_PORT_LID_FOREIGN
+*              Indicates the Port has a LID value not currently known in
+*              in the OpenSM LID database.
+*
+* SEE ALSO
+*      Port
+*********/
+
+/****s* OpenSM: Port/osm_port_t
+* NAME
+*      osm_port_t
+*
+* DESCRIPTION
+*      This object represents a logical port on a switch, router or end-point.
+*
+*      The osm_port_t object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_port
+{
+       cl_map_item_t                   map_item;
+       struct _osm_node                *p_node;
+       ib_net64_t                      guid;
+       uint32_t                        discovery_count;
+       uint8_t                         default_port_num;
+       uint8_t                         physp_tbl_size;
+       cl_qlist_t                      mcm_list;
+       osm_physp_t                     *tbl[1];
+} osm_port_t;
+/*
+* FIELDS
+*      map_item
+*              Linkage structure for cl_qmap.  MUST BE FIRST MEMBER!
+*
+*      p_node
+*              Points to the Node object that owns this port.
+*
+*      guid
+*              Manufacturer assigned GUID for this port.
+*
+*      discovery_count
+*              The number of times this port has been discovered
+*              during the current fabric sweep.  This number is reset
+*              to zero at the start of a sweep.
+*
+*      default_port_num
+*              Index of the physical port used when physical characteristics
+*              contained in the Physical Port are needed.
+*
+*      physp_tbl_size
+*              Number of physical ports associated with this logical port.
+*
+*      mcm_list
+*              Multicast member list
+*
+*      tbl
+*              Array of pointers to Physical Port objects contained by this node.
+*     MUST BE LAST ELEMENT SINCE IT CAN GROW !!!
+*
+* SEE ALSO
+*      Port, Physical Port, Physical Port Table
+*********/
+
+/****f* OpenSM: Port/osm_port_construct
+* NAME
+*      osm_port_construct
+*
+* DESCRIPTION
+*      This function constructs a Port object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_port_construct(
+       IN osm_port_t* const p_port )
+{
+       memset( p_port, 0, sizeof(*p_port) );
+       cl_qlist_init( &p_port->mcm_list );
+}
+/*
+* PARAMETERS
+*      p_port
+*              [in] Pointer to a Port object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_port_init, and osm_port_destroy.
+*
+*      Calling osm_port_construct is a prerequisite to calling any other
+*      method except osm_port_init.
+*
+* SEE ALSO
+*      Port, osm_port_init, osm_port_destroy
+*********/
+
+/****f* OpenSM: Port/osm_port_destroy
+* NAME
+*      osm_port_destroy
+*
+* DESCRIPTION
+*      This function destroys a Port object.
+*
+* SYNOPSIS
+*/
+void
+osm_port_destroy(
+  IN osm_port_t* const p_port );
+/*
+* PARAMETERS
+*      p_port
+*              [in] Pointer to a Port object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified Port object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to osm_port_construct
+*      or osm_port_init.
+*
+* SEE ALSO
+*      Port, osm_port_init, osm_port_destroy
+*********/
+
+/****f* OpenSM: Port/osm_port_delete
+* NAME
+*      osm_port_delete
+*
+* DESCRIPTION
+*      This function destroys and deallocates a Port object.
+*
+* SYNOPSIS
+*/
+inline static void
+osm_port_delete(
+       IN OUT osm_port_t** const pp_port )
+{
+       osm_port_destroy( *pp_port );
+       free( *pp_port );
+       *pp_port = NULL;
+}
+/*
+* PARAMETERS
+*      pp_port
+*              [in][out] Pointer to a pointer to a Port object to delete.
+*              On return, this pointer is NULL.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified Port object.
+*
+* SEE ALSO
+*      Port, osm_port_init, osm_port_destroy
+*********/
+
+/****f* OpenSM: Port/osm_port_init
+* NAME
+*      osm_port_init
+*
+* DESCRIPTION
+*      This function initializes a Port object.
+*
+* SYNOPSIS
+*/
+void
+osm_port_init(
+       IN osm_port_t* const p_port,
+       IN const ib_node_info_t* p_ni,
+       IN const struct _osm_node* const p_parent_node );
+/*
+* PARAMETERS
+*      p_port
+*              [in] Pointer to a Port object to initialize.
+*
+*      p_ni
+*              [in] Pointer to the NodeInfo attribute relavent for this port.
+*
+*      p_parent_node
+*              [in] Pointer to the initialized parent osm_node_t object
+*              that owns this port.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*      Allows calling other port methods.
+*
+* SEE ALSO
+*      Port
+*********/
+
+/****f* OpenSM: Port/osm_port_new
+* NAME
+*      osm_port_new
+*
+* DESCRIPTION
+*      This function allocates and initializes a Port object.
+*
+* SYNOPSIS
+*/
+osm_port_t*
+osm_port_new(
+       IN const ib_node_info_t* p_ni,
+       IN const struct _osm_node* const p_parent_node );
+/*
+* PARAMETERS
+*      p_ni
+*              [in] Pointer to the NodeInfo attribute relavent for this port.
+*
+*      p_parent_node
+*              [in] Pointer to the initialized parent osm_node_t object
+*              that owns this port.
+*
+* RETURN VALUE
+*      Pointer to the initialize Port object.
+*
+* NOTES
+*      Allows calling other port methods.
+*
+* SEE ALSO
+*      Port
+*********/
+
+/****f* OpenSM: Port/osm_port_get_base_lid
+* NAME
+*      osm_port_get_base_lid
+*
+* DESCRIPTION
+*      Gets the base LID of a port.
+*
+* SYNOPSIS
+*/
+static inline ib_net16_t
+osm_port_get_base_lid(
+       IN const osm_port_t* const p_port )
+{
+       const osm_physp_t* const p_physp = p_port->tbl[p_port->default_port_num];
+       CL_ASSERT( p_physp );
+       CL_ASSERT( osm_physp_is_valid( p_physp ) );
+       return( osm_physp_get_base_lid( p_physp ));
+}
+/*
+* PARAMETERS
+*      p_port
+*              [in] Pointer to a Port object.
+*
+* RETURN VALUE
+*      Base LID of the port.
+*      If the return value is 0, then this port has no assigned LID.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port
+*********/
+
+/****f* OpenSM: Port/osm_port_get_lmc
+* NAME
+*      osm_port_get_lmc
+*
+* DESCRIPTION
+*      Gets the LMC value of a port.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_port_get_lmc(
+       IN const osm_port_t* const p_port )
+{
+       const osm_physp_t* const p_physp = p_port->tbl[p_port->default_port_num];
+       CL_ASSERT( p_physp );
+       CL_ASSERT( osm_physp_is_valid( p_physp ) );
+       return( osm_physp_get_lmc( p_physp ));
+}
+/*
+* PARAMETERS
+*      p_port
+*              [in] Pointer to a Port object.
+*
+* RETURN VALUE
+*      Gets the LMC value of a port.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port
+*********/
+
+/****f* OpenSM: Port/osm_port_get_guid
+* NAME
+*      osm_port_get_guid
+*
+* DESCRIPTION
+*      Gets the GUID of a port.
+*
+* SYNOPSIS
+*/
+static inline ib_net64_t
+osm_port_get_guid(
+       IN const osm_port_t* const p_port )
+{
+       return( p_port->guid );
+}
+/*
+* PARAMETERS
+*      p_port
+*              [in] Pointer to a Port object.
+*
+* RETURN VALUE
+*      Manufacturer assigned GUID of the port.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port
+*********/
+
+/****f* OpenSM: Port/osm_port_get_num_physp
+* NAME
+*      osm_port_get_num_physp
+*
+* DESCRIPTION
+*      Returns the number of Physical Port objects associated with this port.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_port_get_num_physp(
+       IN const osm_port_t* const p_port )
+{
+       return( p_port->physp_tbl_size );
+}
+/*
+* PARAMETERS
+*      p_port
+*              [in] Pointer to a Port object.
+*
+* RETURN VALUE
+*      Returns the number of Physical Port objects associated with this port.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port
+*********/
+
+/****f* OpenSM: Port/osm_port_get_phys_ptr
+* NAME
+*      osm_port_get_phys_ptr
+*
+* DESCRIPTION
+*      Gets the pointer to the specified Physical Port object.
+*
+* SYNOPSIS
+*/
+static inline osm_physp_t*
+osm_port_get_phys_ptr(
+       IN const osm_port_t* const p_port,
+       IN const uint8_t port_num )
+{
+       CL_ASSERT( port_num < p_port->physp_tbl_size );
+       return( p_port->tbl[port_num] );
+}
+/*
+* PARAMETERS
+*      p_port
+*              [in] Pointer to a Port object.
+*
+*      port_num
+*              [in] Number of physical port for which to return the
+*              osm_physp_t object.  If this port is on an HCA, then
+*              this value is ignored.
+*
+* RETURN VALUE
+*      Pointer to the Physical Port object.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port
+*********/
+
+/****f* OpenSM: Port/osm_port_get_default_phys_ptr
+* NAME
+*      osm_port_get_default_phys_ptr
+*
+* DESCRIPTION
+*      Gets the pointer to the default Physical Port object.
+*      This call should only be used for non-switch ports in which there
+*      is a one-for-one mapping of port to physp.
+*
+* SYNOPSIS
+*/
+static inline
+osm_physp_t*
+osm_port_get_default_phys_ptr(
+       IN const osm_port_t* const p_port )
+{
+       CL_ASSERT( p_port->tbl[p_port->default_port_num] );
+       CL_ASSERT( osm_physp_is_valid( p_port->tbl[p_port->default_port_num] ) );
+       return( p_port->tbl[p_port->default_port_num] );
+}
+/*
+* PARAMETERS
+*      p_port
+*              [in] Pointer to a Port object.
+*
+* RETURN VALUE
+*      Pointer to the Physical Port object.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port
+*********/
+
+/****f* OpenSM: Port/osm_port_get_parent_node
+* NAME
+*      osm_port_get_parent_node
+*
+* DESCRIPTION
+*      Gets the pointer to the this port's Node object.
+*
+* SYNOPSIS
+*/
+static inline struct _osm_node*
+osm_port_get_parent_node(
+       IN const osm_port_t* const p_port )
+{
+       return( p_port->p_node );
+}
+/*
+* PARAMETERS
+*      p_port
+*              [in] Pointer to a Port object.
+*
+*      port_num
+*              [in] Number of physical port for which to return the
+*              osm_physp_t object.
+*
+* RETURN VALUE
+*      Pointer to the Physical Port object.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port
+*********/
+
+/****f* OpenSM: Port/osm_port_get_lid_range_ho
+* NAME
+*      osm_port_get_lid_range_ho
+*
+* DESCRIPTION
+*      Returns the HOST ORDER lid min and max values for this port,
+*      based on the lmc value.
+*
+* SYNOPSIS
+*/
+void
+osm_port_get_lid_range_ho(
+       IN const osm_port_t* const p_port,
+       OUT uint16_t* const p_min_lid,
+       OUT uint16_t* const p_max_lid );
+/*
+* PARAMETERS
+*      p_port
+*              [in] Pointer to a Port object.
+*
+*      p_min_lid
+*              [out] Pointer to the minimum LID value occupied by this port.
+*
+*      p_max_lid
+*              [out] Pointer to the maximum LID value occupied by this port.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port
+*********/
+
+/****f* OpenSM: Port/osm_get_port_by_base_lid
+* NAME
+*      osm_get_port_by_base_lid
+*
+* DESCRIPTION
+*      Returns a status on whether a Port was able to be 
+*      determined based on the LID supplied and if so, return the Port.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_get_port_by_base_lid(
+       IN const osm_subn_t*       const p_subn,
+       IN const ib_net16_t        lid,
+       IN OUT const osm_port_t**  const pp_port );
+/*
+* PARAMETERS
+*      p_subn
+*              [in] Pointer to the subnet data structure.
+*
+*      lid
+*              [in] LID requested.
+*
+*      pp_port
+*              [in][out] Pointer to pointer to Port object.
+*
+* RETURN VALUES
+*      IB_SUCCESS
+*      IB_NOT_FOUND 
+*
+* NOTES
+*
+* SEE ALSO
+*       Port
+*********/
+
+/****f* OpenSM: Port/osm_port_add_new_physp
+* NAME
+*      osm_port_add_new_physp
+*
+* DESCRIPTION
+*      Adds a new physical port to the logical collection owned by the Port.
+*      Physical Ports added here must share the same GUID as the Port.
+*
+* SYNOPSIS
+*/
+void
+osm_port_add_new_physp(
+       IN osm_port_t* const p_port,
+       IN const uint8_t port_num );
+/*
+* PARAMETERS
+*      p_port
+*              [in] Pointer to a Port object.
+*
+*      port_num
+*              [in] Port number to add.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port
+*********/
+
+/****f* OpenSM: Port/osm_port_discovery_count_reset
+* NAME
+*      osm_port_discovery_count_reset
+*
+* DESCRIPTION
+*      Resets the discovery count for this Port to zero.
+*      This operation should be performed at the start of a sweep.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_port_discovery_count_reset(
+       IN osm_port_t* const p_port )
+{
+       p_port->discovery_count = 0;
+}
+/*
+* PARAMETERS
+*      p_port
+*              [in] Pointer to an osm_port_t object.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port object
+*********/
+
+/****f* OpenSM: Port/osm_port_discovery_count_get
+* NAME
+*      osm_port_discovery_count_get
+*
+* DESCRIPTION
+*      Returns the number of times this port has been discovered
+*      since the last time the discovery count was reset.
+*
+* SYNOPSIS
+*/
+static inline uint32_t
+osm_port_discovery_count_get(
+       IN const osm_port_t* const p_port )
+{
+       return( p_port->discovery_count );
+}
+/*
+* PARAMETERS
+*      p_port
+*              [in] Pointer to an osm_port_t object.
+*
+* RETURN VALUES
+*      Returns the number of times this port has been discovered
+*      since the last time the discovery count was reset.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port object
+*********/
+
+/****f* OpenSM: Port/osm_port_discovery_count_inc
+* NAME
+*      osm_port_discovery_count_inc
+*
+* DESCRIPTION
+*      Increments the discovery count for this Port.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_port_discovery_count_inc(
+       IN osm_port_t* const p_port )
+{
+       p_port->discovery_count++;
+}
+/*
+* PARAMETERS
+*      p_port
+*              [in] Pointer to an osm_port_t object.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port object
+*********/
+
+/****f* OpenSM: Port/osm_port_add_mgrp
+* NAME
+*      osm_port_add_mgrp
+*
+* DESCRIPTION
+*      Logically connects a port to a multicast group.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_port_add_mgrp(
+       IN osm_port_t* const p_port,
+       IN const ib_net16_t mlid );
+/*
+* PARAMETERS
+*      p_port
+*              [in] Pointer to an osm_port_t object.
+*
+*      mlid
+*              [in] MLID of the multicast group.
+*
+* RETURN VALUES
+*      IB_SUCCESS
+*      IB_INSUFFICIENT_MEMORY
+*
+* NOTES
+*
+* SEE ALSO
+*      Port object
+*********/
+
+/****f* OpenSM: Port/osm_port_remove_mgrp
+* NAME
+*      osm_port_remove_mgrp
+*
+* DESCRIPTION
+*      Logically disconnects a port from a multicast group.
+*
+* SYNOPSIS
+*/
+void
+osm_port_remove_mgrp(
+       IN osm_port_t* const p_port,
+       IN const ib_net16_t mlid );
+/*
+* PARAMETERS
+*      p_port
+*              [in] Pointer to an osm_port_t object.
+*
+*      mlid
+*              [in] MLID of the multicast group.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port object
+*********/
+
+/****f* OpenSM: Port/osm_port_remove_all_mgrp
+* NAME
+*      osm_port_remove_all_mgrp
+*
+* DESCRIPTION
+*      Logically disconnects a port from all its multicast groups.
+*
+* SYNOPSIS
+*/
+void
+osm_port_remove_all_mgrp(
+       IN osm_port_t* const p_port );
+/*
+* PARAMETERS
+*      p_port
+*              [in] Pointer to an osm_port_t object.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      Port object
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_calc_link_mtu
+* NAME
+*      osm_physp_calc_link_mtu
+*
+* DESCRIPTION
+*      Calculate the Port MTU based on current and remote 
+*  physical ports MTU CAP values.
+*
+* SYNOPSIS
+*/
+uint8_t
+osm_physp_calc_link_mtu(
+       IN osm_log_t*           p_log,
+       IN const osm_physp_t*   p_physp );
+/*
+* PARAMETERS
+*      p_log
+*              [in] Pointer to a log object.
+*
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+*      The MTU of the link to be used.
+*
+* NOTES
+*
+* SEE ALSO
+*      PhysPort object
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_calc_link_op_vls
+* NAME
+*      osm_physp_calc_link_op_vls
+*
+* DESCRIPTION
+*      Calculate the Port OP_VLS based on current and remote 
+*  physical ports VL CAP values. Allowing user option for a max limit.
+*
+* SYNOPSIS
+*/
+uint8_t
+osm_physp_calc_link_op_vls(
+       IN osm_log_t*                p_log,
+       IN const osm_subn_t *        p_subn,
+       IN const osm_physp_t*        p_physp );
+/*
+* PARAMETERS
+*      p_log
+*              [in] Pointer to a log object.
+*
+*      p_subn
+*              [in] Pointer to the subnet object for accessing of the options.
+*
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+*      The OP_VLS of the link to be used.
+*
+* NOTES
+*
+* SEE ALSO
+*  PhysPort object
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_replace_dr_path_with_alternate_dr_path
+* NAME
+*      osm_physp_replace_dr_path_with_alternate_dr_path
+*
+* DESCRIPTION
+*      Replace the direct route path for the given phys port with an
+*  alternate path going through forien set of phys port.
+*
+* SYNOPSIS
+*/void
+osm_physp_replace_dr_path_with_alternate_dr_path(
+  IN osm_log_t           *p_log,
+  IN osm_subn_t  const   *p_subn,
+  IN osm_physp_t const   *p_physp,
+  IN osm_bind_handle_t   *h_bind );
+/*
+* PARAMETERS
+*      p_log
+*              [in] Pointer to a log object.
+*
+*      p_subn
+*              [in] Pointer to the subnet object for accessing of the options.
+*
+*      p_physp
+*              [in] Pointer to an osm_physp_t object.
+*
+*      h_bind
+*              [in] Pointer to osm_bind_handle_t object.
+*
+* RETURN VALUES
+*      NONE
+*
+* NOTES
+*
+* SEE ALSO
+*      PhysPort object
+*********/
+
+END_C_DECLS
+
+#endif         /* _OSM_PORT_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port_info_rcv.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port_info_rcv.h
new file mode 100644 (file)
index 0000000..85a8078
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_port_info_rcv.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_pi_rcv_t.
+ *     This object represents the PortInfo Receiver object.
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_PI_RCV_H_
+#define _OSM_PI_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_state_mgr.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Port Info Receiver
+* NAME
+*      Port Info Receiver
+*
+* DESCRIPTION
+*      The Port Info Receiver object encapsulates the information
+*      needed to receive the PortInfo attribute from a node.
+*
+*      The Port Info Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Port Info Receiver/osm_pi_rcv_t
+* NAME
+*      osm_pi_rcv_t
+*
+* DESCRIPTION
+*      Port Info Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pi_rcv
+{
+   osm_subn_t              *p_subn;
+   osm_req_t               *p_req;
+   osm_log_t               *p_log;
+   osm_state_mgr_t         *p_state_mgr;
+   cl_plock_t              *p_lock;
+} osm_pi_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_req
+*              Pointer to the generic attribute request object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_state_mgr
+*              Pointer to the State Manager object.
+*     
+*      p_lock
+*              Pointer to the serializing lock.
+*
+* SEE ALSO
+*      Port Info Receiver object
+*********/
+
+/****f* OpenSM: Port Info Receiver/osm_pi_rcv_construct
+* NAME
+*      osm_pi_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a Port Info Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_pi_rcv_construct(
+       IN osm_pi_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Port Info Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_pi_rcv_destroy
+*
+*      Calling osm_pi_rcv_construct is a prerequisite to calling any other
+*      method except osm_pi_rcv_init.
+*
+* SEE ALSO
+*      Port Info Receiver object, osm_pi_rcv_init,
+*      osm_pi_rcv_destroy
+*********/
+
+/****f* OpenSM: Port Info Receiver/osm_pi_rcv_destroy
+* NAME
+*      osm_pi_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_pi_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_pi_rcv_destroy(
+       IN osm_pi_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Port Info Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_pi_rcv_construct or osm_pi_rcv_init.
+*
+* SEE ALSO
+*      Port Info Receiver object, osm_pi_rcv_construct,
+*      osm_pi_rcv_init
+*********/
+
+/****f* OpenSM: Port Info Receiver/osm_pi_rcv_init
+* NAME
+*      osm_pi_rcv_init
+*
+* DESCRIPTION
+*      The osm_pi_rcv_init function initializes a
+*      Port Info Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pi_rcv_init(
+       IN osm_pi_rcv_t* const p_ctrl,
+       IN osm_req_t* const p_req,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN osm_state_mgr_t* const p_state_mgr,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_pi_rcv_t object to initialize.
+*
+*      p_req
+*              [in] Pointer to an osm_req_t object.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_state_mgr
+*              [in] Pointer to the state manager object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Port Info Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Port Info Receiver methods.
+*
+* SEE ALSO
+*      Port Info Receiver object, osm_pi_rcv_construct,
+*      osm_pi_rcv_destroy
+*********/
+
+/****f* OpenSM: Port Info Receiver/osm_pi_rcv_process
+* NAME
+*      osm_pi_rcv_process
+*
+* DESCRIPTION
+*      Process the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+void osm_pi_rcv_process(
+       IN const osm_pi_rcv_t* const p_ctrl,
+       IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_pi_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the node's PortInfo attribute.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*      This function processes a PortInfo attribute.
+*
+* SEE ALSO
+*      Port Info Receiver, Port Info Response Controller
+*********/
+       
+END_C_DECLS
+
+#endif /* _OSM_PI_RCV_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port_info_rcv_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port_info_rcv_ctrl.h
new file mode 100644 (file)
index 0000000..644005c
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_port_info_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_pi_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA NodeInfo
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_PI_RCV_CTRL_H_
+#define _OSM_PI_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_port_info_rcv.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Port Info Receive Controller
+* NAME
+*      Port Info Receive Controller
+*
+* DESCRIPTION
+*      The Port Info Receive Controller object encapsulates
+*      the information needed to receive the NodeInfo attribute from a node.
+*
+*      The Port Info Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Port Info Receive Controller/osm_pi_rcv_ctrl_t
+* NAME
+*      osm_pi_rcv_ctrl_t
+*
+* DESCRIPTION
+*      Port Info Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pi_rcv_ctrl
+{
+       osm_pi_rcv_t                    *p_rcv;
+       osm_log_t                       *p_log;
+       cl_dispatcher_t                 *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_pi_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the Port Info Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      Port Info Receive Controller object
+*      Port Info Receiver object
+*********/
+
+/****f* OpenSM: Port Info Receive Controller/osm_pi_rcv_ctrl_construct
+* NAME
+*      osm_pi_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Port Info Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_pi_rcv_ctrl_construct(
+       IN osm_pi_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Port Info Receive Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_pi_rcv_ctrl_init, osm_pi_rcv_ctrl_destroy,
+*      and osm_pi_rcv_ctrl_is_inited.
+*
+*      Calling osm_pi_rcv_ctrl_construct is a prerequisite to calling any other
+*      method except osm_pi_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Port Info Receive Controller object, osm_pi_rcv_ctrl_init,
+*      osm_pi_rcv_ctrl_destroy, osm_pi_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Port Info Receive Controller/osm_pi_rcv_ctrl_destroy
+* NAME
+*      osm_pi_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_pi_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_pi_rcv_ctrl_destroy(
+       IN osm_pi_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Port Info Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_pi_rcv_ctrl_construct or osm_pi_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Port Info Receive Controller object, osm_pi_rcv_ctrl_construct,
+*      osm_pi_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Port Info Receive Controller/osm_pi_rcv_ctrl_init
+* NAME
+*      osm_pi_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_pi_rcv_ctrl_init function initializes a
+*      Port Info Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pi_rcv_ctrl_init(
+       IN osm_pi_rcv_ctrl_t* const p_ctrl,
+       IN osm_pi_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_pi_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_pi_rcv_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Port Info Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Port Info Receive Controller methods.
+*
+* SEE ALSO
+*      Port Info Receive Controller object, osm_pi_rcv_ctrl_construct,
+*      osm_pi_rcv_ctrl_destroy, osm_pi_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Port Info Receive Controller/osm_pi_rcv_ctrl_is_inited
+* NAME
+*      osm_pi_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+*      Indicates if the object has been initialized with osm_pi_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_pi_rcv_ctrl_is_inited(
+       IN const osm_pi_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_pi_rcv_ctrl_t object.
+*
+* RETURN VALUES
+*      TRUE if the object was initialized successfully,
+*      FALSE otherwise.
+*
+* NOTES
+*      The osm_pi_rcv_ctrl_construct or osm_pi_rcv_ctrl_init must be
+*      called before using this function.
+*
+* SEE ALSO
+*      Port Info Receive Controller object, osm_pi_rcv_ctrl_construct,
+*      osm_pi_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PI_RCV_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port_profile.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_port_profile.h
new file mode 100644 (file)
index 0000000..88c004e
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_port_profile.h 1091 2008-04-30 07:01:35Z tzachid $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of Switch/osm_port_profile_t.
+ *     This object represents a port profile for an IBA switch.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#ifndef _OSM_PORT_PROFILE_H_
+#define _OSM_PORT_PROFILE_H_
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_matrix.h>
+#include <opensm/osm_fwd_tbl.h>
+#include <opensm/osm_mcast_tbl.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Port Profile
+* NAME
+*      Port Profile
+*
+* DESCRIPTION
+*      The Port Profile object contains profiling information for
+*      each Physical Port on a switch.  The profile information
+*      may be used to optimize path selection.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Switch/osm_port_profile_t
+* NAME
+*      osm_port_profile_t
+*
+* DESCRIPTION
+*      The Port Profile object contains profiling information for
+*      each Physical Port on the switch.  The profile information
+*      may be used to optimize path selection.
+*
+*      This object should be treated as opaque and should be
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_port_profile
+{
+       uint32_t                num_paths;
+} osm_port_profile_t;
+/*
+* FIELDS
+*      num_paths
+*              The number of paths using this port.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Port Profile/osm_port_prof_construct
+* NAME
+*      osm_port_prof_construct
+*
+* DESCRIPTION
+*      
+*
+* SYNOPSIS
+*/
+static inline void
+osm_port_prof_construct(
+       IN osm_port_profile_t* const p_prof )
+{
+       CL_ASSERT( p_prof );
+       memset( p_prof, 0, sizeof(*p_prof) );
+}
+/*
+* PARAMETERS
+*      p_prof
+*              [in] Pointer to the Port Profile object to construct.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Port Profile/osm_port_prof_path_count_inc
+* NAME
+*      osm_port_prof_path_count_inc
+*
+* DESCRIPTION
+*      Increments the count of the number of paths going through this port.
+*      
+*
+* SYNOPSIS
+*/
+static inline void
+osm_port_prof_path_count_inc(
+       IN osm_port_profile_t* const p_prof )
+{
+       CL_ASSERT( p_prof );
+       p_prof->num_paths++;
+}
+/*
+* PARAMETERS
+*      p_pro
+*              [in] Pointer to the Port Profile object.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Port Profile/osm_port_prof_path_count_get
+* NAME
+*      osm_port_prof_path_count_get
+*
+* DESCRIPTION
+*      Returns the count of the number of paths going through this port.
+*
+* SYNOPSIS
+*/
+static inline uint32_t
+osm_port_prof_path_count_get(
+       IN const osm_port_profile_t* const p_prof )
+{
+       return( p_prof->num_paths );
+}
+/*
+* PARAMETERS
+*      p_pro
+*              [in] Pointer to the Port Profile object.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Port Profile Opt/osm_port_prof_is_ignored_port
+* NAME
+*      osm_port_prof_is_ignored_port
+*
+* DESCRIPTION
+*      Check to see if this port is to be ignored in path counting.
+*  This is done by examining the optional list of port_prof_ignore_guids.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_port_prof_is_ignored_port(
+       IN const osm_subn_t *p_subn, 
+       IN uint64_t port_guid,
+       IN uint8_t port_num )
+{
+  const cl_map_t *p_map = &(p_subn->opt.port_prof_ignore_guids);
+  const void *p_obj = cl_map_get(p_map, port_guid);
+  size_t res;
+
+  // HACK: we currently support ignoring ports 0 - 31
+  if (p_obj != NULL) {
+        res = (size_t)p_obj & (size_t)(1 << port_num);
+        return (res != 0);
+  }
+  return FALSE;
+}
+/*
+* PARAMETERS
+*      p_subn
+*              [in] Pointer to the OSM Subnet object.
+*
+*  port_guid 
+*     [in] The port guid 
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Port Profile Opt/osm_port_prof_set_ignored_port
+* NAME
+*      osm_port_prof_set_ignored_port
+*
+* DESCRIPTION
+*      Set the ignored property of the port.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_port_prof_set_ignored_port(
+       IN osm_subn_t *p_subn, 
+       IN uint64_t port_guid,
+       IN uint8_t port_num )
+{
+  cl_map_t *p_map = &(p_subn->opt.port_prof_ignore_guids);
+  const void *p_obj = cl_map_get(p_map, port_guid);
+  size_t value = 0;
+
+  // HACK: we currently support ignoring ports 0 - 31
+  CL_ASSERT(port_num < 32);
+  
+  if (p_obj != NULL) {
+        value = (size_t)p_obj;
+  } 
+  
+  value = value | ((size_t)1 << port_num); //size_t will be 64 bit length in Win2003_64
+  cl_map_insert(&(p_subn->opt.port_prof_ignore_guids),
+                                        port_guid,
+                                        (void *)value);
+}
+/*
+* PARAMETERS
+*      p_subn
+*              [in] Pointer to the OSM Subnet object.
+*
+*  port_guid 
+*     [in] The port guid 
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif         /* _OSM_PORT_PROFILE_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_rand_fwd_tbl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_rand_fwd_tbl.h
new file mode 100644 (file)
index 0000000..a8db882
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_rand_fwd_tbl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_switch_t.
+ *     This object represents an IBA switch.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_RAND_FWD_TBL_H_
+#define _OSM_RAND_FWD_TBL_H_
+
+#include <stdlib.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Random Forwarding Table
+* NAME
+*      Random Forwarding Table
+*
+* DESCRIPTION
+*      The Random Forwarding Table objects encapsulate the information
+*      needed by the OpenSM to manage random forwarding tables.  The OpenSM
+*      allocates one Random Forwarding Table object per switch in the
+*      IBA subnet, if that switch uses a random forwarding table.
+*
+*      The Random Forwarding Table objects are not thread safe, thus
+*      callers must provide serialization.
+*
+*   ** RANDOM FORWARDING TABLES ARE NOT SUPPORTED IN THE CURRENT VERSION **
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Forwarding Table/osm_rand_fwd_tbl_t
+* NAME
+*      osm_rand_fwd_tbl_t
+*
+* DESCRIPTION
+*      Random Forwarding Table structure.
+*
+*      THIS OBJECT IS PLACE HOLDER.  SUPPORT FOR SWITCHES WITH
+*      RANDOM FORWARDING TABLES HAS NOT BEEN IMPLEMENTED YET.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_rand_fwd_tbl
+{
+       /* PLACE HOLDER STRUCTURE ONLY!! */
+       uint32_t                                size;
+} osm_rand_fwd_tbl_t;
+/*
+* FIELDS
+*      RANDOM FORWARDING TABLES ARE NOT SUPPORTED YET!!
+*
+* SEE ALSO
+*      Forwarding Table object, Random Forwarding Table object.
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_rand_tbl_delete
+* NAME
+*      osm_rand_tbl_delete
+*
+* DESCRIPTION
+*      This destroys and deallocates a Random Forwarding Table object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_rand_tbl_delete(
+       IN osm_rand_fwd_tbl_t** const pp_tbl )
+{
+       /*
+               TO DO - This is a place holder function only!
+       */
+       free( *pp_tbl );
+       *pp_tbl = NULL;
+}
+/*
+* PARAMETERS
+*      pp_tbl
+*              [in] Pointer a Pointer to the Random Forwarding Table object.
+*
+* RETURN VALUE
+*      On success, returns a pointer to a new Linear Forwarding Table object
+*      of the specified size.
+*      NULL otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_rand_fwd_tbl_set
+* NAME
+*      osm_rand_fwd_tbl_set
+*
+* DESCRIPTION
+*      Sets the port to route the specified LID.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_rand_fwd_tbl_set(
+       IN osm_rand_fwd_tbl_t* const p_tbl,
+       IN const uint16_t lid_ho,
+       IN const uint8_t port )
+{
+       /* Random forwarding tables not supported yet. */
+       UNUSED_PARAM( p_tbl );
+       UNUSED_PARAM( lid_ho );
+       UNUSED_PARAM( port );
+       CL_ASSERT( FALSE );
+}
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Random Forwarding Table object.
+*
+*      lid_ho
+*              [in] LID value (host order) for which to set the route.
+*
+*      port
+*              [in] Port to route the specified LID value.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_rand_fwd_tbl_set_block
+* NAME
+*      osm_rand_fwd_tbl_set_block
+*
+* DESCRIPTION
+*      Copies the specified block into the Random Forwarding Table.
+*
+* SYNOPSIS
+*/
+static inline ib_api_status_t
+osm_rand_fwd_tbl_set_block(
+       IN osm_rand_fwd_tbl_t* const p_tbl,
+       IN const uint8_t* const p_block,
+       IN const uint32_t block_num )
+{
+       /* Random forwarding tables not supported yet. */
+       UNUSED_PARAM( p_tbl );
+       UNUSED_PARAM( p_block );
+       UNUSED_PARAM( block_num );
+       CL_ASSERT( FALSE );
+       return( IB_ERROR );
+}
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Random Forwarding Table object.
+*
+*      p_block
+*              [in] Pointer to the Forwarding Table block.
+*
+*      block_num
+*              [in] Block number of this block.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_rand_fwd_tbl_get
+* NAME
+*      osm_rand_fwd_tbl_get
+*
+* DESCRIPTION
+*      Returns the port that routes the specified LID.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_rand_fwd_tbl_get(
+       IN const osm_rand_fwd_tbl_t* const p_tbl,
+       IN const uint16_t lid_ho )
+{
+       CL_ASSERT( FALSE );
+       UNUSED_PARAM( p_tbl );
+       UNUSED_PARAM( lid_ho );
+
+       return( OSM_NO_PATH );
+}
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Linear Forwarding Table object.
+*
+*      lid_ho
+*              [in] LID value (host order) for which to get the route.
+*
+* RETURN VALUE
+*      Returns the port that routes the specified LID.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_rand_fwd_tbl_get_lids_per_block
+* NAME
+*      osm_rand_fwd_tbl_get_lids_per_block
+*
+* DESCRIPTION
+*      Returns the number of LIDs per LID block.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_rand_fwd_tbl_get_lids_per_block(
+       IN const osm_rand_fwd_tbl_t* const p_tbl )
+{
+       UNUSED_PARAM( p_tbl );
+       return( 16 );
+}
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+*      Returns the number of LIDs per LID block.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_rand_fwd_tbl_get_max_block_id_in_use
+* NAME
+*      osm_rand_fwd_tbl_get_max_block_id_in_use
+*
+* DESCRIPTION
+*      Returns the maximum block ID in actual use by the forwarding table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_rand_fwd_tbl_get_max_block_id_in_use(
+       IN const osm_rand_fwd_tbl_t* const p_tbl,
+       IN const uint16_t lid_top_ho )
+{
+       UNUSED_PARAM( p_tbl );
+       UNUSED_PARAM( lid_top_ho );
+       CL_ASSERT( FALSE );
+       return( 0 );
+}
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+*      Returns the maximum block ID in actual use by the forwarding table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_rand_fwd_tbl_get_size
+* NAME
+*      osm_rand_fwd_tbl_get_size
+*
+* DESCRIPTION
+*      Returns the number of entries available in the forwarding table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_rand_fwd_tbl_get_size(
+       IN const osm_rand_fwd_tbl_t* const p_tbl )
+{
+       UNUSED_PARAM( p_tbl );
+       CL_ASSERT( FALSE );
+       return( 0 );
+}
+/*
+* PARAMETERS
+*      p_tbl
+*              [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+*      Returns the number of entries available in the forwarding table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_RAND_FWD_TBL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_remote_sm.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_remote_sm.h
new file mode 100644 (file)
index 0000000..6f393a4
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_remote_sm.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_sm_t, osm_remote_sm_t.
+ *     This object represents an IBA subnet.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_REMOTE_SM_H_
+#define _OSM_REMOTE_SM_H_
+
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_port.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Remote SM
+* NAME
+*      Remote SM
+*
+* DESCRIPTION
+*      The Remote SM object encapsulates the information tracked for
+*      other SM ports on the subnet.
+*
+*      The Remote SM object is thread safe.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Remote SM/osm_remote_sm_t
+* NAME
+*      osm_remote_sm_t
+*
+* DESCRIPTION
+*      Remote Subnet Manager structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_remote_sm
+{
+       cl_map_item_t                           map_item;
+       const osm_port_t                        *p_port;
+       ib_sm_info_t                            smi;
+} osm_remote_sm_t;
+/*
+* FIELDS
+*      map_item
+*              Linkage for the cl_qmap container.  MUST BE FIRST ELEMENT!!
+*      p_port
+*              Pointer to the port object for this SM.
+*
+*      smi
+*              The SMInfo attribute for this SM.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: SM/osm_remote_sm_construct
+* NAME
+*      osm_remote_sm_construct
+*
+* DESCRIPTION
+*      This function constructs an Remote SM object.
+*
+* SYNOPSIS
+*/
+void
+osm_remote_sm_construct(
+       IN osm_remote_sm_t* const p_sm );
+/*
+* PARAMETERS
+*      p_sm
+*              [in] Pointer to an Remote SM object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_remote_sm_init, osm_remote_sm_destroy
+*
+*      Calling osm_remote_sm_construct is a prerequisite to calling any other
+*      method except osm_remote_sm_init.
+*
+* SEE ALSO
+*      SM object, osm_remote_sm_init, osm_remote_sm_destroy
+*********/
+
+/****f* OpenSM: SM/osm_remote_sm_destroy
+* NAME
+*      osm_remote_sm_destroy
+*
+* DESCRIPTION
+*      The osm_remote_sm_destroy function destroys an SM, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_remote_sm_destroy(
+       IN osm_remote_sm_t* const p_sm );
+/*
+* PARAMETERS
+*      p_sm
+*              [in] Pointer to an Remote SM object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified Remote SM object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_remote_sm_construct or osm_remote_sm_init.
+*
+* SEE ALSO
+*      Remote SM object, osm_remote_sm_construct, osm_remote_sm_init
+*********/
+
+/****f* OpenSM: SM/osm_remote_sm_init
+* NAME
+*      osm_remote_sm_init
+*
+* DESCRIPTION
+*      The osm_remote_sm_init function initializes an Remote SM object for use.
+*
+* SYNOPSIS
+*/
+void
+osm_remote_sm_init(
+       IN osm_remote_sm_t* const p_sm,
+       IN const osm_port_t* const p_port,
+       IN const ib_sm_info_t* const p_smi );
+/*
+* PARAMETERS
+*      p_sm
+*              [in] Pointer to an osm_remote_sm_t object to initialize.
+*
+*      p_port
+*              [in] Pointer to the Remote SM's port object.
+*      
+*      p_smi
+*              [in] Pointer to the SMInfo attribute for this SM.
+*
+* RETURN VALUES
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling other Remote SM methods.
+*
+* SEE ALSO
+*      Remote SM object, osm_remote_sm_construct, osm_remote_sm_destroy
+*********/
+
+END_C_DECLS
+
+#endif         /* _OSM_REMOTE_SM_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_req.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_req.h
new file mode 100644 (file)
index 0000000..cbcb409
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_req.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_req_t.
+ *     This object represents an object that genericly requests
+ *     attributes from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_REQ_H_
+#define _OSM_REQ_H_
+
+#include <complib/cl_atomic.h>
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_path.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Generic Requester
+* NAME
+*      Generic Requester
+*
+* DESCRIPTION
+*      The Generic Requester object encapsulates the information
+*      needed to request an attribute from a node.
+*
+*      The Generic Requester object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Generic Requester/osm_req_t
+* NAME
+*      osm_req_t
+*
+* DESCRIPTION
+*      Generic Requester structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_req
+{
+       osm_mad_pool_t                          *p_pool;
+       osm_vl15_t                                      *p_vl15;
+       osm_log_t                                       *p_log;
+       osm_subn_t                                      *p_subn;
+       atomic32_t                                      *p_sm_trans_id;
+
+} osm_req_t;
+/*
+* FIELDS
+*      p_pool
+*              Pointer to the MAD pool.
+*
+*      p_vl15
+*              Pointer to the VL15 interface.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_subn
+*              Pointer to the subnet object.
+*
+* SEE ALSO
+*      Generic Requester object
+*********/
+
+/****f* OpenSM: Generic Requester/osm_req_construct
+* NAME
+*      osm_req_construct
+*
+* DESCRIPTION
+*      This function constructs a Generic Requester object.
+*
+* SYNOPSIS
+*/
+void
+osm_req_construct(
+       IN osm_req_t* const p_req );
+/*
+* PARAMETERS
+*      p_req
+*              [in] Pointer to a Generic Requester object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_req_init, and osm_req_destroy.
+*
+*      Calling osm_req_construct is a prerequisite to calling any other
+*      method except osm_req_init.
+*
+* SEE ALSO
+*      Generic Requester object, osm_req_init,
+*      osm_req_destroy
+*********/
+
+/****f* OpenSM: Generic Requester/osm_req_destroy
+* NAME
+*      osm_req_destroy
+*
+* DESCRIPTION
+*      The osm_req_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_req_destroy(
+       IN osm_req_t* const p_req );
+/*
+* PARAMETERS
+*      p_req
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Generic Requester object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_req_construct or osm_req_init.
+*
+* SEE ALSO
+*      Generic Requester object, osm_req_construct,
+*      osm_req_init
+*********/
+
+/****f* OpenSM: Generic Requester/osm_req_init
+* NAME
+*      osm_req_init
+*
+* DESCRIPTION
+*      The osm_req_init function initializes a
+*      Generic Requester object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_req_init(
+       IN osm_req_t*                           const p_req,
+       IN osm_mad_pool_t*                      const p_pool,
+       IN osm_vl15_t*                          const p_vl15,
+       IN osm_subn_t*                          const p_subn,
+       IN osm_log_t*                           const p_log,
+       IN atomic32_t*                          const p_sm_trans_id );
+/*
+* PARAMETERS
+*      p_req
+*              [in] Pointer to an osm_req_t object to initialize.
+*
+*      p_mad_pool
+*              [in] Pointer to the MAD pool.
+*
+*      p_vl15
+*              [in] Pointer to the VL15 interface.
+*
+*      p_subn
+*              [in] Pointer to the subnet object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_sm_trans_id
+*              [in] Pointer to the atomic SM transaction ID.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the Generic Requester object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Generic Requester methods.
+*
+* SEE ALSO
+*      Generic Requester object, osm_req_construct,
+*      osm_req_destroy
+*********/
+
+/****f* OpenSM: Generic Requester/osm_req_get
+* NAME
+*      osm_req_get
+*
+* DESCRIPTION
+*      Starts the process to transmit a directed route request for
+*      the attribute.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_req_get(
+       IN const osm_req_t* const p_req,
+       IN const osm_dr_path_t* const p_path,
+       IN const uint16_t attr_id,
+       IN const uint32_t attr_mod,
+       IN const cl_disp_msgid_t err_msg,
+       IN const osm_madw_context_t* const p_context );
+/*
+* PARAMETERS
+*      p_req
+*              [in] Pointer to an osm_req_t object.
+*
+*      p_path
+*              [in] Pointer to the directed route path to the node
+*              from which to retrieve the attribute.
+*
+*      attr_id
+*              [in] Attribute ID to request.
+*
+*      attr_mod
+*              [in] Attribute modifier for this request.
+*
+*      err_msg
+*              [in] Message id with which to post this MAD if an error occurs.
+*
+*      p_context
+*              [in] Mad wrapper context structure to be copied into the wrapper
+*              context, and thus visible to the recipient of the response.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the request was successful.
+*
+* NOTES
+*      This function asynchronously requests the specified attribute.
+*      The response from the node will be routed through the Dispatcher
+*      to the appropriate receive controller object.
+*
+* SEE ALSO
+*      Generic Requester
+*********/
+/****f* OpenSM: Generic Requester/osm_req_set
+* NAME
+*      osm_req_set
+*
+* DESCRIPTION
+*      Starts the process to transmit a directed route Set() request.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_req_set(
+       IN const osm_req_t* const p_req,
+       IN const osm_dr_path_t* const p_path,
+       IN const uint8_t* const p_payload,
+       IN const size_t payload_size,
+       IN const uint16_t attr_id,
+       IN const uint32_t attr_mod,
+       IN const cl_disp_msgid_t err_msg,
+       IN const osm_madw_context_t* const p_context );
+/*
+* PARAMETERS
+*      p_req
+*              [in] Pointer to an osm_req_t object.
+*
+*      p_path
+*              [in] Pointer to the directed route path of the recipient.
+*
+*      p_payload
+*              [in] Pointer to the SMP payload to send.
+*
+*  payload_size
+*              [in] The size of the payload to be copied to the SMP data field.
+*
+*      attr_id
+*              [in] Attribute ID to request.
+*
+*      attr_mod
+*              [in] Attribute modifier for this request.
+*
+*      err_msg
+*              [in] Message id with which to post this MAD if an error occurs.
+*
+*      p_context
+*              [in] Mad wrapper context structure to be copied into the wrapper
+*              context, and thus visible to the recipient of the response.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the request was successful.
+*
+* NOTES
+*      This function asynchronously requests the specified attribute.
+*      The response from the node will be routed through the Dispatcher
+*      to the appropriate receive controller object.
+*
+* SEE ALSO
+*      Generic Requester
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_REQ_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_req_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_req_ctrl.h
new file mode 100644 (file)
index 0000000..f8bbc40
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_req_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_req_ctrl_t.
+ *     This object represents a controller that calls the
+ *     generic requester object to retrieve attributes from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_REQ_CTRL_H_
+#define _OSM_REQ_CTRL_H_
+
+#include <opensm/osm_base.h>
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_req.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Generic Request Controller
+* NAME
+*      Generic Request Controller
+*
+* DESCRIPTION
+*      The Generic Request Controller object encapsulates the information
+*      needed to request an attribute from a node.
+*
+*      The Generic Request Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Generic Request Controller/osm_req_ctrl_t
+* NAME
+*      osm_req_ctrl_t
+*
+* DESCRIPTION
+*      Generic Request Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_req_ctrl
+{
+       osm_req_t                                       *p_req;
+       osm_log_t                                       *p_log;
+       cl_dispatcher_t                         *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_req_ctrl_t;
+/*
+* FIELDS
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      Generic Request Controller object
+*********/
+
+/****f* OpenSM: Generic Request Controller/osm_req_ctrl_construct
+* NAME
+*      osm_req_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Generic Request Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_req_ctrl_construct(
+       IN osm_req_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Generic Request Controller object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_req_ctrl_init, and osm_req_ctrl_destroy.
+*
+*      Calling osm_req_ctrl_construct is a prerequisite to calling any other
+*      method except osm_req_ctrl_init.
+*
+* SEE ALSO
+*      Generic Request Controller object, osm_req_ctrl_init,
+*      osm_req_ctrl_destroy
+*********/
+
+/****f* OpenSM: Generic Request Controller/osm_req_ctrl_destroy
+* NAME
+*      osm_req_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_req_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_req_ctrl_destroy(
+       IN osm_req_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Generic Request Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_req_ctrl_construct or osm_req_ctrl_init.
+*
+* SEE ALSO
+*      Generic Request Controller object, osm_req_ctrl_construct,
+*      osm_req_ctrl_init
+*********/
+
+/****f* OpenSM: Generic Request Controller/osm_req_ctrl_init
+* NAME
+*      osm_req_ctrl_init
+*
+* DESCRIPTION
+*      The osm_req_ctrl_init function initializes a
+*      Generic Request Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_req_ctrl_init(
+       IN osm_req_ctrl_t*      const p_ctrl,
+       IN osm_req_t*           const p_req,
+       IN osm_log_t*                   const p_log,
+       IN cl_dispatcher_t*             const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_req_ctrl_t object to initialize.
+*
+*      p_req
+*              [in] Pointer to a Generic Requester object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Generic Request Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Generic Request Controller methods.
+*
+* SEE ALSO
+*      Generic Request Controller object, osm_req_ctrl_construct,
+*      Generic Requester object, osm_req_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_REQ_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_resp.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_resp.h
new file mode 100644 (file)
index 0000000..2909e2a
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_resp.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_resp_t.
+ *     This object represents an object that genericly requests
+ *     attributes from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_RESP_H_
+#define _OSM_RESP_H_
+
+#include <complib/cl_atomic.h>
+#include <opensm/osm_base.h>
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_path.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Generic Responder
+* NAME
+*      Generic Responder
+*
+* DESCRIPTION
+*      The Generic Responder object encapsulates the information
+*      needed to respond to an attribute from a node.
+*
+*      The Generic Responder object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Generic Responder/osm_resp_t
+* NAME
+*      osm_resp_t
+*
+* DESCRIPTION
+*      Generic Responder structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_resp
+{
+       osm_mad_pool_t                          *p_pool;
+       osm_vl15_t                                      *p_vl15;
+       osm_log_t                                       *p_log;
+       osm_subn_t                                      *p_subn;
+
+} osm_resp_t;
+/*
+* FIELDS
+*      p_pool
+*              Pointer to the MAD pool.
+*
+*      p_vl15
+*              Pointer to the VL15 interface.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_subn
+*              Pointer to the subnet object.
+*
+* SEE ALSO
+*      Generic Responder object
+*********/
+
+/****f* OpenSM: Generic Responder/osm_resp_construct
+* NAME
+*      osm_resp_construct
+*
+* DESCRIPTION
+*      This function constructs a Generic Responder object.
+*
+* SYNOPSIS
+*/
+void
+osm_resp_construct(
+       IN osm_resp_t* const p_resp );
+/*
+* PARAMETERS
+*      p_resp
+*              [in] Pointer to a Generic Responder object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_resp_init, osm_resp_destroy
+*
+*      Calling osm_resp_construct is a prerequisite to calling any other
+*      method except osm_resp_init.
+*
+* SEE ALSO
+*      Generic Responder object, osm_resp_init,
+*      osm_resp_destroy
+*********/
+
+/****f* OpenSM: Generic Responder/osm_resp_destroy
+* NAME
+*      osm_resp_destroy
+*
+* DESCRIPTION
+*      The osm_resp_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_resp_destroy(
+       IN osm_resp_t* const p_resp );
+/*
+* PARAMETERS
+*      p_resp
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Generic Responder object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_resp_construct or osm_resp_init.
+*
+* SEE ALSO
+*      Generic Responder object, osm_resp_construct,
+*      osm_resp_init
+*********/
+
+/****f* OpenSM: Generic Responder/osm_resp_init
+* NAME
+*      osm_resp_init
+*
+* DESCRIPTION
+*      The osm_resp_init function initializes a
+*      Generic Responder object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_resp_init(
+       IN osm_resp_t*                          const p_resp,
+       IN osm_mad_pool_t*                      const p_pool,
+       IN osm_vl15_t*                          const p_vl15,
+       IN osm_subn_t*                          const p_subn,
+       IN osm_log_t*                           const p_log );
+/*
+* PARAMETERS
+*      p_resp
+*              [in] Pointer to an osm_resp_t object to initialize.
+*
+*      p_mad_pool
+*              [in] Pointer to the MAD pool.
+*
+*      p_vl15
+*              [in] Pointer to the VL15 interface.
+*
+*      p_subn
+*              [in] Pointer to the subnet object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the Generic Responder object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Generic Responder methods.
+*
+* SEE ALSO
+*      Generic Responder object, osm_resp_construct,
+*      osm_resp_destroy
+*********/
+
+/****f* OpenSM: Generic Responder/osm_resp_send
+* NAME
+*      osm_resp_send
+*
+* DESCRIPTION
+*      Starts the process to transmit a directed route response.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_resp_send(
+       IN const osm_resp_t* const p_resp,
+       IN const osm_madw_t* const p_req_madw,
+       IN const ib_net16_t status,
+       IN const uint8_t* const p_payload );
+/*
+* PARAMETERS
+*      p_resp
+*              [in] Pointer to an osm_resp_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper object for the requesting MAD
+*              to which this response is generated.
+*
+*      status
+*              [in] Status for this response.
+*
+*      p_payload
+*              [in] Pointer to the payload of the response MAD.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the response was successful.
+*
+* NOTES
+*
+* SEE ALSO
+*      Generic Responder
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_RESP_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_router.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_router.h
new file mode 100644 (file)
index 0000000..91b0416
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_router_t.
+ *     This object represents an IBA router.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ */
+
+#ifndef _OSM_ROUTER_H_
+#define _OSM_ROUTER_H_
+
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_matrix.h>
+#include <opensm/osm_fwd_tbl.h>
+#include <opensm/osm_mcast_tbl.h>
+#include <opensm/osm_port_profile.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Router
+* NAME
+*      Router
+*
+* DESCRIPTION
+*      The Router object encapsulates the information needed by the
+*      OpenSM to manage routers.  The OpenSM allocates one router object
+*      per router in the IBA subnet.
+*
+*      The Router object is not thread safe, thus callers must provide
+*      serialization.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Hal Rosenstock, Voltaire 
+*
+*********/
+
+/****s* OpenSM: Router/osm_router_t
+* NAME
+*      osm_router_t
+*
+* DESCRIPTION
+*      Router structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_router
+{
+       cl_map_item_t                           map_item;
+       osm_port_t                              *p_port;
+} osm_router_t;
+/*
+* FIELDS
+*      map_item
+*              Linkage structure for cl_qmap.  MUST BE FIRST MEMBER!
+*
+*      p_port
+*              Pointer to the Port object for this router.
+*
+* SEE ALSO
+*      Router object
+*********/
+
+/****f* OpenSM: Router/osm_router_construct
+* NAME
+*      osm_router_construct
+*
+* DESCRIPTION
+*      This function constructs a Router object.
+*
+* SYNOPSIS
+*/
+void
+osm_router_construct(
+       IN osm_router_t* const p_rtr );
+/*
+* PARAMETERS
+*      p_rtr
+*              [in] Pointer to a Router object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_router_init, and osm_router_destroy.
+*
+*      Calling osm_router_construct is a prerequisite to calling any other
+*      method except osm_router_init.
+*
+* SEE ALSO
+*      Router object, osm_router_init, osm_router_destroy
+*********/
+
+/****f* OpenSM: Router/osm_router_destroy
+* NAME
+*      osm_router_destroy
+*
+* DESCRIPTION
+*      The osm_router_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_router_destroy(
+       IN osm_router_t* const p_rtr );
+/*
+* PARAMETERS
+*      p_rtr
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to osm_router_construct
+*      or osm_router_init.
+*
+* SEE ALSO
+*      Router object, osm_router_construct, osm_router_init
+*********/
+
+/****f* OpenSM: Router/osm_router_destroy
+* NAME
+*      osm_router_destroy
+*
+* DESCRIPTION
+*      Destroys and deallocates the object.
+*
+* SYNOPSIS
+*/
+void
+osm_router_delete(
+       IN OUT osm_router_t** const pp_rtr );
+/*
+* PARAMETERS
+*      p_rtr
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      Router object, osm_router_construct, osm_router_init
+*********/
+
+/****f* OpenSM: Router/osm_router_init
+* NAME
+*      osm_router_init
+*
+* DESCRIPTION
+*      The osm_router_init function initializes a Router object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_router_init(
+       IN osm_router_t* const p_rtr,
+       IN osm_port_t* const p_port );
+/*
+* PARAMETERS
+*      p_rtr
+*              [in] Pointer to an osm_router_t object to initialize.
+*
+*      p_port
+*              [in] Pointer to the port object of this router 
+*
+* RETURN VALUES
+*      IB_SUCCESS if the Router object was initialized successfully.
+*
+* NOTES
+*      Allows calling other node methods.
+*
+* SEE ALSO
+*      Router object, osm_router_construct, osm_router_destroy
+*********/
+
+/****f* OpenSM: Router/osm_router_new
+* NAME
+*      osm_router_new
+*
+* DESCRIPTION
+*      The osm_router_init function initializes a Router object for use.
+*
+* SYNOPSIS
+*/
+osm_router_t*
+osm_router_new(
+       IN osm_port_t* const p_port );
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer to the node object of this router
+*
+* RETURN VALUES
+*      Pointer to the new initialized router object.
+*
+* NOTES
+*
+* SEE ALSO
+*      Router object, osm_router_construct, osm_router_destroy,
+*********/
+
+/****f* OpenSM: Router/osm_router_get_port_ptr
+* NAME
+*      osm_router_get_port_ptr
+*
+* DESCRIPTION
+*      Returns a pointer to the Port object for this router.
+*
+* SYNOPSIS
+*/
+static inline osm_port_t*
+osm_router_get_port_ptr(
+        IN const osm_router_t* const p_rtr )
+{
+        return( p_rtr->p_port );
+}
+/*
+* PARAMETERS
+*      p_rtr
+*              [in] Pointer to an osm_router_t object.
+*
+* RETURN VALUES
+*      Returns a pointer to the Port object for this router.
+*       
+* NOTES
+*
+* SEE ALSO
+*      Router object
+*********/
+
+/****f* OpenSM: Router/osm_router_get_node_ptr
+* NAME
+*      osm_router_get_node_ptr
+*
+* DESCRIPTION
+*      Returns a pointer to the Node object for this router.
+*
+* SYNOPSIS
+*/
+static inline osm_node_t*
+osm_router_get_node_ptr(
+       IN const osm_router_t* const p_rtr )
+{
+       return( p_rtr->p_port->p_node );
+}
+/*
+* PARAMETERS
+*      p_rtr
+*              [in] Pointer to an osm_router_t object.
+*
+* RETURN VALUES
+*      Returns a pointer to the Node object for this router.
+*      
+* NOTES
+*
+* SEE ALSO
+*      Router object
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_ROUTER_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa.h
new file mode 100644 (file)
index 0000000..0c493b9
--- /dev/null
@@ -0,0 +1,500 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_sa_t.
+ *     This object represents an IBA subnet.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#ifndef _OSM_SA_H_
+#define _OSM_SA_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_event.h>
+#include <complib/cl_thread.h>
+#include <complib/cl_timer.h>
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_subnet.h>
+#include <vendor/osm_vendor.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_node_record_ctrl.h>
+#include <opensm/osm_sa_portinfo_record_ctrl.h>
+#include <opensm/osm_sa_guidinfo_record_ctrl.h>
+#include <opensm/osm_sa_link_record_ctrl.h>
+#include <opensm/osm_sa_path_record_ctrl.h>
+#include <opensm/osm_sa_multipath_record_ctrl.h>
+#include <opensm/osm_sa_sminfo_record_ctrl.h>
+#include <opensm/osm_sa_mad_ctrl.h>
+#include <opensm/osm_sa_mcmember_record_ctrl.h>
+#include <opensm/osm_sa_service_record_ctrl.h>
+#include <opensm/osm_sa_class_port_info_ctrl.h>
+#include <opensm/osm_sa_informinfo_ctrl.h>
+#include <opensm/osm_sa_slvl_record_ctrl.h>
+#include <opensm/osm_sa_vlarb_record_ctrl.h>
+#include <opensm/osm_sa_pkey_record_ctrl.h>
+#include <opensm/osm_sa_lft_record_ctrl.h>
+#include <opensm/osm_sa_sw_info_record_ctrl.h>
+#include <opensm/osm_sa_mft_record_ctrl.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SA
+* NAME
+*      SA
+*
+* DESCRIPTION
+*      The SA object encapsulates the information needed by the
+*      OpenSM to instantiate a subnet administrator.  The OpenSM allocates
+*      one SA object per subnet manager.
+*
+*      The SA object is thread safe.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* AUTHOR
+*      Ranjit Pandit, Intel
+*      Anil Keshavamurthy, Intel       
+*
+*********/
+
+/****d* OpenSM: SA/osm_sa_state_t
+* NAME
+*      osm_sa_state_t
+*
+* DESCRIPTION
+*      Enumerates the possible states of SA object.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_sa_state
+{
+       OSM_SA_STATE_INIT = 0,
+       OSM_SA_STATE_READY
+
+} osm_sa_state_t;
+/***********/
+
+/****s* OpenSM: SM/osm_sa_t
+* NAME
+*      osm_sa_t
+*
+* DESCRIPTION
+*      Subnet Administration structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sa
+{
+       osm_sa_state_t                          state;
+       osm_subn_t                              *p_subn;
+       osm_vendor_t                            *p_vendor;
+       osm_log_t                               *p_log;
+       osm_mad_pool_t                          *p_mad_pool;
+       cl_dispatcher_t                         *p_disp;
+       cl_plock_t                              *p_lock;
+       atomic32_t                              sa_trans_id;
+       osm_sa_mad_ctrl_t                       mad_ctrl;
+       osm_sa_resp_t                           resp;
+       osm_cpi_rcv_t                           cpi_rcv;
+       osm_cpi_rcv_ctrl_t                      cpi_rcv_ctrl;
+       osm_nr_rcv_t                            nr_rcv;
+       osm_nr_rcv_ctrl_t                       nr_rcv_ctrl;
+       osm_pir_rcv_t                           pir_rcv;
+       osm_pir_rcv_ctrl_t                      pir_rcv_ctrl;
+       osm_gir_rcv_t                           gir_rcv;
+       osm_gir_rcv_ctrl_t                      gir_rcv_ctrl;
+       osm_lr_rcv_t                            lr_rcv;
+       osm_lr_rcv_ctrl_t                       lr_rcv_ctrl;
+       osm_pr_rcv_t                            pr_rcv;
+       osm_pr_rcv_ctrl_t                       pr_rcv_ctrl;
+       osm_smir_rcv_t                          smir_rcv;
+       osm_smir_ctrl_t                         smir_ctrl;
+       osm_mcmr_recv_t                         mcmr_rcv;
+       osm_mcmr_rcv_ctrl_t                     mcmr_rcv_ctlr;
+       osm_sr_rcv_t                            sr_rcv;
+       osm_sr_rcv_ctrl_t                       sr_rcv_ctrl;
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+       osm_mpr_rcv_t                           mpr_rcv;
+       osm_mpr_rcv_ctrl_t                      mpr_rcv_ctrl;
+#endif
+
+       /* InformInfo Receiver */
+       osm_infr_rcv_t                          infr_rcv;
+       osm_infr_rcv_ctrl_t                     infr_rcv_ctrl;
+
+       /* VL Arbitrartion Query */
+       osm_vlarb_rec_rcv_t                     vlarb_rec_rcv;
+       osm_vlarb_rec_rcv_ctrl_t                vlarb_rec_rcv_ctrl;
+
+       /* SLtoVL Map Query */
+       osm_slvl_rec_rcv_t                      slvl_rec_rcv;
+       osm_slvl_rec_rcv_ctrl_t                 slvl_rec_rcv_ctrl;
+  
+       /* P_Key table Query */
+       osm_pkey_rec_rcv_t                      pkey_rec_rcv;
+       osm_pkey_rec_rcv_ctrl_t                 pkey_rec_rcv_ctrl;
+
+       /* LinearForwardingTable Query */
+       osm_lftr_rcv_t                          lftr_rcv;
+       osm_lftr_rcv_ctrl_t                     lftr_rcv_ctrl;
+
+       /* SwitchInfo Query */
+       osm_sir_rcv_t                           sir_rcv;
+       osm_sir_rcv_ctrl_t                      sir_rcv_ctrl;
+
+       /* MulticastForwardingTable Query */
+       osm_mftr_rcv_t                          mftr_rcv;
+       osm_mftr_rcv_ctrl_t                     mftr_rcv_ctrl;
+} osm_sa_t;
+/*
+* FIELDS
+*      state
+*              State of this SA object
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_vendor
+*              Pointer to the vendor specific interfaces object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_mad_pool
+*              Pointer to the MAD pool.
+*
+*      p_disp
+*              Pointer to dispatcher
+*
+*      p_lock
+*              Pointer to Lock for serialization
+*
+*      sa_trans_id
+*              Transaction ID
+*
+*      mad_ctrl
+*              Mad Controller
+*
+*      resp
+*              Response object
+*
+*      nr
+*
+*      nr_ctrl
+*
+*      pir_rcv
+*
+*      pir_rcv_ctrl
+*
+*      lr
+*
+*      lr_ctrl
+*
+*      pr
+*
+*      pr_ctrl
+*
+*      smir
+*
+*      smir_ctrl
+*
+* SEE ALSO
+*      SM object
+*********/
+
+/****f* OpenSM: SA/osm_sa_construct
+* NAME
+*      osm_sa_construct
+*
+* DESCRIPTION
+*      This function constructs an SA object.
+*
+* SYNOPSIS
+*/
+void osm_sa_construct(
+       IN osm_sa_t* const p_sa );
+/*
+* PARAMETERS
+*      p_sa
+*              [in] Pointer to a SA object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_sa_init, osm_sa_destroy, and osm_sa_is_inited.
+*
+*      Calling osm_sa_construct is a prerequisite to calling any other
+*      method except osm_sa_init.
+*
+* SEE ALSO
+*      SA object, osm_sa_init, osm_sa_destroy, osm_sa_is_inited
+*********/
+
+/****f* OpenSM: SA/osm_sa_shutdown
+* NAME
+*      osm_sa_shutdown
+*
+* DESCRIPTION
+*      The osm_sa_shutdown function shutdowns an SA, unregistering from all
+*  dispatcher messages and unbinding the QP1 mad service 
+*
+* SYNOPSIS
+*/
+void osm_sa_shutdown(
+       IN osm_sa_t* const p_sa );
+/*
+* PARAMETERS
+*      p_sa
+*              [in] Pointer to a SA object to shutdown.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* SEE ALSO
+*      SA object, osm_sa_construct, osm_sa_init
+*********/
+
+/****f* OpenSM: SA/osm_sa_destroy
+* NAME
+*      osm_sa_destroy
+*
+* DESCRIPTION
+*      The osm_sa_destroy function destroys an SA, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_sa_destroy(
+       IN osm_sa_t* const p_sa );
+/*
+* PARAMETERS
+*      p_sa
+*              [in] Pointer to a SA object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified SA object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to osm_sa_construct or
+*      osm_sa_init.
+*
+* SEE ALSO
+*      SA object, osm_sa_construct, osm_sa_init
+*********/
+
+/****f* OpenSM: SA/osm_sa_init
+* NAME
+*      osm_sa_init
+*
+* DESCRIPTION
+*      The osm_sa_init function initializes a SA object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_sa_init(
+       IN osm_sm_t* const p_sm,
+       IN osm_sa_t* const p_sa,
+       IN osm_subn_t* const p_subn,
+       IN osm_vendor_t* const p_vendor,
+       IN osm_mad_pool_t* const p_mad_pool,
+       IN osm_log_t* const p_log,
+       IN osm_stats_t* const p_stats,
+       IN cl_dispatcher_t* const p_disp,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_sa
+*              [in] Pointer to an osm_sa_t object to initialize.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_vendor
+*              [in] Pointer to the vendor specific interfaces object.
+*
+*      p_mad_pool
+*              [in] Pointer to the MAD pool.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_stats
+*              [in] Pointer to the statistics object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the SA object was initialized successfully.
+*
+* NOTES
+*      Allows calling other SA methods.
+*
+* SEE ALSO
+*      SA object, osm_sa_construct, osm_sa_destroy,
+*      osm_sa_is_inited
+*********/
+
+/****f* OpenSM: SA/osm_sa_is_inited
+* NAME
+*      osm_sa_is_inited
+*
+* DESCRIPTION
+*      Indicates if the object has been initialized with osm_sa_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_sa_is_inited(
+       IN const osm_sa_t* const p_sa );
+/*
+* PARAMETERS
+*      p_sa
+*              [in] Pointer to an osm_sa_t object.
+*
+* RETURN VALUES
+*      TRUE if the object was initialized successfully,
+*      FALSE otherwise.
+*
+* NOTES
+*      The osm_sa_construct or osm_sa_init must be called before using
+*      this function.
+*
+* SEE ALSO
+*      SA object, osm_sa_construct, osm_sa_init
+*********/
+
+/****f* OpenSM: SA/osm_sa_bind
+* NAME
+*      osm_sa_bind
+*
+* DESCRIPTION
+*      Binds the SA object to a port guid.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sa_bind(
+       IN osm_sa_t* const p_sa,
+       IN const ib_net64_t port_guid );
+/*
+* PARAMETERS
+*      p_sa
+*              [in] Pointer to an osm_sa_t object to bind.
+*
+*      port_guid
+*              [in] Local port GUID with which to bind.
+*
+*
+* RETURN VALUES
+*      None
+*
+* NOTES
+*      A given SA object can only be bound to one port at a time.
+*
+* SEE ALSO
+*********/
+
+struct _osm_opensm_t;
+/****f* OpenSM: SA/osm_sa_db_file_dump
+* NAME
+*      osm_sa_db_file_dump
+*
+* DESCRIPTION
+*      Dumps the SA DB to the dump file.
+*
+* SYNOPSIS
+*/
+int osm_sa_db_file_dump(struct _osm_opensm_t *p_osm);
+/*
+* PARAMETERS
+*      p_osm
+*              [in] Pointer to an osm_opensm_t object.
+*
+* RETURN VALUES
+*      None
+*
+*********/
+
+/****f* OpenSM: SA/osm_sa_db_file_load
+* NAME
+*      osm_sa_db_file_load
+*
+* DESCRIPTION
+*      Loads SA DB from the file.
+*
+* SYNOPSIS
+*/
+int osm_sa_db_file_load(struct _osm_opensm_t *p_osm);
+/*
+* PARAMETERS
+*      p_osm
+*              [in] Pointer to an osm_opensm_t object.
+*
+* RETURN VALUES
+*      0 on success, other value on failure.
+*
+*********/
+
+END_C_DECLS
+
+#endif         /* _OSM_SA_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_class_port_info.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_class_port_info.h
new file mode 100644 (file)
index 0000000..ea64fbe
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_class_port_info.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_cpi_rcv_t.
+ *     This object represents the ClassPortInfo Receiver object.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+#ifndef _OSM_CPI_H_
+#define _OSM_CPI_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_qlockpool.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/ClassPort Info Receiver
+* NAME
+*      ClassPort Info Receiver
+*
+* DESCRIPTION
+*      The ClassPort Info Receiver object encapsulates the information
+*      needed to receive the ClassPortInfo request from a node.
+*
+*      The ClassPort Info Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: ClassPort Info Receiver/osm_cpi_rcv_t
+* NAME
+*      osm_cpi_rcv_t
+*
+* DESCRIPTION
+*      ClassPort Info Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_cpi_rcv
+{
+       osm_subn_t                                      *p_subn;
+       osm_sa_resp_t                           *p_resp;
+       osm_mad_pool_t                          *p_mad_pool;
+       osm_log_t                                       *p_log;
+       cl_plock_t                                      *p_lock;
+
+} osm_cpi_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_gen_req_ctrl
+*              Pointer to the generic request controller.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+* SEE ALSO
+*      ClassPort Info Receiver object
+*********/
+
+/****f* OpenSM: ClassPort Info Receiver/osm_cpi_rcv_construct
+* NAME
+*      osm_cpi_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a ClassPort Info Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_cpi_rcv_construct(
+       IN osm_cpi_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to a ClassPort Info Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_cpi_rcv_init, osm_cpi_rcv_destroy
+*
+*      Calling osm_cpi_rcv_construct is a prerequisite to calling any other
+*      method except osm_cpi_rcv_init.
+*
+* SEE ALSO
+*      ClassPort Info Receiver object, osm_cpi_rcv_init, osm_cpi_rcv_destroy
+*********/
+
+/****f* OpenSM: ClassPort Info Receiver/osm_cpi_rcv_destroy
+* NAME
+*      osm_cpi_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_cpi_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_cpi_rcv_destroy(
+       IN osm_cpi_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      ClassPort Info Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_cpi_rcv_construct or osm_cpi_rcv_init.
+*
+* SEE ALSO
+*      ClassPort Info Receiver object, osm_cpi_rcv_construct,
+*      osm_cpi_rcv_init
+*********/
+
+/****f* OpenSM: ClassPort Info Receiver/osm_cpi_rcv_init
+* NAME
+*      osm_cpi_rcv_init
+*
+* DESCRIPTION
+*      The osm_cpi_rcv_init function initializes a
+*      ClassPort Info Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_cpi_rcv_init(
+       IN osm_cpi_rcv_t* const p_rcv,
+       IN osm_sa_resp_t* const p_resp,
+       IN osm_mad_pool_t* const p_mad_pool,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_cpi_rcv_t object to initialize.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the ClassPort Info Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other ClassPort Info Receiver methods.
+*
+* SEE ALSO
+*      ClassPort Info Receiver object, osm_cpi_rcv_construct,
+*      osm_cpi_rcv_destroy
+*********/
+
+/****f* OpenSM: ClassPort Info Receiver/osm_cpi_rcv_process
+* NAME
+*      osm_cpi_rcv_process
+*
+* DESCRIPTION
+*      Process the ClassPortInfo request.
+*
+* SYNOPSIS
+*/
+void
+osm_cpi_rcv_process(
+       IN osm_cpi_rcv_t*                       const p_rcv,
+       IN const osm_madw_t*            const p_madw );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_cpi_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the ClassPortInfo attribute.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the ClassPortInfo processing was successful.
+*
+* NOTES
+*      This function processes a ClassPortInfo attribute.
+*
+* SEE ALSO
+*      ClassPort Info Receiver, ClassPort Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_CPI_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_class_port_info_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_class_port_info_ctrl.h
new file mode 100644 (file)
index 0000000..79f13b4
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_class_port_info_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_cpi_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA ClassPortInfo 
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+#ifndef _OSM_CPICTRL_H_
+#define _OSM_CPICTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_class_port_info.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Class Port Info Receive Controller
+* NAME
+*      Class Port Info Receive Controller
+*
+* DESCRIPTION
+*      The Class Port Info Receive Controller object encapsulates
+*      the information requested by the ClassPortInfo attribute.
+*
+*      The ClassPortInfo Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: ClassPort Info Receive Controller/osm_cpi_rcv_ctrl_t
+* NAME
+*      osm_cpi_rcv_ctrl_t
+*
+* DESCRIPTION
+*      ClassPort Info Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_cpi_rcv_ctrl
+{
+       osm_cpi_rcv_t                   *p_rcv;
+       osm_log_t                       *p_log;
+       cl_dispatcher_t                 *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_cpi_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the ClassPort Info Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      Class Port Info Receive Controller object
+*      Class Port Info Receiver object
+*********/
+
+/****f* OpenSM: Class Port Info Receive Controller/osm_cpi_rcv_ctrl_construct
+* NAME
+*      osm_cpi_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Class Port Info Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_cpi_rcv_ctrl_construct(
+       IN osm_cpi_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Class Port Info Receive Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_cpi_rcv_ctrl_init, osm_cpi_rcv_ctrl_destroy,
+*      and osm_cpi_rcv_ctrl_is_inited.
+*
+*      Calling osm_cpi_rcv_ctrl_construct is a prerequisite to calling any other
+*      method except osm_cpi_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Class Port Info Receive Controller object, osm_cpi_rcv_ctrl_init,
+*      osm_cpi_rcv_ctrl_destroy, osm_cpi_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Class Port Info Receive Controller/osm_cpi_rcv_ctrl_destroy
+* NAME
+*      osm_cpi_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_cpi_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_cpi_rcv_ctrl_destroy(
+       IN osm_cpi_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Class Port Info Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_cpi_rcv_ctrl_construct or osm_cpi_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Class Port Info Receive Controller object, osm_cpi_rcv_ctrl_construct,
+*      osm_cpi_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Class Port Info Receive Controller/osm_cpi_rcv_ctrl_init
+* NAME
+*      osm_cpi_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_cpi_rcv_ctrl_init function initializes a
+*      Class Port Info Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_cpi_rcv_ctrl_init(
+       IN osm_cpi_rcv_ctrl_t* const p_ctrl,
+       IN osm_cpi_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_cpi_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_cpi_rcv_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Class Port Info Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Class Port Info Receive Controller methods.
+*
+* SEE ALSO
+*      Class Port Info Receive Controller object, osm_cpi_rcv_ctrl_construct,
+*      osm_cpi_rcv_ctrl_destroy, osm_cpi_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Class Port Info Receive Controller/osm_cpi_rcv_ctrl_is_inited
+* NAME
+*      osm_cpi_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+*      Indicates if the object has been initialized with osm_cpi_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_cpi_rcv_ctrl_is_inited(
+       IN const osm_cpi_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_cpi_rcv_ctrl_t object.
+*
+* RETURN VALUES
+*      TRUE if the object was initialized successfully,
+*      FALSE otherwise.
+*
+* NOTES
+*      The osm_cpi_rcv_ctrl_construct or osm_cpi_rcv_ctrl_init must be
+*      called before using this function.
+*
+* SEE ALSO
+*      Class Port Info Receive Controller object, osm_cpi_rcv_ctrl_construct,
+*      osm_cpi_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_CPICTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_guidinfo_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_guidinfo_record.h
new file mode 100644 (file)
index 0000000..216b520
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_guidinfo_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_gir_rcv_t.
+ *     This object represents the GUIDInfo Record Receiver object.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ */
+
+#ifndef _OSM_GIR_RCV_H_
+#define _OSM_GIR_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/GUIDInfo Record Receiver
+* NAME
+*      GUIDInfo Record Receiver
+*
+* DESCRIPTION
+*      The GUIDInfo Record Receiver object encapsulates the information
+*      needed to receive the GUIDInfoRecord attribute from a node.
+*
+*      The GUIDInfo Record Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Hal Rosenstock, Voltaire 
+*
+*********/
+
+/****s* OpenSM: GUIDInfo Record Receiver/osm_gir_rcv_t
+* NAME
+*      osm_gir_rcv_t
+*
+* DESCRIPTION
+*      GUIDInfo Record Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_gir_rcv
+{
+       const osm_subn_t                        *p_subn;
+       osm_sa_resp_t                           *p_resp;
+       osm_mad_pool_t                          *p_mad_pool;
+       osm_log_t                                       *p_log;
+       cl_plock_t                                      *p_lock;
+       cl_qlock_pool_t                 pool;
+
+} osm_gir_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_resp
+*              Pointer to the SA responder.
+*
+*      p_mad_pool
+*              Pointer to the mad pool.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+*      pool
+*              Pool of linkable GUIDInfo Record objects used to generate
+*              the query response.
+*
+* SEE ALSO
+*      
+*********/
+
+/****f* OpenSM: GUIDInfo Record Receiver/osm_gir_rcv_construct
+* NAME
+*      osm_gir_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a GUIDInfo Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_gir_rcv_construct(
+       IN osm_gir_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to a GUIDInfo Record Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_gir_rcv_init, osm_gir_rcv_destroy
+*
+*      Calling osm_gir_rcv_construct is a prerequisite to calling any other
+*      method except osm_gir_rcv_init.
+*
+* SEE ALSO
+*      GUIDInfo Record Receiver object, osm_gir_rcv_init,
+*      osm_gir_rcv_destroy
+*********/
+
+/****f* OpenSM: GUIDInfo Record Receiver/osm_gir_rcv_destroy
+* NAME
+*      osm_gir_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_gir_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_gir_rcv_destroy(
+       IN osm_gir_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      GUIDInfo Record Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_gir_rcv_construct or osm_gir_rcv_init.
+*
+* SEE ALSO
+*      GUIDInfo Record Receiver object, osm_gir_rcv_construct,
+*      osm_gir_rcv_init
+*********/
+
+/****f* OpenSM: GUIDInfo Record Receiver/osm_gir_rcv_init
+* NAME
+*      osm_gir_rcv_init
+*
+* DESCRIPTION
+*      The osm_gir_rcv_init function initializes a
+*      GUIDInfo Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_gir_rcv_init(
+       IN osm_gir_rcv_t* const p_rcv,
+       IN osm_sa_resp_t* const p_resp,
+       IN osm_mad_pool_t* const p_mad_pool,
+       IN const osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_gir_rcv_t object to initialize.
+*
+*      p_req
+*              [in] Pointer to an osm_req_t object.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the GUIDInfo Record Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other GUIDInfo Record Receiver methods.
+*
+* SEE ALSO
+*      GUIDInfo Record Receiver object, osm_gir_rcv_construct,
+*      osm_gir_rcv_destroy
+*********/
+
+/****f* OpenSM: GUIDInfo Record Receiver/osm_gir_rcv_process
+* NAME
+*      osm_gir_rcv_process
+*
+* DESCRIPTION
+*      Process the GUIDInfoRecord attribute.
+*
+* SYNOPSIS
+*/
+void
+osm_gir_rcv_process(
+       IN osm_gir_rcv_t* const p_rcv,
+       IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_gir_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the node's GUIDInfoRecord attribute.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the GUIDInfoRecord processing was successful.
+*
+* NOTES
+*      This function processes a GUIDInfoRecord attribute.
+*
+* SEE ALSO
+*      GUIDInfo Record Receiver, GUIDInfo Record Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_GIR_RCV_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_guidinfo_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_guidinfo_record_ctrl.h
new file mode 100644 (file)
index 0000000..07e776e
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_guidinfo_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_sa_gir_rec_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA GUID Info 
+ *     record query from SA client.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ */
+
+#ifndef _OSM_GIR_CTRL_H_
+#define _OSM_GIR_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_guidinfo_record.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/GUID Info Record Receive Controller
+* NAME
+*      GUID Info Record Receive Controller
+*
+* DESCRIPTION
+*      The GUID Info Record Receive Controller object encapsulates
+*      the information needed to handle GUID Info record query from SA client.
+*
+*      The GUID Info Record Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Hal Rosenstock, Voltaire 
+*
+*********/
+
+/****s* OpenSM: GUID Info Record Receive Controller/osm_gir_rcv_ctrl_t
+* NAME
+*      osm_gir_rcv_ctrl_t
+*
+* DESCRIPTION
+*      GUID Info Record Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_gir_rcv_ctrl
+{
+       osm_gir_rcv_t                   *p_rcv;
+       osm_log_t                                       *p_log;
+       cl_dispatcher_t                 *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_gir_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the GUID Info Record Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      GUID Info Record Receive Controller object
+*      GUID Info Record Receiver object
+*********/
+
+/****f* OpenSM: GUID Info Record Receive Controller/osm_gir_rec_rcv_ctrl_construct
+* NAME
+*      osm_gir_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a GUID Info Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_gir_rcv_ctrl_construct(
+       IN osm_gir_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a GUID Info Record Receive Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_gir_rcv_ctrl_init, osm_gir_rcv_ctrl_destroy
+*
+*      Calling osm_gir_rcv_ctrl_construct is a prerequisite to calling any other
+*      method except osm_gir_rcv_ctrl_init.
+*
+* SEE ALSO
+*      GUID Info Record Receive Controller object, osm_gir_rcv_ctrl_init,
+*      osm_gir_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: GUID Info Record Receive Controller/osm_gir_rcv_ctrl_destroy
+* NAME
+*      osm_gir_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_gir_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_gir_rcv_ctrl_destroy(
+       IN osm_gir_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      GUIDInfo Record Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_gir_rcv_ctrl_construct or osm_gir_rcv_ctrl_init.
+*
+* SEE ALSO
+*      GUIDInfo Record Receive Controller object, osm_gir_rcv_ctrl_construct,
+*      osm_gir_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: GUID Info Record Receive Controller/osm_gir_rcv_ctrl_init
+* NAME
+*      osm_gir_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_gir_rcv_ctrl_init function initializes a
+*      GUID Info Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_gir_rcv_ctrl_init(
+       IN osm_gir_rcv_ctrl_t* const p_ctrl,
+       IN osm_gir_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_gir_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_gir_rcv_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the GUID Info Record Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other GUID Info Record Receive Controller methods.
+*
+* SEE ALSO
+*      GUID Info Record Receive Controller object, osm_gir_rcv_ctrl_construct,
+*      osm_gir_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_GIR_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_informinfo.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_informinfo.h
new file mode 100644 (file)
index 0000000..7bedf64
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_informinfo.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_infr_rcv_t.
+ *     This object represents the InformInfoRecord Receiver object.
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#ifndef _OSM_SA_INFR_H_
+#define _OSM_SA_INFR_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_timer.h>
+#include <complib/cl_qlockpool.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/InformInfo Receiver
+* NAME
+*      InformInfo Receiver
+*
+* DESCRIPTION
+*      The InformInfo Receiver object encapsulates the information
+*      needed to receive the InformInfo request from a node.
+*
+*      The InformInfo Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: InformInfo Receiver/osm_infr_rcv_t
+* NAME
+*      osm_infr_rcv_t
+*
+* DESCRIPTION
+*      InformInfo Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_infr_rcv
+{
+       osm_subn_t              *p_subn;
+       osm_sa_resp_t           *p_resp;
+       osm_mad_pool_t          *p_mad_pool;
+       osm_log_t               *p_log;
+       cl_plock_t              *p_lock;
+       cl_qlock_pool_t         pool;
+} osm_infr_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_resp
+*              Pointer to the osm_sa_resp_t object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+*      pool
+*              Pool of linkable InformInfo Record objects used to
+*              generate the query response.
+*
+* SEE ALSO
+*      InformInfo Receiver object
+*********/
+
+/****f* OpenSM: InformInfo Receiver/osm_infr_rcv_construct
+* NAME
+*      osm_infr_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a InformInfo Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_infr_rcv_construct(
+       IN osm_infr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to a InformInfo Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_infr_rcv_init, osm_infr_rcv_destroy
+*
+*      Calling osm_infr_rcv_construct is a prerequisite to calling any other
+*      method except osm_infr_rcv_init.
+*
+* SEE ALSO
+*      InformInfo Receiver object, osm_infr_rcv_init, osm_infr_rcv_destroy
+*********/
+
+/****f* OpenSM: InformInfo Receiver/osm_infr_rcv_destroy
+* NAME
+*      osm_infr_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_infr_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_infr_rcv_destroy(
+       IN osm_infr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      InformInfo Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_infr_rcv_construct or osm_infr_rcv_init.
+*
+* SEE ALSO
+*      InformInfo Receiver object, osm_infr_rcv_construct,
+*      osm_infr_rcv_init
+*********/
+
+/****f* OpenSM: InformInfo Receiver/osm_infr_rcv_init
+* NAME
+*      osm_infr_rcv_init
+*
+* DESCRIPTION
+*      The osm_infr_rcv_init function initializes a
+*      InformInfo Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_infr_rcv_init(
+       IN osm_infr_rcv_t* const p_rcv,
+       IN osm_sa_resp_t* const p_resp,
+       IN osm_mad_pool_t* const p_mad_pool,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_infr_rcv_t object to initialize.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the InformInfo Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other InformInfo Receiver methods.
+*
+* SEE ALSO
+*      InformInfo Receiver object, osm_infr_rcv_construct,
+*      osm_infr_rcv_destroy
+*********/
+
+/****f* OpenSM: InformInfo Receiver/osm_infr_rcv_process
+* NAME
+*      osm_infr_rcv_process
+*
+* DESCRIPTION
+*      Process the InformInfo request.
+*
+* SYNOPSIS
+*/
+void
+osm_infr_rcv_process(
+       IN osm_infr_rcv_t*              const p_rcv,
+       IN const osm_madw_t*            const p_madw );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_infr_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the node's InformInfo attribute.
+* NOTES
+*      This function processes a InformInfo attribute.
+*
+* SEE ALSO
+*      InformInfo Receiver
+*********/
+
+/****f* OpenSM: InformInfo Record Receiver/osm_infir_rcv_process
+* NAME
+*      osm_infir_rcv_process
+*
+* DESCRIPTION
+*      Process the InformInfo Record request.
+*
+* SYNOPSIS
+*/
+void
+osm_infir_rcv_process(
+       IN osm_infr_rcv_t*              const p_rcv,
+       IN const osm_madw_t*            const p_madw );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_infr_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the node's InformInfo Record attribute.
+* NOTES
+*      This function processes a InformInfo Record attribute.
+*
+* SEE ALSO
+*      InformInfo Receiver
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SA_INFR_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_informinfo_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_informinfo_ctrl.h
new file mode 100644 (file)
index 0000000..42113cf
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_informinfo_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_infr_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA InfromInfo
+ *     Set method attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#ifndef _OSM_INFR_RCV_CTRL_H_
+#define _OSM_INFR_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_inform.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/InformInfo Receive Controller
+* NAME
+*      InformInfo Receive Controller
+*
+* DESCRIPTION
+*      The InformInfo Receive Controller object encapsulates
+*      the information  needed to receive the InformInfo attribute from a node.
+*
+*      The InformInfo Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: InformInfo Receive Controller/osm_infr_rcv_ctrl_t
+* NAME
+*      osm_infr_rcv_ctrl_t
+*
+* DESCRIPTION
+*      InformInfo Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_infr_rcv_ctrl
+{
+  osm_infr_rcv_t               *p_rcv;
+  osm_log_t                    *p_log;
+  cl_dispatcher_t              *p_disp;
+  cl_disp_reg_handle_t         h_disp;
+  cl_disp_reg_handle_t         h_disp2;
+} osm_infr_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the InformInfo Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      InformInfo Receive Controller object
+*      InformInfo Receiver object
+*********/
+
+/****f* OpenSM: InformInfo Receive Controller/osm_infr_rcv_ctrl_construct
+* NAME
+*      osm_infr_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a InformInfo Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_infr_rcv_ctrl_construct(
+       IN osm_infr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a InformInfo Receive Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_infr_rcv_ctrl_init, osm_infr_rcv_ctrl_destroy,
+*      and osm_infr_rcv_ctrl_is_inited.
+*
+*      Calling osm_infr_rcv_ctrl_construct is a prerequisite to calling any
+*      other method except osm_infr_rcv_ctrl_init.
+*
+* SEE ALSO
+*      InformInfo Receive Controller object, osm_infr_rcv_ctrl_init,
+*      osm_infr_rcv_ctrl_destroy, osm_infr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: InformInfo Receive Controller/osm_infr_rcv_ctrl_destroy
+* NAME
+*      osm_infr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_infr_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_infr_rcv_ctrl_destroy(
+       IN osm_infr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      InformInfo Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_infr_rcv_ctrl_construct or osm_infr_rcv_ctrl_init.
+*
+* SEE ALSO
+*      InformInfo Receive Controller object, osm_infr_rcv_ctrl_construct,
+*      osm_infr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: InformInfo Receive Controller/osm_infr_rcv_ctrl_init
+* NAME
+*      osm_infr_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_infr_rcv_ctrl_init function initializes a
+*      InformInfo Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_infr_rcv_ctrl_init(
+       IN osm_infr_rcv_ctrl_t* const p_ctrl,
+       IN osm_infr_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_infr_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_infr_rcv_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the InformInfo Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other InformInfo Receive Controller methods.
+*
+* SEE ALSO
+*      InformInfo Receive Controller object, osm_infr_rcv_ctrl_construct,
+*      osm_infr_rcv_ctrl_destroy, osm_infr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: InformInfo Receive Controller/osm_infr_rcv_ctrl_is_inited
+* NAME
+*      osm_infr_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+*      Indicates if the object has been initialized with osm_infr_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_infr_rcv_ctrl_is_inited(
+       IN const osm_infr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_infr_rcv_ctrl_t object.
+*
+* RETURN VALUES
+*      TRUE if the object was initialized successfully,
+*      FALSE otherwise.
+*
+* NOTES
+*      The osm_infr_rcv_ctrl_construct or osm_infr_rcv_ctrl_init must be
+*      called before using this function.
+*
+* SEE ALSO
+*      InformInfo Receive Controller object, osm_infr_rcv_ctrl_construct,
+*      osm_infr_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_INFR_RCV_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_lft_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_lft_record.h
new file mode 100644 (file)
index 0000000..514e5c8
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_lft_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_lftr_rcv_t.
+ *     This object represents the LinearForwardingTable Receiver object.
+ *     attribute from a switch node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_LFTR_H_
+#define _OSM_LFTR_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Linear Forwarding Table Receiver
+* NAME
+*      Linear Forwarding Table Receiver
+*
+* DESCRIPTION
+*      The Linear Forwarding Table Receiver object encapsulates the information
+*      needed to receive the LinearForwardingTable attribute from a switch node.
+*
+*      The Linear Forwarding Table Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Eitan Zahavi, Mellanox Technologies LTD
+*
+*********/
+
+/****s* OpenSM: Linear Forwarding Table Receiver/osm_lftr_rcv_t
+* NAME
+*      osm_lftr_rcv_t
+*
+* DESCRIPTION
+*      Linear Forwarding Table Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lft
+{
+  osm_subn_t*                                  p_subn;
+  osm_stats_t*                                 p_stats;
+  osm_sa_resp_t*                               p_resp;
+  osm_mad_pool_t*                              p_mad_pool;
+  osm_log_t*                                   p_log;
+  cl_plock_t*                                  p_lock;
+  cl_qlock_pool_t                              pool;
+} osm_lftr_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_stats
+*              Pointer to the statistics.
+*
+*      p_resp
+*              Pointer to the SA responder.
+*
+*      p_mad_pool
+*              Pointer to the mad pool.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+*      pool
+*              Pool of linkable Linear Forwarding Table Record objects used to
+*               generate the query response.
+*
+* SEE ALSO
+*      Linear Forwarding Table Receiver object
+*********/
+
+/****f* OpenSM: Linear Forwarding Table Receiver/osm_lftr_rcv_construct
+* NAME
+*      osm_lftr_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a Linear Forwarding Table Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_lftr_rcv_construct(
+       IN osm_lftr_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Linear Forwarding Table Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_lftr_rcv_init, osm_lftr_rcv_destroy
+*
+*      Calling osm_lftr_rcv_construct is a prerequisite to calling any other
+*      method except osm_lftr_rcv_init.
+*
+* SEE ALSO
+*      Linear Forwarding Table Receiver object, osm_lftr_rcv_init, 
+*  osm_lftr_rcv_destroy
+*********/
+
+/****f* OpenSM: Linear Forwarding Table Receiver/osm_lftr_rcv_destroy
+* NAME
+*      osm_lftr_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_lftr_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_lftr_rcv_destroy(
+       IN osm_lftr_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Linear Forwarding Table Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_lftr_rcv_construct or osm_lftr_rcv_init.
+*
+* SEE ALSO
+*      Linear Forwarding Table Receiver object, osm_lftr_rcv_construct,
+*      osm_lftr_rcv_init
+*********/
+
+/****f* OpenSM: Linear Forwarding Table Receiver/osm_lftr_rcv_init
+* NAME
+*      osm_lftr_rcv_init
+*
+* DESCRIPTION
+*      The osm_lftr_rcv_init function initializes a
+*      Linear Forwarding Table Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_lftr_rcv_init(
+       IN osm_lftr_rcv_t* const p_rcv,
+       IN osm_sa_resp_t* const p_resp,
+       IN osm_mad_pool_t* const p_mad_pool,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_lftr_rcv_t object to initialize.
+*
+*      p_req
+*              [in] Pointer to an osm_req_t object.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Linear Forwarding Table Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Linear Forwarding Table Receiver methods.
+*
+* SEE ALSO
+*      Linear Forwarding Table Receiver object, osm_lftr_rcv_construct, 
+*  osm_lftr_rcv_destroy
+*********/
+
+/****f* OpenSM: Linear Forwarding Table Receiver/osm_lftr_rcv_process
+* NAME
+*      osm_lftr_rcv_process
+*
+* DESCRIPTION
+*      Process the LinearForwardingTable attribute.
+*
+* SYNOPSIS
+*/
+void osm_lftr_rcv_process(
+       IN osm_lftr_rcv_t* const p_ctrl,
+       IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_lftr_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the switch node's LinearForwardingTable attribute.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the LinearForwardingTable processing was successful.
+*
+* NOTES
+*      This function processes a LinearForwardingTable attribute.
+*
+* SEE ALSO
+*      Linear Forwarding Table Receiver, Linear Forwarding Table Response
+*  Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LFTR_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_lft_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_lft_record_ctrl.h
new file mode 100644 (file)
index 0000000..ca6b98d
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_lft_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_lftr_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA
+ *     LinearForwardingTable attribute from a switch.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_LFTR_RCV_CTRL_H_
+#define _OSM_LFTR_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_lft_record.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Linear Forwarding Table Receive Controller
+* NAME
+*      Linear Forwarding Table Record Receive Controller
+*
+* DESCRIPTION
+*      The Linear Forwarding Table Receive Controller object encapsulates
+*      the information needed to receive the LinearFowardingTable attribute
+*  from a switch node.
+*
+*      The Linear Forwarding Table Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Eitan Zahavi, Mellanox Technologies LTD
+*
+*********/
+
+/****s* OpenSM: Linear Forwarding Table Receive Controller/osm_lftr_rcv_ctrl_t
+* NAME
+*      osm_lftr_rcv_ctrl_t
+*
+* DESCRIPTION
+*      Linear Forwarding Table Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lftr_rcv_ctrl
+{
+       osm_lftr_rcv_t                  *p_rcv;
+       osm_log_t                       *p_log;
+       cl_dispatcher_t                 *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_lftr_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the Linear Forwarding Table Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      Linear Forwarding Table Receive Controller object
+*      Linear Forwarding Table Receiver object
+*********/
+
+/****f* OpenSM: Linear Forwarding Table Receive Controller/osm_lftr_rcv_ctrl_construct
+* NAME
+*      osm_lftr_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Linear Forwarding Table Receive
+*  Controller object.
+*
+* SYNOPSIS
+*/
+void osm_lftr_rcv_ctrl_construct(
+       IN osm_lftr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Linear Forwarding Table Receive Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_lftr_rcv_ctrl_init, osm_lftr_rcv_ctrl_destroy
+*
+*      Calling osm_lftr_rcv_ctrl_construct is a prerequisite to calling any other
+*      method except osm_lftr_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Linear Forwarding Table Receive Controller object, osm_lftr_rcv_ctrl_init,
+*      osm_lftr_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: Linear Forwarding Table Receive Controller/osm_lftr_rcv_ctrl_destroy
+* NAME
+*      osm_lftr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_lftr_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_lftr_rcv_ctrl_destroy(
+       IN osm_lftr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Linear Forwarding Table Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_lftr_rcv_ctrl_construct or osm_lftr_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Linear Forwarding Table Receive Controller object, osm_lftr_rcv_ctrl_construct,
+*      osm_lftr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Linear Forwarding Table Receive Controller/osm_lftr_rcv_ctrl_init
+* NAME
+*      osm_lftr_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_lftr_rcv_ctrl_init function initializes a
+*      Linear Forwarding Table Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_lftr_rcv_ctrl_init(
+       IN osm_lftr_rcv_ctrl_t* const p_ctrl,
+       IN osm_lftr_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_lftr_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_lftr_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Linear Forwarding Table Receive Controller object
+*  was initialized successfully.
+*
+* NOTES
+*      Allows calling other Linear Forwarding Table Receive Controller methods.
+*
+* SEE ALSO
+*      Linear Forwarding Table Receive Controller object, 
+*  osm_lftr_rcv_ctrl_construct, osm_lftr_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LFTR_RCV_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_link_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_link_record.h
new file mode 100644 (file)
index 0000000..fbab6e3
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_link_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_lr_rcv_t.
+ *     This object represents the Link Record Receiver object.
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_LR_RCV_H_
+#define _OSM_LR_RCV_H_
+
+#include <complib/cl_qlockpool.h>
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Link Record Receiver
+* NAME
+*      Link Record Receiver
+*
+* DESCRIPTION
+*      The Link Record Receiver object encapsulates the information
+*      needed to receive the Link Record attribute from a node.
+*
+*      The Link Record Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Ranjit Pandit, Intel
+*
+*********/
+
+/****s* OpenSM: Link Record Receiver/osm_lr_rcv_t
+* NAME
+*      osm_lr_rcv_t
+*
+* DESCRIPTION
+*      Link Record Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lr_rcv
+{
+       osm_subn_t                                      *p_subn;
+       osm_sa_resp_t                           *p_resp;
+       osm_mad_pool_t                          *p_mad_pool;
+       osm_log_t                                       *p_log;
+       cl_plock_t                                      *p_lock;
+       cl_qlock_pool_t                         lr_pool;
+
+} osm_lr_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_resp
+*              Pointer to the SA responder.
+*
+*      p_mad_pool
+*              Pointer to the mad pool.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+*      lr_pool
+*              Pool of link record objects used to generate the query response.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Link Record Receiver/osm_lr_rcv_construct
+* NAME
+*      osm_lr_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a Link Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_lr_rcv_construct(
+       IN osm_lr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to a Link Record Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_lr_rcv_init, osm_lr_rcv_destroy
+*
+*      Calling osm_lr_rcv_construct is a prerequisite to calling any other
+*      method except osm_lr_rcv_init.
+*
+* SEE ALSO
+*      Link Record Receiver object, osm_lr_rcv_init, osm_lr_rcv_destroy
+*********/
+
+/****f* OpenSM: Link Record Receiver/osm_lr_rcv_destroy
+* NAME
+*      osm_lr_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_lr_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_lr_rcv_destroy(
+       IN osm_lr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Link Record Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_lr_rcv_construct or osm_lr_rcv_init.
+*
+* SEE ALSO
+*      Link Record Receiver object, osm_lr_rcv_construct,
+*      osm_lr_rcv_init
+*********/
+
+/****f* OpenSM: Link Record Receiver/osm_lr_rcv_init
+* NAME
+*      osm_lr_rcv_init
+*
+* DESCRIPTION
+*      The osm_lr_rcv_init function initializes a
+*      Link Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_lr_rcv_init(
+       IN osm_lr_rcv_t* const p_rcv,
+       IN osm_sa_resp_t* const p_resp,
+       IN osm_mad_pool_t* const p_mad_pool,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_lr_rcv_t object to initialize.
+*
+*      p_resp
+*              [in] Pointer to the SA Responder object.
+*
+*      p_mad_pool
+*              [in] Pointer to the mad pool.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the Link Record Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Link Record Receiver methods.
+*
+* SEE ALSO
+*      Link Record Receiver object, osm_lr_rcv_construct, osm_lr_rcv_destroy
+*********/
+
+/****f* OpenSM: Link Record Receiver/osm_lr_rcv_process
+* NAME
+*      osm_lr_rcv_process
+*
+* DESCRIPTION
+*      Process the Link Record attribute.
+*
+* SYNOPSIS
+*/
+void osm_lr_rcv_process(
+       IN osm_lr_rcv_t* const p_rcv,
+       IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_lr_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the node's Link Record attribute.
+*
+* NOTES
+*      This function processes a Link Record attribute.
+*
+* SEE ALSO
+*      Link Record Receiver, Link Record Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LR_RCV_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_link_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_link_record_ctrl.h
new file mode 100644 (file)
index 0000000..d4a740a
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_link_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_lr_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA Link Record
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_LR_CTRL_H_
+#define _OSM_LR_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_link_record.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Link Record Receive Controller
+* NAME
+*      Link Record Receive Controller
+*
+* DESCRIPTION
+*      The Link Record Receive Controller object encapsulates
+*      the information needed to receive the LinkRecord attribute from a node.
+*
+*      The Link Record Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Ranjit Pandit, Intel
+*
+*********/
+
+/****s* OpenSM: Link Record Receive Controller/osm_lr_rcv_ctrl_t
+* NAME
+*      osm_lr_rcv_ctrl_t
+*
+* DESCRIPTION
+*      Link Record Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lr_rcv_ctrl
+{
+       osm_lr_rcv_t                    *p_rcv;
+       osm_log_t                       *p_log;
+       cl_dispatcher_t                 *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_lr_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the Link Record Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      Link Record Receive Controller object
+*      Link Record Receiver object
+*********/
+
+/****f* OpenSM: Link Record Receive Controller/osm_lr_rcv_ctrl_construct
+* NAME
+*      osm_lr_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Link Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_lr_rcv_ctrl_construct(
+       IN osm_lr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Link Record Receive Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_lr_rcv_ctrl_init, osm_lr_rcv_ctrl_destroy,
+*      and osm_lr_rcv_ctrl_is_inited.
+*
+*      Calling osm_lr_rcv_ctrl_construct is a prerequisite to calling any other
+*      method except osm_lr_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Link Record Receive Controller object, osm_lr_rcv_ctrl_init,
+*      osm_lr_rcv_ctrl_destroy, osm_lr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Link Record Receive Controller/osm_lr_rcv_ctrl_destroy
+* NAME
+*      osm_lr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_lr_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_lr_rcv_ctrl_destroy(
+       IN osm_lr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Link Record Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_lr_rcv_ctrl_construct or osm_lr_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Link Record Receive Controller object, osm_lr_rcv_ctrl_construct,
+*      osm_lr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Link Record Receive Controller/osm_lr_rcv_ctrl_init
+* NAME
+*      osm_lr_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_lr_rcv_ctrl_init function initializes a
+*      Link Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_lr_rcv_ctrl_init(
+       IN osm_lr_rcv_ctrl_t* const p_ctrl,
+       IN osm_lr_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_lr_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_lr_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Link Record Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Link Record Receive Controller methods.
+*
+* SEE ALSO
+*      Link Record Receive Controller object, osm_lr_rcv_ctrl_construct,
+*      osm_lr_rcv_ctrl_destroy, osm_lr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Link Record Receive Controller/osm_lr_rcv_ctrl_is_inited
+* NAME
+*      osm_lr_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+*      Indicates if the object has been initialized with osm_lr_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_lr_rcv_ctrl_is_inited(
+       IN const osm_lr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_lr_rcv_ctrl_t object.
+*
+* RETURN VALUES
+*      TRUE if the object was initialized successfully,
+*      FALSE otherwise.
+*
+* NOTES
+*      The osm_lr_rcv_ctrl_construct or osm_lr_rcv_ctrl_init must be
+*      called before using this function.
+*
+* SEE ALSO
+*      Link Record Receive Controller object, osm_lr_rcv_ctrl_construct,
+*      osm_lr_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LR_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mad_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mad_ctrl.h
new file mode 100644 (file)
index 0000000..085eab7
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_mad_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_sa_mad_ctrl_t.
+ *     This object represents a controller that receives the IBA SA 
+ *     attributes from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SA_MAD_CTRL_H_
+#define _OSM_SA_MAD_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_response.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SA MAD Controller
+* NAME
+*      SA MAD Controller
+*
+* DESCRIPTION
+*      The SA MAD Controller object encapsulates
+*      the information needed to receive MADs from the transport layer.
+*
+*      The SA MAD Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Ranjit Pandit, Intel
+*
+*********/
+
+/****s* OpenSM: SA MAD Controller/osm_sa_mad_ctrl_t
+* NAME
+*      osm_sa_mad_ctrl_t
+*
+* DESCRIPTION
+*      SA MAD Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sa_mad_ctrl
+{
+  osm_log_t             *p_log;
+  osm_mad_pool_t        *p_mad_pool;
+  osm_vendor_t          *p_vendor;
+  osm_bind_handle_t      h_bind;
+  cl_dispatcher_t       *p_disp;
+  cl_disp_reg_handle_t   h_disp;
+  osm_stats_t           *p_stats;
+  osm_subn_t            *p_subn;
+  osm_sa_resp_t         *p_resp;  
+} osm_sa_mad_ctrl_t;
+/*
+* FIELDS
+*      p_log
+*              Pointer to the log object.
+*
+*      p_mad_pool
+*              Pointer to the MAD pool.
+*
+*      p_vendor
+*              Pointer to the vendor specific interfaces object.
+*
+*      h_bind
+*              Bind handle returned by the transport layer.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+*      p_stats
+*              Pointer to the OpenSM statistics block.
+*
+*  p_resp
+*     Pointer to the SA response manager
+*
+* SEE ALSO
+*      SA MAD Controller object
+*      SA MADr object
+*********/
+
+/****f* OpenSM: SA MAD Controller/osm_sa_mad_ctrl_construct
+* NAME
+*      osm_sa_mad_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a SA MAD Controller object.
+*
+* SYNOPSIS
+*/
+void osm_sa_mad_ctrl_construct(
+       IN osm_sa_mad_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a SA MAD Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_sa_mad_ctrl_init, and osm_sa_mad_ctrl_destroy.
+*
+*      Calling osm_sa_mad_ctrl_construct is a prerequisite to calling any other
+*      method except osm_sa_mad_ctrl_init.
+*
+* SEE ALSO
+*      SA MAD Controller object, osm_sa_mad_ctrl_init,
+*      osm_sa_mad_ctrl_destroy
+*********/
+
+/****f* OpenSM: SA MAD Controller/osm_sa_mad_ctrl_destroy
+* NAME
+*      osm_sa_mad_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_sa_mad_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_sa_mad_ctrl_destroy(
+       IN osm_sa_mad_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      SA MAD Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_sa_mad_ctrl_construct or osm_sa_mad_ctrl_init.
+*
+* SEE ALSO
+*      SA MAD Controller object, osm_sa_mad_ctrl_construct,
+*      osm_sa_mad_ctrl_init
+*********/
+
+/****f* OpenSM: SA MAD Controller/osm_sa_mad_ctrl_init
+* NAME
+*      osm_sa_mad_ctrl_init
+*
+* DESCRIPTION
+*      The osm_sa_mad_ctrl_init function initializes a
+*      SA MAD Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_sa_mad_ctrl_init(
+       IN osm_sa_mad_ctrl_t* const p_ctrl,
+   IN osm_sa_resp_t*     const p_resp,
+       IN osm_mad_pool_t* const p_mad_pool,
+       IN osm_vendor_t* const p_vendor,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN osm_stats_t* const p_stats,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_sa_mad_ctrl_t object to initialize.
+*
+*  p_resp
+*     [in] Pointer to the response SA manager object
+*
+*      p_mad_pool
+*              [in] Pointer to the MAD pool.
+*
+*      p_vendor
+*              [in] Pointer to the vendor specific interfaces object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_stats
+*              [in] Pointer to the OpenSM stastics block.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the SA MAD Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other SA MAD Controller methods.
+*
+* SEE ALSO
+*      SA MAD Controller object, osm_sa_mad_ctrl_construct,
+*      osm_sa_mad_ctrl_destroy
+*********/
+
+/****f* OpenSM: SA/osm_sa_mad_ctrl_bind
+* NAME
+*      osm_sa_mad_ctrl_bind
+*
+* DESCRIPTION
+*      Binds the SA MAD Controller object to a port guid.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sa_mad_ctrl_bind(
+       IN osm_sa_mad_ctrl_t* const p_ctrl,
+       IN const ib_net64_t port_guid );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_sa_mad_ctrl_t object to initialize.
+*
+*      port_guid
+*              [in] Local port GUID with which to bind.
+*
+*
+* RETURN VALUES
+*      None
+*
+* NOTES
+*      A given SA MAD Controller object can only be bound to one
+*      port at a time.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: SA/osm_sa_mad_ctrl_unbind
+* NAME
+*      osm_sa_mad_ctrl_unbind
+*
+* DESCRIPTION
+*      Un-Binds the SA MAD Controller object from the IB port
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sa_mad_ctrl_unbind(
+  IN osm_sa_mad_ctrl_t* const p_ctrl);
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_sa_mad_ctrl_t object to initialize.
+*
+* RETURN VALUES
+*      None
+*
+* NOTES
+*      A given SA MAD Controller should be previously bound to IB
+*      port.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: SA/osm_sa_mad_ctrl_get_bind_handle
+* NAME
+*      osm_sa_mad_ctrl_get_bind_handle
+*
+* DESCRIPTION
+*      Returns the bind handle.
+*
+* SYNOPSIS
+*/
+static inline osm_bind_handle_t
+osm_sa_mad_ctrl_get_bind_handle(
+       IN const osm_sa_mad_ctrl_t* const p_ctrl )
+{
+       return( p_ctrl->h_bind );
+}
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_sa_mad_ctrl_t object.
+*
+* RETURN VALUES
+*      Returns the bind handle, which may be OSM_BIND_INVALID_HANDLE
+*      if no port has been bound.
+*
+* NOTES
+*      A given SA MAD Controller object can only be bound to one
+*      port at a time.
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SA_MAD_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mcmember_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mcmember_record.h
new file mode 100644 (file)
index 0000000..0ee1f28
--- /dev/null
@@ -0,0 +1,420 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_mcmember_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_mcmr_recv_t.
+ *     This object represents the MCMemberRecord Receiver object.
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#ifndef _OSM_MCMR_H_
+#define _OSM_MCMR_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_sm.h>
+#include <opensm/osm_multicast.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/MCMember Receiver
+* NAME
+*      MCMember Receiver
+*
+* DESCRIPTION
+*      The MCMember Receiver object encapsulates the information
+*      needed to receive the MCMemberRecord attribute from a node.
+*
+*      The MCMember Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Anil Keshavamurthy, Intel
+*
+*********/
+
+/****s* OpenSM: MCMember Receiver/osm_mcmr_recv_t
+* NAME
+*      osm_mcmr_recv_t
+*
+* DESCRIPTION
+*      MCMember Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+
+
+typedef struct _osm_mcmr
+{
+       osm_subn_t                                      *p_subn;
+       osm_sm_t                                           *p_sm;
+       osm_sa_resp_t                           *p_resp;
+       osm_mad_pool_t                          *p_mad_pool;
+       osm_log_t                                       *p_log;
+       cl_plock_t                                      *p_lock;
+       uint16_t                                           mlid_ho;
+       cl_qlock_pool_t                 pool;
+} osm_mcmr_recv_t;
+
+
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_gen_req_ctrl
+*              Pointer to the generic request controller.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+* SEE ALSO
+*      MCMember Receiver object
+*********/
+
+/****f* OpenSM: MCMember Receiver/osm_mcmr_rcv_construct
+* NAME
+*      osm_mcmr_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a MCMember Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_mcmr_rcv_construct(
+       IN osm_mcmr_recv_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a MCMember Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_mcmr_rcv_init, osm_mcmr_rcv_destroy
+*
+*      Calling osm_mcmr_rcv_construct is a prerequisite to calling any other
+*      method except osm_mcmr_init.
+*
+* SEE ALSO
+*      MCMember Receiver object, osm_mcmr_init,
+*      osm_mcmr_rcv_destroy
+*********/
+
+/****f* OpenSM: MCMember Receiver/osm_mcmr_rcv_destroy
+* NAME
+*      osm_mcmr_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_mcmr_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_mcmr_rcv_destroy(
+       IN osm_mcmr_recv_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      MCMember Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_mcmr_rcv_construct or osm_mcmr_init.
+*
+* SEE ALSO
+*      MCMember Receiver object, osm_mcmr_rcv_construct,
+*      osm_mcmr_init
+*********/
+
+/****f* OpenSM: MCMember Receiver/osm_mcmr_rcv_init
+* NAME
+*      osm_mcmr_init
+*
+* DESCRIPTION
+*      The osm_mcmr_init function initializes a
+*      MCMember Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_mcmr_rcv_init(
+       IN osm_sm_t * const p_sm,
+       IN osm_mcmr_recv_t* const p_ctrl,
+       IN osm_sa_resp_t* const p_resp,
+       IN osm_mad_pool_t* const p_mad_pool,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_sm
+*              [in] pointer to osm_sm_t object
+*      p_ctrl
+*              [in] Pointer to an osm_mcmr_recv_t object to initialize.
+*
+*      p_req
+*              [in] Pointer to an osm_req_t object.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the MCMember Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other MCMember Receiver methods.
+*
+* SEE ALSO
+*      MCMember Receiver object, osm_mcmr_rcv_construct,
+*      osm_mcmr_rcv_destroy
+*********/
+
+/****f* OpenSM: MCMember Receiver/osm_mcmr_rcv_process
+* NAME
+*      osm_mcmr_rcv_process
+*
+* DESCRIPTION
+*      Process the MCMemberRecord attribute.
+*
+* SYNOPSIS
+*/
+void osm_mcmr_rcv_process(
+       IN osm_mcmr_recv_t* const p_ctrl,
+       IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_mcmr_recv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the node's MCMemberRecord attribute.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the MCMemberRecord processing was successful.
+*
+* NOTES
+*      This function processes a MCMemberRecord attribute.
+*
+* SEE ALSO
+*      MCMember Receiver, MCMember Response Controller
+*********/
+
+
+
+/****f* OpenSM: MC Member Record Receiver/osm_mcmr_rcv_create_new_mgrp
+* NAME
+*      osm_mcmr_rcv_create_new_mgrp
+*
+* DESCRIPTION
+*      Create new Multicast group
+*
+* SYNOPSIS
+*/
+
+ib_api_status_t
+osm_mcmr_rcv_create_new_mgrp(
+                                                                         IN osm_mcmr_recv_t* const p_mcmr,
+                                                                         IN uint64_t comp_mask,
+                                                                         IN const ib_member_rec_t* const p_recvd_mcmember_rec, 
+                             IN const osm_physp_t* const p_req_physp,
+                                                                         OUT osm_mgrp_t **pp_mgrp);
+/*
+* PARAMETERS
+*      p_mcmr
+*              [in] Pointer to an osm_mcmr_recv_t object.
+*      p_recvd_mcmember_rec
+*              [in] Received Multicast member record
+*
+*  p_req_physp
+*     [in] The requesting osm_physp_t object. 
+*     NULL if the creation is without a requesting port (e.g - ipoib known mcgroups)
+*
+*      pp_mgrp
+*              [out] pointer the osm_mgrp_t object
+*              
+* RETURN VALUES
+*      IB_SUCCESS, IB_ERROR
+*
+* NOTES
+*
+*
+* SEE ALSO
+*      
+*********/
+
+/****f* OpenSM: MC Member Record Receiver/osm_mcmr_rcv_find_or_create_new_mgrp
+* NAME
+*      osm_mcmr_rcv_find_or_create_new_mgrp
+*
+* DESCRIPTION
+*      Create new Multicast group
+*
+* SYNOPSIS
+*/
+
+ib_api_status_t
+osm_mcmr_rcv_find_or_create_new_mgrp(
+         IN osm_mcmr_recv_t* const p_mcmr,
+         IN uint64_t comp_mask,
+         IN ib_member_rec_t* const p_recvd_mcmember_rec,
+         OUT osm_mgrp_t **pp_mgrp);
+/*
+* PARAMETERS
+*      p_mcmr
+*              [in] Pointer to an osm_mcmr_recv_t object.
+*      p_recvd_mcmember_rec
+*              [in] Received Multicast member record
+*
+*      pp_mgrp
+*              [out] pointer the osm_mgrp_t object
+*
+* RETURN VALUES
+*      IB_SUCCESS, IB_ERROR
+*
+* NOTES
+*
+*
+* SEE ALSO
+*
+*********/
+
+#define JOIN_MC_COMP_MASK      (IB_MCR_COMPMASK_MGID |         \
+                                                       IB_MCR_COMPMASK_PORT_GID |      \
+                                                       IB_MCR_COMPMASK_JOIN_STATE)
+
+#define REQUIRED_MC_CREATE_COMP_MASK   (IB_MCR_COMPMASK_MGID           | \
+                                                                               IB_MCR_COMPMASK_PORT_GID        | \
+                                                                               IB_MCR_COMPMASK_JOIN_STATE      | \
+                                                                               IB_MCR_COMPMASK_QKEY            | \
+                                                                               IB_MCR_COMPMASK_TCLASS          | \
+                                                                               IB_MCR_COMPMASK_PKEY            | \
+                                                                               IB_MCR_COMPMASK_FLOW            | \
+                                                                               IB_MCR_COMPMASK_SL) 
+
+/****d* OpenSM: MC Member Record Receiver/OSM_DEFAULT_MGRP_MTU
+* Name
+*      OSM_DEFAULT_MGRP_MTU
+*
+* DESCRIPTION
+*      Default MTU used for new MGRP creation (2048 bytes)
+*  Note it includes the MTUSelector which is set to "Greater Than"
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_MGRP_MTU 0x04
+/***********/
+
+/****d* OpenSM: MC Member Record Receiver/OSM_DEFAULT_MGRP_RATE
+* Name
+*      OSM_DEFAULT_MGRP_RATE
+*
+* DESCRIPTION
+*      Default RATE used for new MGRP creation (10Gb/sec)
+*  Note it includes the RateSelector which is set to "Greater Than"
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_MGRP_RATE 0x03
+/***********/
+
+/* Scope component definitions from IBA 1.2 (Table 3 p. 146) */
+#define MC_SCOPE_LINK_LOCAL            0x2
+#define MC_SCOPE_SITE_LOCAL            0x5
+#define MC_SCOPE_ORG_LOCAL             0x8
+#define MC_SCOPE_GLOBAL                        0xE
+
+/****d* OpenSM: MC Member Record Receiver/OSM_DEFAULT_MGRP_SCOPE
+* Name
+*      OSM_DEFAULT_MGRP_SCOPE
+*
+* DESCRIPTION
+*      Default SCOPE used for new MGRP creation (link local)
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_MGRP_SCOPE MC_SCOPE_LINK_LOCAL
+/***********/
+
+/* JoinState definitions from IBA 1.2 */
+#define MC_FULL_MEMBER                 0x1
+#define MC_NON_MEMBER                  0x2
+#define MC_SENDONLY_NON_MEMBER         0x4
+
+END_C_DECLS
+
+#endif /* _OSM_MCMR_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mcmember_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mcmember_record_ctrl.h
new file mode 100644 (file)
index 0000000..3adc02d
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_mcmember_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_mcmr_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA MCMemberRecord 
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_MCMRCTRL_H
+#define _OSM_MCMRCTRL_H
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_mcmember_record.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/MCMember Receive Controller
+* NAME
+*      MCMember Receive Controller
+*
+* DESCRIPTION
+*      The MCMember Receive Controller object encapsulates
+*      the information needed to receive the MCMemberRecord attribute from a node.
+*
+*      The MCMember Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Ranjit Pandit, Intel
+*
+*********/
+
+/****s* OpenSM: MCMember Receive Controller/osm_mcmr_rcv_ctrl_t
+* NAME
+*      osm_mcmr_rcv_ctrl_t
+*
+* DESCRIPTION
+*      MCMember Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mcmr_rcv_ctrl
+{
+       osm_mcmr_recv_t                 *p_rcv;
+       osm_log_t                       *p_log;
+       cl_dispatcher_t                 *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_mcmr_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the MCMember Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      MCMember Receive Controller object
+*      MCMember Receiver object
+*********/
+
+/****f* OpenSM: MCMember Receive Controller/osm_mcmr_rcv_ctrl_construct
+* NAME
+*      osm_mcmr_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a MCMember Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_mcmr_rcv_ctrl_construct(
+       IN osm_mcmr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a MCMember Receive Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_mcmr_rcv_ctrl_init, osm_mcmr_rcv_ctrl_destroy,
+*      and osm_mcmr_ctrl_is_inited.
+*
+*      Calling osm_mcmr_rcv_ctrl_construct is a prerequisite to calling any other
+*      method except osm_mcmr_rcv_ctrl_init.
+*
+* SEE ALSO
+*      MCMember Receive Controller object, osm_mcmr_rcv_ctrl_init,
+*      osm_mcmr_rcv_ctrl_destroy, osm_mcmr_ctrl_is_inited
+*********/
+
+/****f* OpenSM: MCMember Receive Controller/osm_mcmr_rcv_ctrl_destroy
+* NAME
+*      osm_mcmr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_mcmr_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_mcmr_rcv_ctrl_destroy(
+       IN osm_mcmr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      MCMember Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_mcmr_rcv_ctrl_construct or osm_mcmr_rcv_ctrl_init.
+*
+* SEE ALSO
+*      MCMember Receive Controller object, osm_mcmr_rcv_ctrl_construct,
+*      osm_mcmr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: MCMember Receive Controller/osm_mcmr_rcv_ctrl_init
+* NAME
+*      osm_mcmr_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_mcmr_rcv_ctrl_init function initializes a
+*      MCMember Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_mcmr_rcv_ctrl_init(
+       IN osm_mcmr_rcv_ctrl_t* const p_ctrl,
+       IN osm_mcmr_recv_t* const p_mcmr,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_mcmr_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_mcmr_recv_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the MCMember Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other MCMember Receive Controller methods.
+*
+* SEE ALSO
+*      MCMember Receive Controller object, osm_mcmr_rcv_ctrl_construct,
+*      osm_mcmr_rcv_ctrl_destroy, osm_mcmr_ctrl_is_inited
+*********/
+
+/****f* OpenSM: MCMember Receive Controller/osm_mcmr_ctrl_is_inited
+* NAME
+*      osm_mcmr_ctrl_is_inited
+*
+* DESCRIPTION
+*      Indicates if the object has been initialized with osm_mcmr_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_mcmr_ctrl_is_inited(
+       IN const osm_mcmr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_mcmr_rcv_ctrl_t object.
+*
+* RETURN VALUES
+*      TRUE if the object was initialized successfully,
+*      FALSE otherwise.
+*
+* NOTES
+*      The osm_mcmr_rcv_ctrl_construct or osm_mcmr_rcv_ctrl_init must be
+*      called before using this function.
+*
+* SEE ALSO
+*      MCMember Receive Controller object, osm_mcmr_rcv_ctrl_construct,
+*      osm_mcmr_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MCMRCTRL_H */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mft_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mft_record.h
new file mode 100644 (file)
index 0000000..a4e4248
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_mftr_rcv_t.
+ *     This object represents the MulticastForwardingTable Receiver object.
+ *     attribute from a switch node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ */
+
+#ifndef _OSM_MFTR_H_
+#define _OSM_MFTR_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Multicast Forwarding Table Receiver
+* NAME
+*      Multicast Forwarding Table Receiver
+*
+* DESCRIPTION
+*      The Multicast Forwarding Table Receiver object encapsulates the information
+*      needed to receive the MulticastForwardingTable attribute from a switch node.
+*
+*      The Multicast Forwarding Table Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Hal Rosenstock, Voltaire
+*
+*********/
+
+/****s* OpenSM: Multicast Forwarding Table Receiver/osm_mftr_rcv_t
+* NAME
+*      osm_mftr_rcv_t
+*
+* DESCRIPTION
+*      Multicast Forwarding Table Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mft
+{
+  osm_subn_t*                                  p_subn;
+  osm_stats_t*                                 p_stats;
+  osm_sa_resp_t*                               p_resp;
+  osm_mad_pool_t*                              p_mad_pool;
+  osm_log_t*                                   p_log;
+  cl_plock_t*                                  p_lock;
+  cl_qlock_pool_t                              pool;
+} osm_mftr_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_stats
+*              Pointer to the statistics.
+*
+*      p_resp
+*              Pointer to the SA responder.
+*
+*      p_mad_pool
+*              Pointer to the mad pool.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+*      pool
+*              Pool of linkable Multicast Forwarding Table Record objects used to
+*               generate the query response.
+*
+* SEE ALSO
+*      Multicast Forwarding Table Receiver object
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Receiver/osm_mftr_rcv_construct
+* NAME
+*      osm_mftr_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a Multicast Forwarding Table Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_mftr_rcv_construct(
+       IN osm_mftr_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Multicast Forwarding Table Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_mftr_rcv_init, osm_mftr_rcv_destroy
+*
+*      Calling osm_mftr_rcv_construct is a prerequisite to calling any other
+*      method except osm_mftr_rcv_init.
+*
+* SEE ALSO
+*      Multicast Forwarding Table Receiver object, osm_mftr_rcv_init, 
+*  osm_mftr_rcv_destroy
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Receiver/osm_mftr_rcv_destroy
+* NAME
+*      osm_mftr_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_mftr_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_mftr_rcv_destroy(
+       IN osm_mftr_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Multicast Forwarding Table Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_mftr_rcv_construct or osm_mftr_rcv_init.
+*
+* SEE ALSO
+*      Multicast Forwarding Table Receiver object, osm_mftr_rcv_construct,
+*      osm_mftr_rcv_init
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Receiver/osm_mftr_rcv_init
+* NAME
+*      osm_mftr_rcv_init
+*
+* DESCRIPTION
+*      The osm_mftr_rcv_init function initializes a
+*      Multicast Forwarding Table Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_mftr_rcv_init(
+       IN osm_mftr_rcv_t* const p_rcv,
+       IN osm_sa_resp_t* const p_resp,
+       IN osm_mad_pool_t* const p_mad_pool,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_mftr_rcv_t object to initialize.
+*
+*      p_req
+*              [in] Pointer to an osm_req_t object.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Multicast Forwarding Table Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Multicast Forwarding Table Receiver methods.
+*
+* SEE ALSO
+*      Multicast Forwarding Table Receiver object, osm_mftr_rcv_construct, 
+*  osm_mftr_rcv_destroy
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Receiver/osm_mftr_rcv_process
+* NAME
+*      osm_mftr_rcv_process
+*
+* DESCRIPTION
+*      Process the MulticastForwardingTable attribute.
+*
+* SYNOPSIS
+*/
+void osm_mftr_rcv_process(
+       IN osm_mftr_rcv_t* const p_ctrl,
+       IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_mftr_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the switch node's MulticastForwardingTable attribute.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the MulticastForwardingTable processing was successful.
+*
+* NOTES
+*      This function processes a MulticastForwardingTable attribute.
+*
+* SEE ALSO
+*      Multicast Forwarding Table Receiver, Multicast Forwarding Table Response
+*  Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MFTR_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mft_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_mft_record_ctrl.h
new file mode 100644 (file)
index 0000000..8f815ff
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_mftr_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA
+ *     MulticastForwardingTable attribute from a switch.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ */
+
+#ifndef _OSM_MFTR_RCV_CTRL_H_
+#define _OSM_MFTR_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_mft_record.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Multicast Forwarding Table Receive Controller
+* NAME
+*      Multicast Forwarding Table Record Receive Controller
+*
+* DESCRIPTION
+*      The Multicast Forwarding Table Receive Controller object encapsulates
+*      the information needed to receive the MulticastFowardingTable attribute
+*  from a switch node.
+*
+*      The Multicast Forwarding Table Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Hal Rosenstock, Voltaire
+*
+*********/
+
+/****s* OpenSM: Multicast Forwarding Table Receive Controller/osm_mftr_rcv_ctrl_t
+* NAME
+*      osm_mftr_rcv_ctrl_t
+*
+* DESCRIPTION
+*      Multicast Forwarding Table Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mftr_rcv_ctrl
+{
+       osm_mftr_rcv_t                  *p_rcv;
+       osm_log_t                       *p_log;
+       cl_dispatcher_t                 *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+} osm_mftr_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the Multicast Forwarding Table Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      Multicast Forwarding Table Receive Controller object
+*      Multicast Forwarding Table Receiver object
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Receive Controller/osm_mftr_rcv_ctrl_construct
+* NAME
+*      osm_mftr_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Multicast Forwarding Table Receive
+*  Controller object.
+*
+* SYNOPSIS
+*/
+void osm_mftr_rcv_ctrl_construct(
+       IN osm_mftr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Multicast Forwarding Table Receive Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_mftr_rcv_ctrl_init, osm_mftr_rcv_ctrl_destroy
+*
+*      Calling osm_mftr_rcv_ctrl_construct is a prerequisite to calling any other
+*      method except osm_mftr_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Multicast Forwarding Table Receive Controller object, osm_mftr_rcv_ctrl_init,
+*      osm_mftr_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Receive Controller/osm_mftr_rcv_ctrl_destroy
+* NAME
+*      osm_mftr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_mftr_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_mftr_rcv_ctrl_destroy(
+       IN osm_mftr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Multicast Forwarding Table Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_mftr_rcv_ctrl_construct or osm_mftr_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Multicast Forwarding Table Receive Controller object, osm_mftr_rcv_ctrl_construct,
+*      osm_mftr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Receive Controller/osm_mftr_rcv_ctrl_init
+* NAME
+*      osm_mftr_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_mftr_rcv_ctrl_init function initializes a
+*      Multicast Forwarding Table Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_mftr_rcv_ctrl_init(
+       IN osm_mftr_rcv_ctrl_t* const p_ctrl,
+       IN osm_mftr_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_mftr_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_mftr_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Multicast Forwarding Table Receive Controller object
+*  was initialized successfully.
+*
+* NOTES
+*      Allows calling other Multicast Forwarding Table Receive Controller methods.
+*
+* SEE ALSO
+*      Multicast Forwarding Table Receive Controller object, 
+*  osm_mftr_rcv_ctrl_construct, osm_mftr_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MFTR_RCV_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_multipath_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_multipath_record.h
new file mode 100644 (file)
index 0000000..b55cfb0
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_mpr_rcv_t.
+ *     This object represents the MultiPathRecord Receiver object.
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ */
+
+#ifndef _OSM_MPR_RCV_H_
+#define _OSM_MPR_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_qlockpool.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_state_mgr.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/MultiPath Record Receiver
+* NAME
+*      MultiPath Record Receiver
+*
+* DESCRIPTION
+*      The MultiPath Record Receiver object encapsulates the information
+*      needed to receive the PathRecord request from a node.
+*
+*      The MultiPath Record Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Hal Rosenstock, Voltaire
+*
+*********/
+
+/****s* OpenSM: MultiPath Record Receiver/osm_mpr_rcv_t
+* NAME
+*      osm_mpr_rcv_t
+*
+* DESCRIPTION
+*      MultiPath Record Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mpr_rcv
+{
+       osm_subn_t      *p_subn;
+       osm_sa_resp_t   *p_resp;
+       osm_mad_pool_t  *p_mad_pool;
+       osm_log_t       *p_log;
+       cl_plock_t      *p_lock;
+       cl_qlock_pool_t pr_pool;
+} osm_mpr_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_gen_req_ctrl
+*              Pointer to the generic request controller.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+*      pr_pool
+*              Pool of multipath record objects used to generate query responses.
+*
+* SEE ALSO
+*      MultiPath Record Receiver object
+*********/
+
+/****f* OpenSM: MultiPath Record Receiver/osm_mpr_rcv_construct
+* NAME
+*      osm_mpr_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a MultiPath Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_mpr_rcv_construct(
+       IN osm_mpr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to a MultiPath Record Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_mpr_rcv_init, osm_mpr_rcv_destroy
+*
+*      Calling osm_mpr_rcv_construct is a prerequisite to calling any other
+*      method except osm_mpr_rcv_init.
+*
+* SEE ALSO
+*      MultiPath Record Receiver object, osm_mpr_rcv_init, osm_mpr_rcv_destroy
+*********/
+
+/****f* OpenSM: MultiPath Record Receiver/osm_mpr_rcv_destroy
+* NAME
+*      osm_mpr_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_mpr_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mpr_rcv_destroy(
+       IN osm_mpr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      MultiPath Record Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_mpr_rcv_construct or osm_mpr_rcv_init.
+*
+* SEE ALSO
+*      MultiPath Record Receiver object, osm_mpr_rcv_construct,
+*      osm_mpr_rcv_init
+*********/
+
+/****f* OpenSM: MultiPath Record Receiver/osm_mpr_rcv_init
+* NAME
+*      osm_mpr_rcv_init
+*
+* DESCRIPTION
+*      The osm_mpr_rcv_init function initializes a
+*      MultiPath Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_mpr_rcv_init(
+       IN osm_mpr_rcv_t* const p_rcv,
+       IN osm_sa_resp_t* const p_resp,
+       IN osm_mad_pool_t* const p_mad_pool,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_mpr_rcv_t object to initialize.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the MultiPath Record Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other MultiPath Record Receiver methods.
+*
+* SEE ALSO
+*      MultiPath Record Receiver object, osm_mpr_rcv_construct,
+*      osm_mpr_rcv_destroy
+*********/
+
+/****f* OpenSM: MultiPath Record Receiver/osm_mpr_rcv_process
+* NAME
+*      osm_mpr_rcv_process
+*
+* DESCRIPTION
+*      Process the MultiPathRecord request.
+*
+* SYNOPSIS
+*/
+void
+osm_mpr_rcv_process(
+       IN osm_mpr_rcv_t*               const p_rcv,
+       IN osm_madw_t*          const p_madw );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_mpr_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the node's MultiPathRecord attribute.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the MultiPathRecord processing was successful.
+*
+* NOTES
+*      This function processes a MultiPathRecord attribute.
+*
+* SEE ALSO
+*      MultiPath Record Receiver, Node Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MPR_RCV_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_multipath_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_multipath_record_ctrl.h
new file mode 100644 (file)
index 0000000..090dc9e
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_mpr_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA
+ *     MultiPathRecord attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ */
+
+#ifndef _OSM_MPRCTRL_H_
+#define _OSM_MPRCTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_multipath_record.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/MultiPath Record Receive Controller
+* NAME
+*      MultiPath Record Receive Controller
+*
+* DESCRIPTION
+*      The MultiPath Record Receive Controller object encapsulates
+*      the information needed to receive the MultiPathRecord attribute from a node.
+*
+*      The MultiPath record Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Hal Rosenstock, Voltaire 
+*
+*********/
+
+/****s* OpenSM: MultiPath Record Receive Controller/osm_mpr_rcv_ctrl_t
+* NAME
+*      osm_mpr_rcv_ctrl_t
+*
+* DESCRIPTION
+*      MultiPath Record Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mpr_rcv_ctrl
+{
+       osm_mpr_rcv_t                           *p_rcv;
+       osm_log_t                                       *p_log;
+       cl_dispatcher_t                         *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_mpr_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the MultiPath Record Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      MultiPath Record Receive Controller object
+*      MultiPath Record Receiver object
+*********/
+
+/****f* OpenSM: MultiPath Record Receive Controller/osm_pr_rcv_ctrl_construct
+* NAME
+*      osm_mpr_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a MultiPath Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_mpr_rcv_ctrl_construct(
+       IN osm_mpr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a MultiPath Record Receive Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_mpr_rcv_ctrl_init, osm_mpr_rcv_ctrl_destroy,
+*      and osm_mpr_rcv_ctrl_is_inited.
+*
+*      Calling osm_mpr_rcv_ctrl_construct is a prerequisite to calling any
+*      other method except osm_mpr_rcv_ctrl_init.
+*
+* SEE ALSO
+*      MultiPath Record Receive Controller object, osm_mpr_rcv_ctrl_init,
+*      osm_mpr_rcv_ctrl_destroy, osm_mpr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: MultiPath Record Receive Controller/osm_mpr_rcv_ctrl_destroy
+* NAME
+*      osm_mpr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_mpr_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_mpr_rcv_ctrl_destroy(
+       IN osm_mpr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      MultiPath Record Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_mpr_rcv_ctrl_construct or osm_mpr_rcv_ctrl_init.
+*
+* SEE ALSO
+*      MultiPath Record Receive Controller object, osm_mpr_rcv_ctrl_construct,
+*      osm_mpr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: MultiPath Record Receive Controller/osm_mpr_rcv_ctrl_init
+* NAME
+*      osm_mpr_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_mpr_rcv_ctrl_init function initializes a
+*      MultiPath Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_mpr_rcv_ctrl_init(
+       IN osm_mpr_rcv_ctrl_t* const p_ctrl,
+       IN osm_mpr_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_mpr_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_mpr_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the MultiPath Record Receive Controller object was
+*      initialized successfully.
+*
+* NOTES
+*      Allows calling other MultiPath Record Receive Controller methods.
+*
+* SEE ALSO
+*      MultiPath Record Receive Controller object, osm_pr_rcv_ctrl_construct,
+*      osm_mpr_rcv_ctrl_destroy, osm_mpr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: MultiPath Record Receive Controller/osm_mpr_rcv_ctrl_is_inited
+* NAME
+*      osm_mpr_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+*      Indicates if the object has been initialized with osm_mpr_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_mpr_rcv_ctrl_is_inited(
+       IN const osm_mpr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_mpr_rcv_ctrl_t object.
+*
+* RETURN VALUES
+*      TRUE if the object was initialized successfully,
+*      FALSE otherwise.
+*
+* NOTES
+*      The osm_mpr_rcv_ctrl_construct or osm_mpr_rcv_ctrl_init must be
+*      called before using this function.
+*
+* SEE ALSO
+*      MultiPath Record Receive Controller object, osm_mpr_rcv_ctrl_construct,
+*      osm_mpr_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MPRCTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_node_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_node_record.h
new file mode 100644 (file)
index 0000000..a3a1f9a
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_node_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_nr_rcv_t.
+ *     This object represents the NodeRecord Receiver object.
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_NR_H_
+#define _OSM_NR_H_
+
+#include <complib/cl_qlockpool.h>
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Node Record Receiver
+* NAME
+*      Node Record Receiver
+*
+* DESCRIPTION
+*      The Node Record Receiver object encapsulates the information
+*      needed to receive the NodeRecord attribute from a node.
+*
+*      The Node record Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Anil S Keshavamurthy, Intel
+*
+*********/
+
+/****s* OpenSM: Node Record Receiver/osm_nr_rcv_t
+* NAME
+*      osm_nr_rcv_t
+*
+* DESCRIPTION
+*      Node Record Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_nr_recv
+{
+       const osm_subn_t                        *p_subn;
+       osm_sa_resp_t                           *p_resp;
+       osm_mad_pool_t                          *p_mad_pool;
+       osm_log_t                                       *p_log;
+       cl_plock_t                                      *p_lock;
+       cl_qlock_pool_t                         pool;
+
+} osm_nr_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_resp
+*              Pointer to the SA responder.
+*
+*      p_mad_pool
+*              Pointer to the mad pool.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+*      pool
+*              Pool of linkable node record objects used to generate
+*              the query response.
+*
+* SEE ALSO
+*      
+*********/
+
+/****f* OpenSM: Node Record Receiver/osm_nr_rcv_construct
+* NAME
+*      osm_nr_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a Node Record Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_nr_rcv_construct(
+       IN osm_nr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to a Node Record Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_nr_rcv_init, osm_nr_rcv_destroy
+*
+*      Calling osm_nr_rcv_construct is a prerequisite to calling any other
+*      method except osm_nr_rcv_init.
+*
+* SEE ALSO
+*      Node Record Receiver object, osm_nr_rcv_init, osm_lr_rcv_destroy
+*********/
+
+/****f* OpenSM: Node Record Receiver/osm_nr_rcv_destroy
+* NAME
+*      osm_nr_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_nr_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_nr_rcv_destroy(
+       IN osm_nr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Node Record Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_nr_rcv_construct or osm_nr_rcv_init.
+*
+* SEE ALSO
+*      Node Record Receiver object, osm_nr_rcv_construct,
+*      osm_nr_rcv_init
+*********/
+
+/****f* OpenSM: Node Record Receiver/osm_nr_rcv_init
+* NAME
+*      osm_nr_rcv_init
+*
+* DESCRIPTION
+*      The osm_nr_rcv_init function initializes a
+*      Node Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_nr_rcv_init(
+       IN osm_nr_rcv_t* const p_rcv,
+       IN osm_sa_resp_t* const p_resp,
+       IN osm_mad_pool_t* const p_mad_pool,
+       IN const osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_nr_rcv_t object to initialize.
+*
+*      p_resp
+*              [in] Pointer to the SA Responder object.
+*
+*      p_mad_pool
+*              [in] Pointer to the mad pool.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the Node Record Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Link Record Receiver methods.
+*
+* SEE ALSO
+*      Node Record Receiver object, osm_nr_rcv_construct, osm_nr_rcv_destroy
+*********/
+
+
+/****f* OpenSM: Node Record Receiver/osm_nr_rcv_process
+* NAME
+*      osm_nr_rcv_process
+*
+* DESCRIPTION
+*      Process the NodeRecord attribute.
+*
+* SYNOPSIS
+*/
+void osm_nr_rcv_process(
+       IN osm_nr_rcv_t* const p_rcv,
+       IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_nr_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the node's NodeRecord attribute.
+*
+* NOTES
+*      This function processes a NodeRecord attribute.
+*
+* SEE ALSO
+*      Node Record Receiver, Node Record Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_NR_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_node_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_node_record_ctrl.h
new file mode 100644 (file)
index 0000000..8dd5c58
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_node_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_nr_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA NodeInfo
+ *     record from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_NR_CTRL_H_
+#define _OSM_NR_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_node_record.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Node Record Receive Controller
+* NAME
+*      Node Record Receive Controller
+*
+* DESCRIPTION
+*      The Node Record Receive Controller object encapsulates
+*      the information needed to receive the NodeInfo attribute from a node.
+*
+*      The Node Record Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Anil S Keshavamurthy, Intel
+*
+*********/
+
+/****s* OpenSM: Node Record Receive Controller/osm_nr_rcv_ctrl_t
+* NAME
+*      osm_nr_rcv_ctrl_t
+*
+* DESCRIPTION
+*      Node Record Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_nr_ctrl
+{
+       osm_nr_rcv_t                            *p_rcv;
+       osm_log_t                                       *p_log;
+       cl_dispatcher_t                         *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_nr_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the Node Record Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      Node Record Receive Controller object
+*      Node Record Receiver object
+*********/
+
+/****f* OpenSM: Node Record Receive Controller/osm_nr_rcv_ctrl_construct
+* NAME
+*      osm_nr_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Node Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_nr_rcv_ctrl_construct(
+       IN osm_nr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Node Record Receive Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_nr_rcv_ctrl_init, osm_nr_rcv_ctrl_destroy,
+*
+*      Calling osm_nr_rcv_ctrl_construct is a prerequisite to calling any other
+*      method except osm_nr_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Node Record Receive Controller object, osm_nr_rcv_ctrl_init,
+*      osm_nr_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: Node Record Receive Controller/osm_nr_rcv_ctrl_destroy
+* NAME
+*      osm_nr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_nr_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_nr_rcv_ctrl_destroy(
+       IN osm_nr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Node Record Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_nr_rcv_ctrl_construct or osm_nr_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Node Record Receive Controller object, osm_nr_rcv_ctrl_construct,
+*      osm_nr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Node Record Receive Controller/osm_nr_rcv_ctrl_init
+* NAME
+*      osm_nr_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_nr_rcv_ctrl_init function initializes a
+*      Node Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_nr_rcv_ctrl_init(
+       IN osm_nr_rcv_ctrl_t* const p_ctrl,
+       IN osm_nr_rcv_t* const p_nr,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_nr_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_nr_rcv_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Node Record Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Node Record Receive Controller methods.
+*
+* SEE ALSO
+*      Node Record Receive Controller object, osm_nr_rcv_ctrl_construct,
+*      osm_nr_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_NR_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_path_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_path_record.h
new file mode 100644 (file)
index 0000000..c7acd3b
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_path_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_pr_rcv_t.
+ *     This object represents the PathRecord Receiver object.
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_PR_H_
+#define _OSM_PR_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_qlockpool.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Path Record Receiver
+* NAME
+*      Path Record Receiver
+*
+* DESCRIPTION
+*      The Path Record Receiver object encapsulates the information
+*      needed to receive the PathRecord request from a node.
+*
+*      The Path Record Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Ranjit Pandit, Intel
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Path Record Receiver/osm_pr_rcv_t
+* NAME
+*      osm_pr_rcv_t
+*
+* DESCRIPTION
+*      Path Record Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pr_rcv
+{
+       osm_subn_t                              *p_subn;
+       osm_sa_resp_t                           *p_resp;
+       osm_mad_pool_t                          *p_mad_pool;
+       osm_log_t                               *p_log;
+       cl_plock_t                              *p_lock;
+       cl_qlock_pool_t                         pr_pool;
+} osm_pr_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_gen_req_ctrl
+*              Pointer to the generic request controller.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+*      pr_pool
+*              Pool of path record objects used to generate query responses.
+*
+* SEE ALSO
+*      Path Record Receiver object
+*********/
+
+/****f* OpenSM: Path Record Receiver/osm_pr_rcv_construct
+* NAME
+*      osm_pr_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a Path Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_pr_rcv_construct(
+       IN osm_pr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to a Path Record Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_pr_rcv_init, osm_pr_rcv_destroy
+*
+*      Calling osm_pr_rcv_construct is a prerequisite to calling any other
+*      method except osm_pr_rcv_init.
+*
+* SEE ALSO
+*      Path Record Receiver object, osm_pr_rcv_init, osm_pr_rcv_destroy
+*********/
+
+/****f* OpenSM: Path Record Receiver/osm_pr_rcv_destroy
+* NAME
+*      osm_pr_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_pr_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_pr_rcv_destroy(
+       IN osm_pr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Path Record Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_pr_rcv_construct or osm_pr_rcv_init.
+*
+* SEE ALSO
+*      Path Record Receiver object, osm_pr_rcv_construct,
+*      osm_pr_rcv_init
+*********/
+
+/****f* OpenSM: Path Record Receiver/osm_pr_rcv_init
+* NAME
+*      osm_pr_rcv_init
+*
+* DESCRIPTION
+*      The osm_pr_rcv_init function initializes a
+*      Path Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_pr_rcv_init(
+       IN osm_pr_rcv_t* const p_rcv,
+       IN osm_sa_resp_t* const p_resp,
+       IN osm_mad_pool_t* const p_mad_pool,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_pr_rcv_t object to initialize.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the Path Record Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Path Record Receiver methods.
+*
+* SEE ALSO
+*      Path Record Receiver object, osm_pr_rcv_construct,
+*      osm_pr_rcv_destroy
+*********/
+
+/****f* OpenSM: Path Record Receiver/osm_pr_rcv_process
+* NAME
+*      osm_pr_rcv_process
+*
+* DESCRIPTION
+*      Process the PathRecord request.
+*
+* SYNOPSIS
+*/
+void
+osm_pr_rcv_process(
+       IN osm_pr_rcv_t*                        const p_rcv,
+       IN const osm_madw_t*            const p_madw );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_pr_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the node's PathRecord attribute.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the PathRecord processing was successful.
+*
+* NOTES
+*      This function processes a PathRecord attribute.
+*
+* SEE ALSO
+*      Path Record Receiver, Path Record Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PR_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_path_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_path_record_ctrl.h
new file mode 100644 (file)
index 0000000..245ab44
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_path_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_pr_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA PathRecord 
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_PRCTRL_H_
+#define _OSM_PRCTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_path_record.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Path Record Receive Controller
+* NAME
+*      Path Record Receive Controller
+*
+* DESCRIPTION
+*      The Path Record Receive Controller object encapsulates
+*      the information needed to receive the PathRecord attribute from a node.
+*
+*      The Path record Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Ranjit Pandit, Intel
+*
+*********/
+
+/****s* OpenSM: Path Record Receive Controller/osm_pr_rcv_ctrl_t
+* NAME
+*      osm_pr_rcv_ctrl_t
+*
+* DESCRIPTION
+*      Path Record Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pr_rcv_ctrl
+{
+       osm_pr_rcv_t                            *p_rcv;
+       osm_log_t                                       *p_log;
+       cl_dispatcher_t                         *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_pr_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the Path Record Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      Path Record Receive Controller object
+*      Path Record Receiver object
+*********/
+
+/****f* OpenSM: Path Record Receive Controller/osm_pr_rcv_ctrl_construct
+* NAME
+*      osm_pr_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Path Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_pr_rcv_ctrl_construct(
+       IN osm_pr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Path Record Receive Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_pr_rcv_ctrl_init, osm_pr_rcv_ctrl_destroy,
+*      and osm_pr_rcv_ctrl_is_inited.
+*
+*      Calling osm_pr_rcv_ctrl_construct is a prerequisite to calling any other
+*      method except osm_pr_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Path Record Receive Controller object, osm_pr_rcv_ctrl_init,
+*      osm_pr_rcv_ctrl_destroy, osm_pr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Path Record Receive Controller/osm_pr_rcv_ctrl_destroy
+* NAME
+*      osm_pr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_pr_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_pr_rcv_ctrl_destroy(
+       IN osm_pr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Path Record Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_pr_rcv_ctrl_construct or osm_pr_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Path Record Receive Controller object, osm_pr_rcv_ctrl_construct,
+*      osm_pr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Path Record Receive Controller/osm_pr_rcv_ctrl_init
+* NAME
+*      osm_pr_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_pr_rcv_ctrl_init function initializes a
+*      Path Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pr_rcv_ctrl_init(
+       IN osm_pr_rcv_ctrl_t* const p_ctrl,
+       IN osm_pr_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_pr_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_pr_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Path Record Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Path Record Receive Controller methods.
+*
+* SEE ALSO
+*      Path Record Receive Controller object, osm_pr_rcv_ctrl_construct,
+*      osm_pr_rcv_ctrl_destroy, osm_pr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Path Record Receive Controller/osm_pr_rcv_ctrl_is_inited
+* NAME
+*      osm_pr_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+*      Indicates if the object has been initialized with osm_pr_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_pr_rcv_ctrl_is_inited(
+       IN const osm_pr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_pr_rcv_ctrl_t object.
+*
+* RETURN VALUES
+*      TRUE if the object was initialized successfully,
+*      FALSE otherwise.
+*
+* NOTES
+*      The osm_pr_rcv_ctrl_construct or osm_pr_rcv_ctrl_init must be
+*      called before using this function.
+*
+* SEE ALSO
+*      Path Record Receive Controller object, osm_pr_rcv_ctrl_construct,
+*      osm_pr_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PRCTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_pkey_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_pkey_record.h
new file mode 100644 (file)
index 0000000..eb52037
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_pkey_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_PKEY_REC_RCV_H_
+#define _OSM_PKEY_REC_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/P_Key Record Receiver
+* NAME
+*  P_Key Record Receiver
+*
+* DESCRIPTION
+*  The P_Key Record Receiver object encapsulates the information
+*  needed to handle P_Key Record query from a SA.
+*
+*  The P_Key Record Receiver object is thread safe.
+*
+*  This object should be treated as opaque and should be
+*  manipulated only through the provided functions.
+*
+* AUTHOR
+*  Yael Kalka, Mellanox
+*
+*********/
+
+/****s* OpenSM: P_Key Record Receiver/osm_pkey_rec_rcv_t
+* NAME
+*  osm_pkey_rec_rcv_t
+*
+* DESCRIPTION
+*  P_Key Record Receiver structure.
+*
+*  This object should be treated as opaque and should
+*  be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pkey_rec_rcv
+{
+  const osm_subn_t         *p_subn;
+  osm_sa_resp_t            *p_resp;
+  osm_mad_pool_t           *p_mad_pool;
+  osm_log_t             *p_log;
+  cl_plock_t               *p_lock;
+  cl_qlock_pool_t        pool;
+
+} osm_pkey_rec_rcv_t;
+/*
+* FIELDS
+*  p_subn
+*     Pointer to the Subnet object for this subnet.
+*
+*  p_resp
+*     Pointer to the SA responder.
+*
+*  p_mad_pool
+*     Pointer to the mad pool.
+*
+*  p_log
+*     Pointer to the log object.
+*
+*  p_lock
+*     Pointer to the serializing lock.
+*
+*  pool
+*     Pool of linkable P_Key Record objects used to generate
+*     the query response.
+*
+* SEE ALSO
+*
+*********/
+
+/****f* OpenSM: P_Key Record Receiver/osm_vlarb_rec_rcv_construct
+* NAME
+*  osm_pkey_rec_rcv_construct
+*
+* DESCRIPTION
+*  This function constructs a P_Key Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_pkey_rec_rcv_construct(
+  IN osm_pkey_rec_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*  p_rcv
+*     [in] Pointer to a P_Key Record Receiver object to construct.
+*
+* RETURN VALUE
+*  This function does not return a value.
+*
+* NOTES
+*  Allows calling osm_pkey_rec_rcv_init, osm_pkey_rec_rcv_destroy
+*
+*  Calling osm_pkey_rec_rcv_construct is a prerequisite to calling any other
+*  method except osm_pkey_rec_rcv_init.
+*
+* SEE ALSO
+*  P_Key Record Receiver object, osm_pkey_rec_rcv_init,
+*  osm_pkey_rec_rcv_destroy
+*********/
+
+/****f* OpenSM: P_Key Record Receiver/osm_pkey_rec_rcv_destroy
+* NAME
+*  osm_pkey_rec_rcv_destroy
+*
+* DESCRIPTION
+*  The osm_pkey_rec_rcv_destroy function destroys the object, releasing
+*  all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_pkey_rec_rcv_destroy(
+  IN osm_pkey_rec_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*  p_rcv
+*     [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*  This function does not return a value.
+*
+* NOTES
+*  Performs any necessary cleanup of the specified
+*  P_Key Record Receiver object.
+*  Further operations should not be attempted on the destroyed object.
+*  This function should only be called after a call to
+*  osm_pkey_rec_rcv_construct or osm_pkey_rec_rcv_init.
+*
+* SEE ALSO
+*  P_Key Record Receiver object, osm_pkey_rec_rcv_construct,
+*  osm_pkey_rec_rcv_init
+*********/
+
+/****f* OpenSM: P_Key Record Receiver/osm_pkey_rec_rcv_init
+* NAME
+*  osm_pkey_rec_rcv_init
+*
+* DESCRIPTION
+*  The osm_pkey_rec_rcv_init function initializes a
+*  P_Key Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_pkey_rec_rcv_init(
+  IN osm_pkey_rec_rcv_t* const p_rcv,
+  IN osm_sa_resp_t* const p_resp,
+  IN osm_mad_pool_t* const p_mad_pool,
+  IN const osm_subn_t* const p_subn,
+  IN osm_log_t* const p_log,
+  IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*  p_rcv
+*     [in] Pointer to an osm_pkey_rec_rcv_t object to initialize.
+*
+*  p_req
+*     [in] Pointer to an osm_req_t object.
+*
+*  p_subn
+*     [in] Pointer to the Subnet object for this subnet.
+*
+*  p_log
+*     [in] Pointer to the log object.
+*
+*  p_lock
+*     [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*  CL_SUCCESS if the P_Key Record Receiver object was initialized
+*  successfully.
+*
+* NOTES
+*  Allows calling other P_Key Record Receiver methods.
+*
+* SEE ALSO
+*  P_Key Record Receiver object, osm_pkey_rec_rcv_construct,
+*  osm_pkey_rec_rcv_destroy
+*********/
+
+/****f* OpenSM: P_Key Record Receiver/osm_pkey_rec_rcv_process
+* NAME
+*  osm_pkey_rec_rcv_process
+*
+* DESCRIPTION
+*  Process the P_Key Table Query .
+*
+* SYNOPSIS
+*/
+void
+osm_pkey_rec_rcv_process(
+  IN osm_pkey_rec_rcv_t* const p_rcv,
+  IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*  p_rcv
+*     [in] Pointer to an osm_pkey_rec_rcv_t object.
+*
+*  p_madw
+*     [in] Pointer to the MAD Wrapper containing the MAD
+*     that contains the P_Key Record Query attribute.
+*
+* RETURN VALUES
+*  CL_SUCCESS if the Query processing was successful.
+*
+* NOTES
+*  This function processes a SA P_Key Record attribute.
+*
+* SEE ALSO
+*  P_Key Record Receiver, P_Key Record Response Controller
+*********/
+
+END_C_DECLS
+
+#endif   /* _OSM_PKEY_REC_RCV_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_pkey_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_pkey_record_ctrl.h
new file mode 100644 (file)
index 0000000..8c2d9a8
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_pkey_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_PKEY_REC_CTRL_H_
+#define _OSM_PKEY_REC_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_pkey_record.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/P_Key Record Receive Controller
+* NAME
+*  P_Key Record Receive Controller
+*
+* DESCRIPTION
+*  The P_Key Record Receive Controller object encapsulates
+*  the information needed to handle P_Key record query from SA client.
+*
+*  The P_Key Record Receive Controller object is thread safe.
+*
+*  This object should be treated as opaque and should be
+*  manipulated only through the provided functions.
+*
+* AUTHOR
+*  Yael Kalka, Mellanox
+*
+*********/
+
+/****s* OpenSM: P_Key Record Receive Controller/osm_pkey_rec_rcv_ctrl_t
+* NAME
+*  osm_pkey_rec_rcv_ctrl_t
+*
+* DESCRIPTION
+*  P_Key Record Receive Controller structure.
+*
+*  This object should be treated as opaque and should
+*  be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pkey_rec_rcv_ctrl
+{
+  osm_pkey_rec_rcv_t       *p_rcv;
+  osm_log_t             *p_log;
+  cl_dispatcher_t       *p_disp;
+  cl_disp_reg_handle_t     h_disp;
+
+} osm_pkey_rec_rcv_ctrl_t;
+/*
+* FIELDS
+*  p_rcv
+*     Pointer to the P_Key Record Receiver object.
+*
+*  p_log
+*     Pointer to the log object.
+*
+*  p_disp
+*     Pointer to the Dispatcher.
+*
+*  h_disp
+*     Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*  P_Key Record Receive Controller object
+*  P_Key Record Receiver object
+*********/
+
+/****f* OpenSM: P_Key Record Receive Controller/osm_pkey_rec_rcv_ctrl_construct
+* NAME
+*  osm_pkey_rec_rcv_ctrl_construct
+*
+* DESCRIPTION
+*  This function constructs a P_Key Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_pkey_rec_rcv_ctrl_construct(
+  IN osm_pkey_rec_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*  p_ctrl
+*     [in] Pointer to a P_Key Record Receive Controller
+*     object to construct.
+*
+* RETURN VALUE
+*  This function does not return a value.
+*
+* NOTES
+*  Allows calling osm_pkey_rec_rcv_ctrl_init, osm_pkey_rec_rcv_ctrl_destroy
+*
+*  Calling osm_pkey_rec_rcv_ctrl_construct is a prerequisite to calling any other
+*  method except osm_pkey_rec_rcv_ctrl_init.
+*
+* SEE ALSO
+*  P_Key Record Receive Controller object, osm_pkey_rec_rcv_ctrl_init,
+*  osm_pkey_rec_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: P_Key Record Receive Controller/osm_pkey_rec_rcv_ctrl_destroy
+* NAME
+*  osm_pkey_rec_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*  The osm_pkey_rec_rcv_ctrl_destroy function destroys the object, releasing
+*  all resources.
+*
+* SYNOPSIS
+*/
+void osm_pkey_rec_rcv_ctrl_destroy(
+  IN osm_pkey_rec_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*  p_ctrl
+*     [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*  This function does not return a value.
+*
+* NOTES
+*  Performs any necessary cleanup of the specified
+*  P_Key Record Receive Controller object.
+*  Further operations should not be attempted on the destroyed object.
+*  This function should only be called after a call to
+*  osm_pkey_rec_rcv_ctrl_construct or osm_pkey_rec_rcv_ctrl_init.
+*
+* SEE ALSO
+*  P_Key Record Receive Controller object, osm_pkey_rec_rcv_ctrl_construct,
+*  osm_pkey_rec_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: P_Key Record Receive Controller/osm_pkey_rec_rcv_ctrl_init
+* NAME
+*  osm_pkey_rec_rcv_ctrl_init
+*
+* DESCRIPTION
+*  The osm_pkey_rec_rcv_ctrl_init function initializes a
+*  P_Key Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pkey_rec_rcv_ctrl_init(
+  IN osm_pkey_rec_rcv_ctrl_t* const p_ctrl,
+  IN osm_pkey_rec_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*  p_ctrl
+*     [in] Pointer to an osm_pkey_rec_rcv_ctrl_t object to initialize.
+*
+*  p_rcv
+*     [in] Pointer to an osm_pkey_rec_rcv_t object.
+*
+*  p_log
+*     [in] Pointer to the log object.
+*
+*  p_disp
+*     [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*  CL_SUCCESS if the P_Key Record Receive Controller object was initialized
+*  successfully.
+*
+* NOTES
+*  Allows calling other P_Key Record Receive Controller methods.
+*
+* SEE ALSO
+*  P_Key Record Receive Controller object, osm_pkey_rec_rcv_ctrl_construct,
+*  osm_pkey_rec_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif   /* _OSM_PKEY_REC_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_portinfo_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_portinfo_record.h
new file mode 100644 (file)
index 0000000..acd42af
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_portinfo_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_pir_rcv_t.
+ *     This object represents the PortInfo Record Receiver object.
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_PIR_RCV_H_
+#define _OSM_PIR_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/PortInfo Record Receiver
+* NAME
+*      PortInfo Record Receiver
+*
+* DESCRIPTION
+*      The PortInfo Record Receiver object encapsulates the information
+*      needed to receive the PortInfoRecord attribute from a node.
+*
+*      The PortInfo Record Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Ranjit Pandit, Intel
+*
+*********/
+
+/****s* OpenSM: PortInfo Record Receiver/osm_pir_rcv_t
+* NAME
+*      osm_pir_rcv_t
+*
+* DESCRIPTION
+*      PortInfo Record Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pir_rcv
+{
+       osm_subn_t                              *p_subn;
+       osm_sa_resp_t                           *p_resp;
+       osm_mad_pool_t                          *p_mad_pool;
+       osm_log_t                               *p_log;
+       cl_plock_t                              *p_lock;
+       cl_qlock_pool_t                          pool;
+} osm_pir_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_resp
+*              Pointer to the SA responder.
+*
+*      p_mad_pool
+*              Pointer to the mad pool.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+*      pool
+*              Pool of linkable PortInfo Record objects used to generate
+*              the query response.
+*
+* SEE ALSO
+*      
+*********/
+
+/****f* OpenSM: PortInfo Record Receiver/osm_pir_rcv_construct
+* NAME
+*      osm_pir_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a PortInfo Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_pir_rcv_construct(
+       IN osm_pir_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to a PortInfo Record Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_pir_rcv_init, osm_pir_rcv_destroy
+*
+*      Calling osm_pir_rcv_construct is a prerequisite to calling any other
+*      method except osm_pir_rcv_init.
+*
+* SEE ALSO
+*      PortInfo Record Receiver object, osm_pir_rcv_init,
+*      osm_pir_rcv_destroy
+*********/
+
+/****f* OpenSM: PortInfo Record Receiver/osm_pir_rcv_destroy
+* NAME
+*      osm_pir_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_pir_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_pir_rcv_destroy(
+       IN osm_pir_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      PortInfo Record Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_pir_rcv_construct or osm_pir_rcv_init.
+*
+* SEE ALSO
+*      PortInfo Record Receiver object, osm_pir_rcv_construct,
+*      osm_pir_rcv_init
+*********/
+
+/****f* OpenSM: PortInfo Record Receiver/osm_pir_rcv_init
+* NAME
+*      osm_pir_rcv_init
+*
+* DESCRIPTION
+*      The osm_pir_rcv_init function initializes a
+*      PortInfo Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_pir_rcv_init(
+       IN osm_pir_rcv_t* const p_rcv,
+       IN osm_sa_resp_t* const p_resp,
+       IN osm_mad_pool_t* const p_mad_pool,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_pir_rcv_t object to initialize.
+*
+*      p_req
+*              [in] Pointer to an osm_req_t object.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the PortInfo Record Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other PortInfo Record Receiver methods.
+*
+* SEE ALSO
+*      PortInfo Record Receiver object, osm_pir_rcv_construct,
+*      osm_pir_rcv_destroy
+*********/
+
+/****f* OpenSM: PortInfo Record Receiver/osm_pir_rcv_process
+* NAME
+*      osm_pir_rcv_process
+*
+* DESCRIPTION
+*      Process the PortInfoRecord attribute.
+*
+* SYNOPSIS
+*/
+void
+osm_pir_rcv_process(
+       IN osm_pir_rcv_t* const p_rcv,
+       IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_pir_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the node's PortInfoRecord attribute.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the PortInfoRecord processing was successful.
+*
+* NOTES
+*      This function processes a PortInfoRecord attribute.
+*
+* SEE ALSO
+*      PortInfo Record Receiver, PortInfo Record Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PIR_RCV_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_portinfo_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_portinfo_record_ctrl.h
new file mode 100644 (file)
index 0000000..8e9bed3
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_portinfo_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_pir_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA PortInfo
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_PIR_CTRL_H_
+#define _OSM_PIR_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_portinfo_record.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/PortInfo Record Receive Controller
+* NAME
+*      PortInfo Record Receive Controller
+*
+* DESCRIPTION
+*      The PortInfo Record Receive Controller object encapsulates
+*      the information needed to receive the PortInfo attribute from a node.
+*
+*      The PortInfo Record Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Ranjit Pandit, Intel
+*
+*********/
+
+/****s* OpenSM: PortInfo Record Receive Controller/osm_pir_rcv_ctrl_t
+* NAME
+*      osm_pir_rcv_ctrl_t
+*
+* DESCRIPTION
+*      PortInfo Record Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pir_rcv_ctrl
+{
+       osm_pir_rcv_t                           *p_rcv;
+       osm_log_t                                       *p_log;
+       cl_dispatcher_t                         *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_pir_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the PortInfo Record Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      PortInfo Record Receive Controller object
+*      PortInfo Record Receiver object
+*********/
+
+/****f* OpenSM: PortInfo Record Receive Controller/osm_pir_rcv_ctrl_construct
+* NAME
+*      osm_pir_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a PortInfo Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_pir_rcv_ctrl_construct(
+       IN osm_pir_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a PortInfo Record Receive Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_pir_rcv_ctrl_init, osm_pir_rcv_ctrl_destroy
+*
+*      Calling osm_pir_rcv_ctrl_construct is a prerequisite to calling any other
+*      method except osm_pir_rcv_ctrl_init.
+*
+* SEE ALSO
+*      PortInfo Record Receive Controller object, osm_pir_rcv_ctrl_init,
+*      osm_pir_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: PortInfo Record Receive Controller/osm_pir_rcv_ctrl_destroy
+* NAME
+*      osm_pir_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_pir_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_pir_rcv_ctrl_destroy(
+       IN osm_pir_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      PortInfo Record Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_pir_rcv_ctrl_construct or osm_pir_rcv_ctrl_init.
+*
+* SEE ALSO
+*      PortInfo Record Receive Controller object, osm_pir_rcv_ctrl_construct,
+*      osm_pir_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: PortInfo Record Receive Controller/osm_pir_rcv_ctrl_init
+* NAME
+*      osm_pir_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_pir_rcv_ctrl_init function initializes a
+*      PortInfo Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pir_rcv_ctrl_init(
+       IN osm_pir_rcv_ctrl_t* const p_ctrl,
+       IN osm_pir_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_pir_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_pir_rcv_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the PortInfo Record Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other PortInfo Record Receive Controller methods.
+*
+* SEE ALSO
+*      PortInfo Record Receive Controller object, osm_pir_rcv_ctrl_construct,
+*      osm_pir_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PIR_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_response.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_response.h
new file mode 100644 (file)
index 0000000..8fa97af
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_response.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_sa_resp_t.
+ *     This object represents an object that responds to SA queries.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SA_RESP_H_
+#define _OSM_SA_RESP_H_
+
+#include <opensm/osm_base.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SA Response
+* NAME
+*      SA Response
+*
+* DESCRIPTION
+*      The SA Response object encapsulates the information
+*      needed to respond to an SA query.
+*
+*      The SA Response object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Ranjit Pandit, Intel
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: SA Response/osm_sa_resp_t
+* NAME
+*      osm_sa_resp_t
+*
+* DESCRIPTION
+*      SA Response structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sa_resp
+{
+       osm_mad_pool_t                          *p_pool;
+       osm_log_t                               *p_log;
+} osm_sa_resp_t;
+/*
+* FIELDS
+*      p_pool
+*              Pointer to the MAD pool.
+*
+* SEE ALSO
+*      SA Response object
+*********/
+
+/****f* OpenSM: SA Response/osm_sa_resp_construct
+* NAME
+*      osm_sa_resp_construct
+*
+* DESCRIPTION
+*      This function constructs a SA Response object.
+*
+* SYNOPSIS
+*/
+void
+osm_sa_resp_construct(
+       IN osm_sa_resp_t* const p_resp );
+/*
+* PARAMETERS
+*      p_resp
+*              [in] Pointer to a SA Response object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_sa_resp_init, and osm_sa_resp_destroy.
+*
+*      Calling osm_sa_resp_construct is a prerequisite to calling any other
+*      method except osm_sa_resp_init.
+*
+* SEE ALSO
+*      SA Response object, osm_sa_resp_init,
+*      osm_sa_resp_destroy
+*********/
+
+/****f* OpenSM: SA Response/osm_sa_resp_destroy
+* NAME
+*      osm_sa_resp_destroy
+*
+* DESCRIPTION
+*      The osm_sa_resp_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_sa_resp_destroy(
+       IN osm_sa_resp_t* const p_resp );
+/*
+* PARAMETERS
+*      p_resp
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      SA Response object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_sa_resp_construct or osm_sa_resp_init.
+*
+* SEE ALSO
+*      SA Response object, osm_sa_resp_construct,
+*      osm_sa_resp_init
+*********/
+
+/****f* OpenSM: SA Response/osm_sa_resp_init
+* NAME
+*      osm_sa_resp_init
+*
+* DESCRIPTION
+*      The osm_sa_resp_init function initializes a
+*      SA Response object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sa_resp_init(
+       IN osm_sa_resp_t*               const p_resp,
+       IN osm_mad_pool_t*              const p_pool,
+       IN osm_log_t*                   const p_log );
+/*
+* PARAMETERS
+*      p_resp
+*              [in] Pointer to an osm_sa_resp_t object to initialize.
+*
+*      p_mad_pool
+*              [in] Pointer to the MAD pool.
+*
+*      p_vl15
+*              [in] Pointer to the VL15 interface.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the SA Response object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other SA Response methods.
+*
+* SEE ALSO
+*      SA Response object, osm_sa_resp_construct,
+*      osm_sa_resp_destroy
+*********/
+
+/****f* IBA Base: Types/osm_sa_send_error
+* NAME
+*      osm_sa_send_error
+*
+* DESCRIPTION
+*      Sends a generic SA response with the specified error status.
+*      The payload is simply replicated from the request MAD.
+*
+* SYNOPSIS
+*/
+void
+osm_sa_send_error(
+    IN osm_sa_resp_t*          const p_resp,
+    IN const osm_madw_t*       const p_madw,
+    IN const ib_net16_t                sa_status );
+/*
+* PARAMETERS
+*      p_resp
+*              [in] Pointer to an osm_sa_resp_t object.
+*
+*      p_madw
+*              [in] Original MAD to which the response must be sent.
+*
+*      sa_status
+*              [in] Status to send in the response.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*      Allows calling other SA Response methods.
+*
+* SEE ALSO
+*      SA Response object, osm_sa_resp_construct,
+*      osm_sa_resp_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SA_RESP_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_service_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_service_record.h
new file mode 100644 (file)
index 0000000..549706b
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_service_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_sr_rcv_t.
+ *     This object represents the ServiceRecord Receiver object.
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SR_H_
+#define _OSM_SR_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_timer.h>
+#include <complib/cl_qlockpool.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Service Record Receiver
+* NAME
+*      Service Record Receiver
+*
+* DESCRIPTION
+*      The Service Record Receiver object encapsulates the information
+*      needed to receive the ServiceRecord request from a node.
+*
+*      The Service Record Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Anil S Keshavamurthy
+*
+*********/
+
+/****s* OpenSM: Service Record Receiver/osm_sr_rcv_t
+* NAME
+*      osm_sr_rcv_t
+*
+* DESCRIPTION
+*      Service Record Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sr_rcv
+{
+       osm_subn_t                                      *p_subn;
+       osm_sa_resp_t                           *p_resp;
+       osm_mad_pool_t                          *p_mad_pool;
+       osm_log_t                                       *p_log;
+       cl_plock_t                                      *p_lock;
+       cl_qlock_pool_t                         sr_pool;
+       cl_timer_t                                      sr_timer;
+
+} osm_sr_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_resp
+*              Pointer to the osm_sa_resp_t object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+*      sr_pool
+*              Pool of Service Record objects used to generate query responses.
+*
+* SEE ALSO
+*      Service Record Receiver object
+*********/
+
+/****f* OpenSM: Service Record Receiver/osm_sr_rcv_construct
+* NAME
+*      osm_sr_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a Service Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_sr_rcv_construct(
+       IN osm_sr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to a Service Record Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_sr_rcv_init, osm_sr_rcv_destroy
+*
+*      Calling osm_sr_rcv_construct is a prerequisite to calling any other
+*      method except osm_sr_rcv_init.
+*
+* SEE ALSO
+*      Service Record Receiver object, osm_sr_rcv_init, osm_sr_rcv_destroy
+*********/
+
+/****f* OpenSM: Service Record Receiver/osm_sr_rcv_destroy
+* NAME
+*      osm_sr_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_sr_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_sr_rcv_destroy(
+       IN osm_sr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Service Record Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_sr_rcv_construct or osm_sr_rcv_init.
+*
+* SEE ALSO
+*      Service Record Receiver object, osm_sr_rcv_construct,
+*      osm_sr_rcv_init
+*********/
+
+/****f* OpenSM: Service Record Receiver/osm_sr_rcv_init
+* NAME
+*      osm_sr_rcv_init
+*
+* DESCRIPTION
+*      The osm_sr_rcv_init function initializes a
+*      Service Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sr_rcv_init(
+       IN osm_sr_rcv_t* const p_rcv,
+       IN osm_sa_resp_t* const p_resp,
+       IN osm_mad_pool_t* const p_mad_pool,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_sr_rcv_t object to initialize.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the Service Record Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Service Record Receiver methods.
+*
+* SEE ALSO
+*      Service Record Receiver object, osm_sr_rcv_construct,
+*      osm_sr_rcv_destroy
+*********/
+
+/****f* OpenSM: Service Record Receiver/osm_sr_rcv_process
+* NAME
+*      osm_sr_rcv_process
+*
+* DESCRIPTION
+*      Process the ServiceRecord request.
+*
+* SYNOPSIS
+*/
+void
+osm_sr_rcv_process(
+       IN osm_sr_rcv_t*                        const p_rcv,
+       IN const osm_madw_t*            const p_madw );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_sr_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the node's ServiceRecord attribute.
+* NOTES
+*      This function processes a ServiceRecord attribute.
+*
+* SEE ALSO
+*      Service Record Receiver
+*********/
+
+/****f* OpenSM: Service Record Receiver/osm_sr_rcv_lease_cb
+* NAME
+*      osm_sr_rcv_lease_cb
+*
+* DESCRIPTION
+*      Timer Callback function which is executed to check the lease period
+*      expiration
+*
+* SYNOPSIS
+*/
+
+void
+osm_sr_rcv_lease_cb(
+       IN void*    context );
+/*
+* PARAMETERS
+*      context
+*              [in] Pointer to osm_sa_db_t object.
+*
+* NOTES
+*      This function processes a ServiceRecord attribute.
+*
+* SEE ALSO
+*      Service Record Receiver
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SR_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_service_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_service_record_ctrl.h
new file mode 100644 (file)
index 0000000..f542c36
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_service_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_sr_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA Service
+ *     record attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SRCTRL_H_
+#define _OSM_SRCTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_service_record.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Service Record Receive Controller
+* NAME
+*      Service Record Receive Controller
+*
+* DESCRIPTION
+*      The Service Record Receive Controller object encapsulates
+*      the information needed to receive the Service Record attribute from a node.
+*
+*      The Service Record Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Anil S Keshavamurthy, Intel
+*
+*********/
+
+/****s* OpenSM: Service Record Receive Controller/osm_sr_rcv_ctrl_t
+* NAME
+*      osm_sr_rcv_ctrl_t
+*
+* DESCRIPTION
+*      Service Record Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sr_rcv_ctrl
+{
+       osm_sr_rcv_t                            *p_rcv;
+       osm_log_t                                       *p_log;
+       cl_dispatcher_t                         *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_sr_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the Service Record Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      Service Record Receiver object
+*********/
+
+/****f* OpenSM: Service Record Receive Controller/osm_sr_rcv_ctrl_construct
+* NAME
+*      osm_sr_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Service Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_sr_rcv_ctrl_construct(
+       IN osm_sr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Service Record Receive Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_sr_rcv_ctrl_init, osm_sr_rcv_ctrl_destroy,
+*
+*      Calling osm_sr_rcv_ctrl_construct is a prerequisite to calling any other
+*      method except osm_psr_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Service Record Receive Controller object, osm_sr_rcv_ctrl_init,
+*      osm_sr_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: Service Record Receive Controller/osm_sr_rcv_ctrl_destroy
+* NAME
+*      osm_sr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_sr_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_sr_rcv_ctrl_destroy(
+       IN osm_sr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Service Record Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_sr_rcv_ctrl_construct or osm_sr_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Service Record Receive Controller object, osm_sr_rcv_ctrl_construct,
+*      osm_sr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Service Record Receive Controller/osm_sr_rcv_ctrl_init
+* NAME
+*      osm_sr_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_sr_rcv_ctrl_init function initializes a
+*      Service Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_sr_rcv_ctrl_init(
+       IN osm_sr_rcv_ctrl_t* const p_ctrl,
+       IN osm_sr_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_sr_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_sr_rcv_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the osm_sr_rcv_t Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Service Record Receive Controller methods.
+*
+* SEE ALSO
+*      Service Record Receive Controller object, osm_sr_rcv_ctrl_construct,
+*      osm_sr_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SRCTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_slvl_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_slvl_record.h
new file mode 100644 (file)
index 0000000..29dce36
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_slvl_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_slvl_rec_rcv_t.
+ *     This object represents the SLtoVL Mapping Table Receiver object.
+ *     attribute from a SA query.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#ifndef _OSM_SLVL_REC_RCV_H_
+#define _OSM_SLVL_REC_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SLtoVL Mapping Record Receiver
+* NAME
+*      SLtoVL Mapping Record Receiver
+*
+* DESCRIPTION
+*      The SLtoVL Mapping Record Receiver object encapsulates the information
+*      needed to handle SLtoVL Mapping Record query from a SA.
+*
+*      The SLtoVL Mapping Record Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: SLtoVL Mapping Record Receiver/osm_slvl_rec_rcv_t
+* NAME
+*      osm_slvl_rec_rcv_t
+*
+* DESCRIPTION
+*      SLtoVL Mapping Record Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_slvl_rec_rcv
+{
+       const osm_subn_t                        *p_subn;
+       osm_sa_resp_t                           *p_resp;
+       osm_mad_pool_t                          *p_mad_pool;
+       osm_log_t                                       *p_log;
+       cl_plock_t                                      *p_lock;
+       cl_qlock_pool_t                  pool;
+
+} osm_slvl_rec_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_resp
+*              Pointer to the SA responder.
+*
+*      p_mad_pool
+*              Pointer to the mad pool.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+*      pool
+*              Pool of linkable SLtoVL Mapping Record objects used to generate
+*              the query response.
+*
+* SEE ALSO
+*      
+*********/
+
+/****f* OpenSM: SLtoVL Mapping Record Receiver/osm_slvl_rec_rcv_construct
+* NAME
+*      osm_slvl_rec_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a SLtoVL Mapping Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_slvl_rec_rcv_construct(
+       IN osm_slvl_rec_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to a SLtoVL Mapping Record Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_slvl_rec_rcv_init, osm_slvl_rec_rcv_destroy
+*
+*      Calling osm_slvl_rec_rcv_construct is a prerequisite to calling any other
+*      method except osm_slvl_rec_rcv_init.
+*
+* SEE ALSO
+*      SLtoVL Mapping Record Receiver object, osm_slvl_rec_rcv_init,
+*      osm_slvl_rec_rcv_destroy
+*********/
+
+/****f* OpenSM: SLtoVL Mapping Record Receiver/osm_slvl_rec_rcv_destroy
+* NAME
+*      osm_slvl_rec_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_slvl_rec_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_slvl_rec_rcv_destroy(
+       IN osm_slvl_rec_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      SLtoVL Mapping Record Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_slvl_rec_rcv_construct or osm_slvl_rec_rcv_init.
+*
+* SEE ALSO
+*      SLtoVL Mapping Record Receiver object, osm_slvl_rec_rcv_construct,
+*      osm_slvl_rec_rcv_init
+*********/
+
+/****f* OpenSM: SLtoVL Mapping Record Receiver/osm_slvl_rec_rcv_init
+* NAME
+*      osm_slvl_rec_rcv_init
+*
+* DESCRIPTION
+*      The osm_slvl_rec_rcv_init function initializes a
+*      SLtoVL Mapping Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_slvl_rec_rcv_init(
+       IN osm_slvl_rec_rcv_t* const p_rcv,
+       IN osm_sa_resp_t* const p_resp,
+       IN osm_mad_pool_t* const p_mad_pool,
+       IN const osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_slvl_rec_rcv_t object to initialize.
+*
+*      p_req
+*              [in] Pointer to an osm_req_t object.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the SLtoVL Mapping Record Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other SLtoVL Mapping Record Receiver methods.
+*
+* SEE ALSO
+*      SLtoVL Mapping Record Receiver object, osm_slvl_rec_rcv_construct,
+*      osm_slvl_rec_rcv_destroy
+*********/
+
+/****f* OpenSM: SLtoVL Mapping Record Receiver/osm_slvl_rec_rcv_process
+* NAME
+*      osm_slvl_rec_rcv_process
+*
+* DESCRIPTION
+*      Process the SLtoVL Map Table Query .
+*
+* SYNOPSIS
+*/
+void
+osm_slvl_rec_rcv_process(
+       IN osm_slvl_rec_rcv_t* const p_rcv,
+       IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_slvl_rec_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the SLtoVL Map Record Query attribute.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Query processing was successful.
+*
+* NOTES
+*      This function processes a SA SLtoVL Map Record attribute.
+*
+* SEE ALSO
+*      SLtoVL Mapping Record Receiver, SLtoVL Mapping Record Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SLVL_REC_RCV_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_slvl_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_slvl_record_ctrl.h
new file mode 100644 (file)
index 0000000..8e8108c
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_slvl_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_sa_slvl_rec_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA VL Arbitration
+ *     record query from SA client.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#ifndef _OSM_SLVL_REC_CTRL_H_
+#define _OSM_SLVL_REC_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_slvl_record.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SLtoVL Record Receive Controller
+* NAME
+*      SLtoVL Record Receive Controller
+*
+* DESCRIPTION
+*      The SLtoVL Mapping Record Receive Controller object encapsulates
+*      the information needed to handle SLtoVL Mapping record query from SA client.
+*
+*      The SLtoVL Mapping Record Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: SLtoVL Mapping Record Receive Controller/osm_slvl_rec_rcv_ctrl_t
+* NAME
+*      osm_slvl_rec_rcv_ctrl_t
+*
+* DESCRIPTION
+*      SLtoVL Mapping Record Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_slvl_rec_rcv_ctrl
+{
+       osm_slvl_rec_rcv_t                         *p_rcv;
+       osm_log_t                                       *p_log;
+       cl_dispatcher_t                 *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_slvl_rec_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the SLtoVL Mapping Record Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      SLtoVL Mapping Record Receive Controller object
+*      SLtoVL Mapping Record Receiver object
+*********/
+
+/****f* OpenSM: SLtoVL Mapping Record Receive Controller/osm_slvl_rec_rcv_ctrl_construct
+* NAME
+*      osm_slvl_rec_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a SLtoVL Mapping Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_slvl_rec_rcv_ctrl_construct(
+       IN osm_slvl_rec_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a SLtoVL Mapping Record Receive Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_slvl_rec_rcv_ctrl_init, osm_slvl_rec_rcv_ctrl_destroy
+*
+*      Calling osm_slvl_rec_rcv_ctrl_construct is a prerequisite to calling any other
+*      method except osm_slvl_rec_rcv_ctrl_init.
+*
+* SEE ALSO
+*      SLtoVL Mapping Record Receive Controller object, osm_slvl_rec_rcv_ctrl_init,
+*      osm_slvl_rec_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: SLtoVL Mapping Record Receive Controller/osm_slvl_rec_rcv_ctrl_destroy
+* NAME
+*      osm_slvl_rec_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_slvl_rec_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_slvl_rec_rcv_ctrl_destroy(
+       IN osm_slvl_rec_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      SLtoVL Mapping Record Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_slvl_rec_rcv_ctrl_construct or osm_slvl_rec_rcv_ctrl_init.
+*
+* SEE ALSO
+*      SLtoVL Mapping Record Receive Controller object, osm_slvl_rec_rcv_ctrl_construct,
+*      osm_slvl_rec_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: SLtoVL Mapping Record Receive Controller/osm_slvl_rec_rcv_ctrl_init
+* NAME
+*      osm_slvl_rec_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_slvl_rec_rcv_ctrl_init function initializes a
+*      SLtoVL Mapping Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_slvl_rec_rcv_ctrl_init(
+       IN osm_slvl_rec_rcv_ctrl_t* const p_ctrl,
+       IN osm_slvl_rec_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_slvl_rec_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_slvl_rec_rcv_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the SLtoVL Mapping Record Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other SLtoVL Mapping Record Receive Controller methods.
+*
+* SEE ALSO
+*      SLtoVL Mapping Record Receive Controller object, osm_slvl_rec_rcv_ctrl_construct,
+*      osm_slvl_rec_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SLVL_REC_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sminfo_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sminfo_record.h
new file mode 100644 (file)
index 0000000..5b4c8ea
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_sminfo_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_smir_rcv_t.
+ *     This object represents the SMInfo Receiver object.
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SMIR_H_
+#define _OSM_SMIR_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SM Info Receiver
+* NAME
+*      SM Info Receiver
+*
+* DESCRIPTION
+*      The SM Info Receiver object encapsulates the information
+*      needed to receive the SMInfoRecord attribute from a node.
+*
+*      The SM Info Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Ranjit Pandit, Intel
+*
+*********/
+/****s* OpenSM: SM Info Receiver/osm_smir_rcv_t
+* NAME
+*      osm_smir_rcv_t
+*
+* DESCRIPTION
+*      SM Info Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_smir
+{
+       osm_subn_t*                             p_subn;
+       osm_stats_t*                            p_stats;
+       osm_sa_resp_t*                          p_resp;
+       osm_mad_pool_t*                         p_mad_pool;
+       osm_log_t*                              p_log;
+       cl_plock_t*                             p_lock;
+       cl_qlock_pool_t                         pool;
+} osm_smir_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+* SEE ALSO
+*      SM Info Receiver object
+*********/
+
+/****f* OpenSM: SM Info Receiver/osm_smir_rcv_construct
+* NAME
+*      osm_smir_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a SM Info Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_smir_rcv_construct(
+       IN osm_smir_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a SM Info Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_smir_rcv_init, osm_smir_rcv_destroy
+*
+*      Calling osm_smir_rcv_construct is a prerequisite to calling any other
+*      method except osm_smir_rcv_init.
+*
+* SEE ALSO
+*      SM Info Receiver object, osm_smir_rcv_init, osm_smir_rcv_destroy
+*********/
+
+/****f* OpenSM: SM Info Receiver/osm_smir_rcv_destroy
+* NAME
+*      osm_smir_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_smir_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_smir_rcv_destroy(
+       IN osm_smir_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      SM Info Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_smir_rcv_construct or osm_smir_rcv_init.
+*
+* SEE ALSO
+*      SM Info Receiver object, osm_smir_rcv_construct,
+*      osm_smir_rcv_init
+*********/
+
+/****f* OpenSM: SM Info Receiver/osm_smir_rcv_init
+* NAME
+*      osm_smir_rcv_init
+*
+* DESCRIPTION
+*      The osm_smir_rcv_init function initializes a
+*      SM Info Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_smir_rcv_init(
+       IN osm_smir_rcv_t* const p_ctrl,
+       IN osm_sa_resp_t* const p_resp,
+       IN osm_mad_pool_t* const p_mad_pool,
+       IN osm_subn_t* const p_subn,
+       IN osm_stats_t* const p_stats,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_smir_rcv_t object to initialize.
+*
+*      p_req
+*              [in] Pointer to an osm_req_t object.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_stats
+*              [in] Pointer to the Statistics object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the SM Info Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other SM Info Receiver methods.
+*
+* SEE ALSO
+*      SM Info Receiver object, osm_smir_rcv_construct, osm_smir_rcv_destroy
+*********/
+
+/****f* OpenSM: SM Info Receiver/osm_smir_rcv_process
+* NAME
+*      osm_smir_rcv_process
+*
+* DESCRIPTION
+*      Process the SMInfoRecord attribute.
+*
+* SYNOPSIS
+*/
+void osm_smir_rcv_process(
+       IN osm_smir_rcv_t* const p_ctrl,
+       IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_smir_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the node's SMInfoRecord attribute.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the SMInfoRecord processing was successful.
+*
+* NOTES
+*      This function processes a SMInfoRecord attribute.
+*
+* SEE ALSO
+*      SM Info Receiver, SM Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SMIR_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sminfo_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sminfo_record_ctrl.h
new file mode 100644 (file)
index 0000000..861c148
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_sminfo_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_smir_ctrl_t.
+ *     This object represents a controller that receives the IBA SMInfo
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SMIR_CTRL_H_
+#define _OSM_SMIR_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_sminfo_record.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SM Info Receive Controller
+* NAME
+*      SM Info Receive Controller
+*
+* DESCRIPTION
+*      The SM Info Receive Controller object encapsulates
+*      the information needed to receive the SMInfo attribute from a node.
+*
+*      The SM Info Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Ranjit Pandit, Intel
+*
+*********/
+
+/****s* OpenSM: SM Info Receive Controller/osm_smir_ctrl_t
+* NAME
+*      osm_smir_ctrl_t
+*
+* DESCRIPTION
+*      SM Info Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_smir_ctrl
+{
+       osm_smir_rcv_t                          *p_rcv;
+       osm_log_t                                       *p_log;
+       cl_dispatcher_t                         *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_smir_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the SM Info Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      SM Info Receive Controller object
+*      SM Info Receiver object
+*********/
+
+/****f* OpenSM: SM Info Receive Controller/osm_smir_ctrl_construct
+* NAME
+*      osm_smir_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a SM Info Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_smir_ctrl_construct(
+       IN osm_smir_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a SM Info Receive Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_smir_ctrl_init, osm_smir_ctrl_destroy
+*
+*      Calling osm_smir_ctrl_construct is a prerequisite to calling any other
+*      method except osm_smir_ctrl_init.
+*
+* SEE ALSO
+*      SM Info Receive Controller object, osm_smir_ctrl_init,
+*      osm_smir_ctrl_destroy
+*********/
+
+/****f* OpenSM: SM Info Receive Controller/osm_smir_ctrl_destroy
+* NAME
+*      osm_smir_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_smir_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_smir_ctrl_destroy(
+       IN osm_smir_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      SM Info Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_smir_ctrl_construct or osm_smir_ctrl_init.
+*
+* SEE ALSO
+*      SM Info Receive Controller object, osm_smir_ctrl_construct,
+*      osm_smir_ctrl_init
+*********/
+
+/****f* OpenSM: SM Info Receive Controller/osm_smir_ctrl_init
+* NAME
+*      osm_smir_ctrl_init
+*
+* DESCRIPTION
+*      The osm_smir_ctrl_init function initializes a
+*      SM Info Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_smir_ctrl_init(
+       IN osm_smir_ctrl_t* const p_ctrl,
+       IN osm_smir_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_smir_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_smir_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the SM Info Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other SM Info Receive Controller methods.
+*
+* SEE ALSO
+*      SM Info Receive Controller object, osm_smir_ctrl_construct,
+*      osm_smir_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SMIR_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sw_info_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sw_info_record.h
new file mode 100644 (file)
index 0000000..e8cf0bb
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_sir_rcv_t.
+ *     This object represents the SwitchInfo Receiver object.
+ *     attribute from a switch node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ */
+
+#ifndef _OSM_SIR_RCV_H_
+#define _OSM_SIR_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_state_mgr.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Switch Info Receiver
+* NAME
+*      Switch Info Receiver
+*
+* DESCRIPTION
+*      The Switch Info Receiver object encapsulates the information
+*      needed to receive the SwitchInfo attribute from a switch node.
+*
+*      The Switch Info Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Hal Rosenstock, Voltaire 
+*
+*********/
+
+/****s* OpenSM: Switch Info Receiver/osm_sir_rcv_t
+* NAME
+*      osm_sir_rcv_t
+*
+* DESCRIPTION
+*      Switch Info Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sir_rcv
+{
+       osm_subn_t                              *p_subn;
+       osm_sa_resp_t                           *p_resp;
+       osm_mad_pool_t                          *p_mad_pool;
+       osm_log_t                               *p_log;
+       osm_req_t                               *p_req;
+       osm_state_mgr_t                         *p_state_mgr;
+       cl_plock_t                              *p_lock;
+       cl_qlock_pool_t                         pool;
+} osm_sir_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_req
+*              Pointer to the Request object.
+*
+*      p_state_mgr
+*              Pointer to the State Manager object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+* SEE ALSO
+*      Switch Info Receiver object
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_sir_rcv_construct
+* NAME
+*      osm_sir_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a Switch Info Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_sir_rcv_construct(
+       IN osm_sir_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Switch Info Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_sir_rcv_init, osm_sir_rcv_destroy,
+*      and osm_sir_rcv_is_inited.
+*
+*      Calling osm_sir_rcv_construct is a prerequisite to calling any other
+*      method except osm_sir_rcv_init.
+*
+* SEE ALSO
+*      Switch Info Receiver object, osm_sir_rcv_init,
+*      osm_sir_rcv_destroy, osm_sir_rcv_is_inited
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_sir_rcv_destroy
+* NAME
+*      osm_sir_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_sir_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_sir_rcv_destroy(
+       IN osm_sir_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Switch Info Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_sir_rcv_construct or osm_sir_rcv_init.
+*
+* SEE ALSO
+*      Switch Info Receiver object, osm_sir_rcv_construct,
+*      osm_sir_rcv_init
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_sir_rcv_init
+* NAME
+*      osm_sir_rcv_init
+*
+* DESCRIPTION
+*      The osm_sir_rcv_init function initializes a
+*      Switch Info Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_sir_rcv_init(
+       IN osm_sir_rcv_t* const p_rcv,
+       IN osm_sa_resp_t* const p_resp,
+       IN osm_mad_pool_t* const p_mad_pool,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_sir_rcv_t object to initialize.
+*
+*      p_resp
+*              [in] Pointer to the SA Responder object.
+*
+*      p_mad_pool
+*              [in] Pointer to the mad pool.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the Switch Info Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Switch Info Receiver methods.
+*
+* SEE ALSO
+*      Switch Info Receiver object, osm_sir_rcv_construct,
+*      osm_sir_rcv_destroy, osm_sir_rcv_is_inited
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_sir_rcv_is_inited
+* NAME
+*      osm_sir_rcv_is_inited
+*
+* DESCRIPTION
+*      Indicates if the object has been initialized with osm_sir_rcv_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_sir_rcv_is_inited(
+       IN const osm_sir_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_sir_rcv_t object.
+*
+* RETURN VALUES
+*      TRUE if the object was initialized successfully,
+*      FALSE otherwise.
+*
+* NOTES
+*      The osm_sir_rcv_construct or osm_sir_rcv_init must be
+*      called before using this function.
+*
+* SEE ALSO
+*      Switch Info Receiver object, osm_sir_rcv_construct,
+*      osm_sir_rcv_init
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_sir_rcv_process
+* NAME
+*      osm_sir_rcv_process
+*
+* DESCRIPTION
+*      Process the SwitchInfo attribute.
+*
+* SYNOPSIS
+*/
+void osm_sir_rcv_process(
+       IN osm_sir_rcv_t* const p_ctrl,
+       IN const osm_madw_t*   const p_madw );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_sir_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the node's SwitchInfo attribute.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the SwitchInfo processing was successful.
+*
+* NOTES
+*      This function processes a SwitchInfo attribute.
+*
+* SEE ALSO
+*      Switch Info Receiver, Switch Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SIR_RCV_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sw_info_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_sw_info_record_ctrl.h
new file mode 100644 (file)
index 0000000..86b9674
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_sir_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA SwitchInfo
+ *     attribute from a switch node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ */
+
+#ifndef _OSM_SIR_RCV_CTRL_H_
+#define _OSM_SIR_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_sw_info_record.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Switch Info Receive Controller
+* NAME
+*      Switch Info Receive Controller
+*
+* DESCRIPTION
+*      The Switch Info Receive Controller object encapsulates the information
+*      needed to receive the SwitchInfo attribute from a switch node.
+*
+*      The Switch Info Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Hal Rosenstock, Voltaire
+*
+*********/
+
+/****s* OpenSM: Switch Info Receive Controller/osm_sir_rcv_ctrl_t
+* NAME
+*      osm_sir_rcv_ctrl_t
+*
+* DESCRIPTION
+*      Switch Info Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sir_rcv_ctrl
+{
+       osm_sir_rcv_t                   *p_rcv;
+       osm_log_t                       *p_log;
+       cl_dispatcher_t                 *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+} osm_sir_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the Switch Info Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      Switch Info Receive Controller object
+*      Switch Info Receiver object
+*********/
+
+/****f* OpenSM: Switch Info Receive Controller/osm_sir_rcv_ctrl_construct
+* NAME
+*      osm_sir_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Switch Info Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_sir_rcv_ctrl_construct(
+       IN osm_sir_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Switch Info Receive Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_sir_rcv_ctrl_init, osm_sir_rcv_ctrl_destroy,
+*      and osm_sir_rcv_ctrl_is_inited.
+*
+*      Calling osm_sir_rcv_ctrl_construct is a prerequisite to calling any
+*      other method except osm_sir_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Switch Info Receive Controller object, osm_sir_rcv_ctrl_init,
+*      osm_sir_rcv_ctrl_destroy, osm_sir_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Switch Info Receive Controller/osm_sir_rcv_ctrl_destroy
+* NAME
+*      osm_sir_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_sir_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_sir_rcv_ctrl_destroy(
+       IN osm_sir_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Switch Info Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_sir_rcv_ctrl_construct or osm_sir_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Switch Info Receive Controller object, osm_sir_rcv_ctrl_construct,
+*      osm_sir_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Switch Info Receive Controller/osm_sir_rcv_ctrl_init
+* NAME
+*      osm_sir_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_sir_rcv_ctrl_init function initializes a
+*      Switch Info Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_sir_rcv_ctrl_init(
+       IN osm_sir_rcv_ctrl_t* const p_ctrl,
+       IN osm_sir_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_sir_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_sir_rcv_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Switch Info Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Switch Info Receive Controller methods.
+*
+* SEE ALSO
+*      Switch Info Receive Controller object, osm_sir_rcv_ctrl_construct,
+*      osm_sir_rcv_ctrl_destroy, osm_sir_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Switch Info Receive Controller/osm_sir_rcv_ctrl_is_inited
+* NAME
+*      osm_sir_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+*      Indicates if the object has been initialized with osm_sir_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_sir_rcv_ctrl_is_inited(
+       IN const osm_sir_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_sir_rcv_ctrl_t object.
+*
+* RETURN VALUES
+*      TRUE if the object was initialized successfully,
+*      FALSE otherwise.
+*
+* NOTES
+*      The osm_sir_rcv_ctrl_construct or osm_sir_rcv_ctrl_init must be
+*      called before using this function.
+*
+* SEE ALSO
+*      Switch Info Receive Controller object, osm_sir_rcv_ctrl_construct,
+*      osm_sir_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SIR_RCV_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_vlarb_record.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_vlarb_record.h
new file mode 100644 (file)
index 0000000..b329500
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_vlarb_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_vlarb_rec_rcv_t.
+ *     This object represents the VLArbitration Record Receiver object.
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#ifndef _OSM_VLARB_REC_RCV_H_
+#define _OSM_VLARB_REC_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/VLArbitration Record Receiver
+* NAME
+*      VLArbitration Record Receiver
+*
+* DESCRIPTION
+*      The VLArbitration Record Receiver object encapsulates the information
+*      needed to handle VL Arbitration Record query from a SA.
+*
+*      The VLArbitration Record Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: VLArbitration Record Receiver/osm_vlarb_rec_rcv_t
+* NAME
+*      osm_vlarb_rec_rcv_t
+*
+* DESCRIPTION
+*      VLArbitration Record Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_vlarb_rec_rcv
+{
+       const osm_subn_t                        *p_subn;
+       osm_sa_resp_t                           *p_resp;
+       osm_mad_pool_t                          *p_mad_pool;
+       osm_log_t                               *p_log;
+       cl_plock_t                              *p_lock;
+       cl_qlock_pool_t                         pool;
+} osm_vlarb_rec_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_resp
+*              Pointer to the SA responder.
+*
+*      p_mad_pool
+*              Pointer to the mad pool.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+*      pool
+*              Pool of linkable VLArbitration Record objects used to generate
+*              the query response.
+*
+* SEE ALSO
+*      
+*********/
+
+/****f* OpenSM: VLArbitration Record Receiver/osm_vlarb_rec_rcv_construct
+* NAME
+*      osm_vlarb_rec_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a VLArbitration Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_vlarb_rec_rcv_construct(
+       IN osm_vlarb_rec_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to a VLArbitration Record Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_vlarb_rec_rcv_init, osm_vlarb_rec_rcv_destroy
+*
+*      Calling osm_vlarb_rec_rcv_construct is a prerequisite to calling any other
+*      method except osm_vlarb_rec_rcv_init.
+*
+* SEE ALSO
+*      VLArbitration Record Receiver object, osm_vlarb_rec_rcv_init,
+*      osm_vlarb_rec_rcv_destroy
+*********/
+
+/****f* OpenSM: VLArbitration Record Receiver/osm_vlarb_rec_rcv_destroy
+* NAME
+*      osm_vlarb_rec_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_vlarb_rec_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_vlarb_rec_rcv_destroy(
+       IN osm_vlarb_rec_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      VLArbitration Record Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_vlarb_rec_rcv_construct or osm_vlarb_rec_rcv_init.
+*
+* SEE ALSO
+*      VLArbitration Record Receiver object, osm_vlarb_rec_rcv_construct,
+*      osm_vlarb_rec_rcv_init
+*********/
+
+/****f* OpenSM: VLArbitration Record Receiver/osm_vlarb_rec_rcv_init
+* NAME
+*      osm_vlarb_rec_rcv_init
+*
+* DESCRIPTION
+*      The osm_vlarb_rec_rcv_init function initializes a
+*      VLArbitration Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_vlarb_rec_rcv_init(
+       IN osm_vlarb_rec_rcv_t* const p_rcv,
+       IN osm_sa_resp_t* const p_resp,
+       IN osm_mad_pool_t* const p_mad_pool,
+       IN const osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_vlarb_rec_rcv_t object to initialize.
+*
+*      p_req
+*              [in] Pointer to an osm_req_t object.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the VLArbitration Record Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other VLArbitration Record Receiver methods.
+*
+* SEE ALSO
+*      VLArbitration Record Receiver object, osm_vlarb_rec_rcv_construct,
+*      osm_vlarb_rec_rcv_destroy
+*********/
+
+/****f* OpenSM: VLArbitration Record Receiver/osm_vlarb_rec_rcv_process
+* NAME
+*      osm_vlarb_rec_rcv_process
+*
+* DESCRIPTION
+*      Process the VL Arbitration Table Query .
+*
+* SYNOPSIS
+*/
+void
+osm_vlarb_rec_rcv_process(
+       IN osm_vlarb_rec_rcv_t* const p_rcv,
+       IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_vlarb_rec_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the VL Arbitration Record Query attribute.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Query processing was successful.
+*
+* NOTES
+*      This function processes a SA VL Arbitration Record attribute.
+*
+* SEE ALSO
+*      VLArbitration Record Receiver, VLArbitration Record Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_VLARB_REC_RCV_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_vlarb_record_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sa_vlarb_record_ctrl.h
new file mode 100644 (file)
index 0000000..9f47683
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_vlarb_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_sa_vlarb_rec_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA VL Arbitration
+ *     record query from SA client.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#ifndef _OSM_VLARB_REC_CTRL_H_
+#define _OSM_VLARB_REC_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_vlarb_record.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/VLArbitration Record Receive Controller
+* NAME
+*      VLArbitration Record Receive Controller
+*
+* DESCRIPTION
+*      The VLArbitration Record Receive Controller object encapsulates
+*      the information needed to handle VLArbitration record query from SA client.
+*
+*      The VLArbitration Record Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: VLArbitration Record Receive Controller/osm_vlarb_rec_rcv_ctrl_t
+* NAME
+*      osm_vlarb_rec_rcv_ctrl_t
+*
+* DESCRIPTION
+*      VLArbitration Record Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_vlarb_rec_rcv_ctrl
+{
+       osm_vlarb_rec_rcv_t                     *p_rcv;
+       osm_log_t                                       *p_log;
+       cl_dispatcher_t                 *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_vlarb_rec_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the VLArbitration Record Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      VLArbitration Record Receive Controller object
+*      VLArbitration Record Receiver object
+*********/
+
+/****f* OpenSM: VLArbitration Record Receive Controller/osm_vlarb_rec_rcv_ctrl_construct
+* NAME
+*      osm_vlarb_rec_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a VLArbitration Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_vlarb_rec_rcv_ctrl_construct(
+       IN osm_vlarb_rec_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a VLArbitration Record Receive Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_vlarb_rec_rcv_ctrl_init, osm_vlarb_rec_rcv_ctrl_destroy
+*
+*      Calling osm_vlarb_rec_rcv_ctrl_construct is a prerequisite to calling any other
+*      method except osm_vlarb_rec_rcv_ctrl_init.
+*
+* SEE ALSO
+*      VLArbitration Record Receive Controller object, osm_vlarb_rec_rcv_ctrl_init,
+*      osm_vlarb_rec_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: VLArbitration Record Receive Controller/osm_vlarb_rec_rcv_ctrl_destroy
+* NAME
+*      osm_vlarb_rec_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_vlarb_rec_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_vlarb_rec_rcv_ctrl_destroy(
+       IN osm_vlarb_rec_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      VLArbitration Record Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_vlarb_rec_rcv_ctrl_construct or osm_vlarb_rec_rcv_ctrl_init.
+*
+* SEE ALSO
+*      VLArbitration Record Receive Controller object, osm_vlarb_rec_rcv_ctrl_construct,
+*      osm_vlarb_rec_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: VLArbitration Record Receive Controller/osm_vlarb_rec_rcv_ctrl_init
+* NAME
+*      osm_vlarb_rec_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_vlarb_rec_rcv_ctrl_init function initializes a
+*      VLArbitration Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_vlarb_rec_rcv_ctrl_init(
+       IN osm_vlarb_rec_rcv_ctrl_t* const p_ctrl,
+       IN osm_vlarb_rec_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_vlarb_rec_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_vlarb_rec_rcv_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the VLArbitration Record Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other VLArbitration Record Receive Controller methods.
+*
+* SEE ALSO
+*      VLArbitration Record Receive Controller object, osm_vlarb_rec_rcv_ctrl_construct,
+*      osm_vlarb_rec_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_VLARB_REC_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_service.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_service.h
new file mode 100644 (file)
index 0000000..f5f48a3
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_service.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_SVCR_H_
+#define _OSM_SVCR_H_
+
+/*
+ * Abstract:
+ *     Declaration of osm_service_rec_t.
+ *     This object represents an IBA Service Record.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_spinlock.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Service Record
+* NAME
+*      Service Record
+*
+* DESCRIPTION
+*      The service record encapsulates the information needed by the
+*      SA to manage service registrations.  
+*
+*      The service records is not thread safe, thus callers must provide
+*      serialization.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Anil S Keshavamurthy, Intel
+*
+*********/
+
+/****s* OpenSM: Service Record/osm_svcr_t
+* NAME
+*      osm_svcr_t
+*
+* DESCRIPTION
+*      Service Record structure.
+*
+*      The osm_svcr_t object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+
+typedef struct _osm_svcr_t
+{
+       cl_list_item_t          list_item;
+       ib_service_record_t     service_record;
+       uint32_t                modified_time;
+       uint32_t                lease_period;
+} osm_svcr_t;
+/*
+* FIELDS
+*      map_item
+*              Map Item for qmap linkage.  Must be first element!!
+*
+*      svc_rec
+*              IB Service record structure
+*
+*      modified_time
+*              Last modified time of this record in milliseconds
+*
+*      lease_period
+*              Remaining lease period for this record
+*              
+*
+* SEE ALSO
+*********/
+
+
+/****f* OpenSM: Service Record/osm_svcr_new
+* NAME
+*      osm_svcr_new
+*
+* DESCRIPTION
+*      Allocates and initializes a Service Record for use.
+*
+* SYNOPSIS
+*/
+osm_svcr_t*
+osm_svcr_new(
+       IN const ib_service_record_t *p_svc_rec );
+/*
+* PARAMETERS
+*      p_svc_rec
+*              [in] Pointer to IB Service Record
+*
+* RETURN VALUES
+*      pointer to osm_svcr_t structure.
+*
+* NOTES
+*      Allows calling other service record methods.
+*
+* SEE ALSO
+*      Service Record, osm_svcr_construct, osm_svcr_destroy
+*********/
+
+
+/****f* OpenSM: Service Record/osm_svcr_init
+* NAME
+*      osm_svcr_new
+*
+* DESCRIPTION
+*      Initializes the osm_svcr_t structure.
+*
+* SYNOPSIS
+*/
+void
+osm_svcr_init(
+       IN osm_svcr_t* const p_svcr,
+       IN const ib_service_record_t *p_svc_rec  );
+/*
+* PARAMETERS
+*      p_svc_rec
+*              [in] Pointer to osm_svcr_t structure
+*      p_svc_rec
+*              [in] Pointer to the ib_service_record_t
+*
+* SEE ALSO
+*      Service Record, osm_svcr_construct, osm_svcr_destroy
+*********/
+
+/****f* OpenSM: Service Record/osm_svcr_construct
+* NAME
+*      osm_svcr_construct
+*
+* DESCRIPTION
+*      Constructs the osm_svcr_t structure.
+*
+* SYNOPSIS
+*/
+void
+osm_svcr_construct(
+       IN osm_svcr_t* const p_svcr );
+/*
+* PARAMETERS
+*      p_svc_rec
+*              [in] Pointer to osm_svcr_t structure
+*
+* SEE ALSO
+*      Service Record, osm_svcr_construct, osm_svcr_destroy
+*********/
+
+/****f* OpenSM: Service Record/osm_svcr_destroy
+* NAME
+*      osm_svcr_destroy
+*
+* DESCRIPTION
+*      Constructs the osm_svcr_t structure.
+*
+* SYNOPSIS
+*/
+void
+osm_svcr_destroy(
+       IN osm_svcr_t* const p_svcr );
+/*
+* PARAMETERS
+*      p_svc_rec
+*              [in] Pointer to osm_svcr_t structure
+*
+* SEE ALSO
+*      Service Record, osm_svcr_construct, osm_svcr_destroy
+*********/
+
+
+
+osm_svcr_t*
+osm_svcr_get_by_rid(
+       IN osm_subn_t   const   *p_subn,
+       IN osm_log_t    *p_log,
+       IN ib_service_record_t* const p_svc_rec );
+
+void
+osm_svcr_insert_to_db(
+       IN osm_subn_t   *p_subn,
+       IN osm_log_t    *p_log,
+       IN osm_svcr_t   *p_svcr);
+void
+osm_svcr_remove_from_db(
+       IN osm_subn_t   *p_subn,
+       IN osm_log_t    *p_log,
+       IN osm_svcr_t   *p_svcr);
+
+
+END_C_DECLS
+
+#endif         /* _OSM_SVCR_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_slvl_map_rcv.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_slvl_map_rcv.h
new file mode 100644 (file)
index 0000000..f96bbe9
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_slvl_map_rcv.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_slvl_rcv_t.
+ *     This object represents the SLtoVL Map Receiver object.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#ifndef _OSM_SLVL_RCV_H_
+#define _OSM_SLVL_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Slvl Map Receiver
+* NAME
+*      Slvl Map Receiver
+*
+* DESCRIPTION
+*      The Slvl Map Receiver object encapsulates the information
+*      needed to set or get the SLtoVL map attribute from a port.
+*
+*      The Slvl Map Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: Slvl Map Receiver/osm_slvl_rcv_t
+* NAME
+*      osm_slvl_rcv_t
+*
+* DESCRIPTION
+*      Slvl Map Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_slvl_rcv
+{
+       osm_subn_t                                      *p_subn;
+       osm_req_t                                       *p_req;
+       osm_log_t                                       *p_log;
+       cl_plock_t                                      *p_lock;
+
+} osm_slvl_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_req
+*              Pointer to the generic attribute request object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+* SEE ALSO
+*      Slvl Map Receiver object
+*********/
+
+/****f* OpenSM: Slvl Map Receiver/osm_slvl_rcv_construct
+* NAME
+*      osm_slvl_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a Slvl Map Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_slvl_rcv_construct(
+       IN osm_slvl_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Slvl Map Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_slvl_rcv_destroy
+*
+*      Calling osm_slvl_rcv_construct is a prerequisite to calling any other
+*      method except osm_slvl_rcv_init.
+*
+* SEE ALSO
+*      Slvl Map Receiver object, osm_slvl_rcv_init,
+*      osm_slvl_rcv_destroy
+*********/
+
+/****f* OpenSM: Slvl Map Receiver/osm_slvl_rcv_destroy
+* NAME
+*      osm_slvl_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_slvl_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_slvl_rcv_destroy(
+       IN osm_slvl_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Slvl Map Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_slvl_rcv_construct or osm_slvl_rcv_init.
+*
+* SEE ALSO
+*      Slvl Map Receiver object, osm_slvl_rcv_construct,
+*      osm_slvl_rcv_init
+*********/
+
+/****f* OpenSM: Slvl Map Receiver/osm_slvl_rcv_init
+* NAME
+*      osm_slvl_rcv_init
+*
+* DESCRIPTION
+*      The osm_slvl_rcv_init function initializes a
+*      Slvl Map Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_slvl_rcv_init(
+       IN osm_slvl_rcv_t* const p_ctrl,
+       IN osm_req_t* const p_req,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_slvl_rcv_t object to initialize.
+*
+*      p_req
+*              [in] Pointer to an osm_req_t object.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Slvl Map Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Slvl Map Receiver methods.
+*
+* SEE ALSO
+*      Slvl Map Receiver object, osm_slvl_rcv_construct,
+*      osm_slvl_rcv_destroy
+*********/
+
+/****f* OpenSM: Slvl Map Receiver/osm_slvl_rcv_process
+* NAME
+*      osm_slvl_rcv_process
+*
+* DESCRIPTION
+*      Process the SLtoVL map attribute.
+*
+* SYNOPSIS
+*/
+void osm_slvl_rcv_process(
+       IN const osm_slvl_rcv_t* const p_ctrl,
+       IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_slvl_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the node's SLtoVL attribute.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the SLtoVL processing was successful.
+*
+* NOTES
+*      This function processes a SLtoVL attribute.
+*
+* SEE ALSO
+*      Slvl Map Receiver, Slvl Map Response Controller
+*********/
+       
+END_C_DECLS
+
+#endif /* _OSM_SLVL_RCV_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_slvl_map_rcv_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_slvl_map_rcv_ctrl.h
new file mode 100644 (file)
index 0000000..c62e44c
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_slvl_map_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_pi_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA NodeInfo
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#ifndef _OSM_SLVL_RCV_CTRL_H_
+#define _OSM_SLVL_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_slvl_map_rcv.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SltoVL Map Table Receive Controller
+* NAME
+*      Slvl Map Receive Controller
+*
+* DESCRIPTION
+*      The Slvl Map Receive Controller object encapsulates
+*      the information needed to get or set SLtoVL Map of a port.
+*
+*      The Slvl Map Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: Slvl Map Receive Controller/osm_slvl_rcv_ctrl_t
+* NAME
+*      osm_slvl_rcv_ctrl_t
+*
+* DESCRIPTION
+*      Slvl Map Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_slvl_rcv_ctrl
+{
+       osm_slvl_rcv_t                  *p_rcv;
+       osm_log_t                       *p_log;
+       cl_dispatcher_t                 *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_slvl_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the Slvl Map Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      Slvl Map Receive Controller object
+*      Slvl Map Receiver object
+*********/
+
+/****f* OpenSM: Slvl Map Receive Controller/osm_slvl_rcv_ctrl_construct
+* NAME
+*      osm_slvl_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Slvl Map Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_slvl_rcv_ctrl_construct(
+       IN osm_slvl_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Slvl Map Receive Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_slvl_rcv_ctrl_init, osm_slvl_rcv_ctrl_destroy,
+*      and osm_slvl_rcv_ctrl_is_inited.
+*
+*      Calling osm_slvl_rcv_ctrl_construct is a prerequisite to calling any other
+*      method except osm_slvl_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Slvl Map Receive Controller object, osm_slvl_rcv_ctrl_init,
+*      osm_slvl_rcv_ctrl_destroy, osm_slvl_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Slvl Map Receive Controller/osm_slvl_rcv_ctrl_destroy
+* NAME
+*      osm_slvl_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_slvl_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_slvl_rcv_ctrl_destroy(
+       IN osm_slvl_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Slvl Map Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_slvl_rcv_ctrl_construct or osm_slvl_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Slvl Map Receive Controller object, osm_slvl_rcv_ctrl_construct,
+*      osm_slvl_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Slvl Map Receive Controller/osm_slvl_rcv_ctrl_init
+* NAME
+*      osm_slvl_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_slvl_rcv_ctrl_init function initializes a
+*      Slvl Map Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_slvl_rcv_ctrl_init(
+       IN osm_slvl_rcv_ctrl_t* const p_ctrl,
+       IN osm_slvl_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_slvl_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_slvl_rcv_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Slvl Map Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Slvl Map Receive Controller methods.
+*
+* SEE ALSO
+*      Slvl Map Receive Controller object, osm_slvl_rcv_ctrl_construct,
+*      osm_slvl_rcv_ctrl_destroy, osm_slvl_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Slvl Map Receive Controller/osm_slvl_rcv_ctrl_is_inited
+* NAME
+*      osm_slvl_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+*      Indicates if the object has been initialized with osm_slvl_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_slvl_rcv_ctrl_is_inited(
+       IN const osm_slvl_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_slvl_rcv_ctrl_t object.
+*
+* RETURN VALUES
+*      TRUE if the object was initialized successfully,
+*      FALSE otherwise.
+*
+* NOTES
+*      The osm_slvl_rcv_ctrl_construct or osm_slvl_rcv_ctrl_init must be
+*      called before using this function.
+*
+* SEE ALSO
+*      Slvl Map Receive Controller object, osm_slvl_rcv_ctrl_construct,
+*      osm_slvl_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SLVL_RCV_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sm.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sm.h
new file mode 100644 (file)
index 0000000..6c260bd
--- /dev/null
@@ -0,0 +1,566 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sm.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_sm_t, osm_other_sm_t.
+ *     This object represents an IBA subnet.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#ifndef _OSM_SM_H_
+#define _OSM_SM_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_event.h>
+#include <complib/cl_thread.h>
+#include <opensm/osm_stats.h>
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_vl15intf.h>
+#include <vendor/osm_vendor.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_resp.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_req_ctrl.h>
+#include <opensm/osm_node_info_rcv_ctrl.h>
+#include <opensm/osm_port_info_rcv_ctrl.h>
+#include <opensm/osm_sw_info_rcv_ctrl.h>
+#include <opensm/osm_node_desc_rcv_ctrl.h>
+#include <opensm/osm_sm_mad_ctrl.h>
+#include <opensm/osm_state_mgr_ctrl.h>
+#include <opensm/osm_lid_mgr.h>
+#include <opensm/osm_ucast_mgr.h>
+#include <opensm/osm_link_mgr.h>
+#include <opensm/osm_drop_mgr.h>
+#include <opensm/osm_lin_fwd_rcv_ctrl.h>
+#include <opensm/osm_mcast_fwd_rcv_ctrl.h>
+#include <opensm/osm_sweep_fail_ctrl.h>
+#include <opensm/osm_sminfo_rcv_ctrl.h>
+#include <opensm/osm_trap_rcv_ctrl.h>
+#include <opensm/osm_sm_state_mgr.h>
+#include <opensm/osm_slvl_map_rcv_ctrl.h>
+#include <opensm/osm_vl_arb_rcv_ctrl.h>
+#include <opensm/osm_pkey_rcv_ctrl.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_mcast_mgr.h>
+#include <opensm/osm_db.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SM
+* NAME
+*      SM
+*
+* DESCRIPTION
+*      The SM object encapsulates the information needed by the
+*      OpenSM to instantiate a subnet manager.  The OpenSM allocates
+*      one SM object per subnet manager.
+*
+*      The SM object is thread safe.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: SM/osm_sm_t
+* NAME
+*  osm_sm_t
+*
+* DESCRIPTION
+*  Subnet Manager structure.
+*
+*  This object should be treated as opaque and should
+*  be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sm
+{
+  osm_thread_state_t       thread_state;
+  cl_event_t               signal;
+  cl_event_t               subnet_up_event;
+  cl_thread_t              sweeper;
+  osm_subn_t               *p_subn;
+  osm_db_t                 *p_db;
+  osm_vendor_t             *p_vendor;
+  osm_log_t                *p_log;
+  osm_mad_pool_t           *p_mad_pool;
+  osm_vl15_t               *p_vl15;
+  cl_dispatcher_t          *p_disp;
+  cl_plock_t               *p_lock;
+  atomic32_t               sm_trans_id;
+  osm_req_t                req;
+  osm_req_ctrl_t           req_ctrl;
+  osm_resp_t               resp;
+  osm_ni_rcv_t             ni_rcv;
+  osm_ni_rcv_ctrl_t        ni_rcv_ctrl;
+  osm_pi_rcv_t             pi_rcv;
+  osm_pi_rcv_ctrl_t        pi_rcv_ctrl;
+  osm_nd_rcv_t             nd_rcv;
+  osm_nd_rcv_ctrl_t        nd_rcv_ctrl;
+  osm_sm_mad_ctrl_t        mad_ctrl;
+  osm_si_rcv_t             si_rcv;
+  osm_si_rcv_ctrl_t        si_rcv_ctrl;
+  osm_state_mgr_ctrl_t     state_mgr_ctrl;
+  osm_lid_mgr_t            lid_mgr;
+  osm_ucast_mgr_t          ucast_mgr;
+  osm_link_mgr_t           link_mgr;
+  osm_state_mgr_t          state_mgr;
+  osm_drop_mgr_t           drop_mgr;
+  osm_lft_rcv_t            lft_rcv;
+  osm_lft_rcv_ctrl_t       lft_rcv_ctrl;
+  osm_mft_rcv_t            mft_rcv;
+  osm_mft_rcv_ctrl_t       mft_rcv_ctrl;
+  osm_sweep_fail_ctrl_t    sweep_fail_ctrl;
+  osm_sminfo_rcv_t         sm_info_rcv;
+  osm_sminfo_rcv_ctrl_t    sm_info_rcv_ctrl;
+  osm_trap_rcv_t           trap_rcv;
+  osm_trap_rcv_ctrl_t      trap_rcv_ctrl;
+  osm_sm_state_mgr_t       sm_state_mgr;
+  osm_mcast_mgr_t          mcast_mgr;
+  osm_slvl_rcv_t           slvl_rcv;
+  osm_slvl_rcv_ctrl_t      slvl_rcv_ctrl;
+  osm_vla_rcv_t            vla_rcv;
+  osm_vla_rcv_ctrl_t       vla_rcv_ctrl;
+  osm_pkey_rcv_t           pkey_rcv;
+  osm_pkey_rcv_ctrl_t      pkey_rcv_ctrl;
+} osm_sm_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*  p_db
+*     Pointer to the database (persistency) object
+*
+*      p_vendor
+*              Pointer to the vendor specific interfaces object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_mad_pool
+*              Pointer to the MAD pool.
+*
+*      p_vl15
+*              Pointer to the VL15 interface.
+*
+*      req
+*              Generic MAD attribute requester.
+*
+*      req_ctrl
+*              Controller for the generic requester.
+*
+*      resp
+*              MAD attribute responder.
+*
+*      nd_rcv_ctrl
+*              Node Description Receive Controller.
+*
+*      ni_rcv_ctrl
+*              Node Info Receive Controller.
+*
+*      pi_rcv_ctrl
+*              Port Info Receive Controller.
+*
+*      si_rcv_ctrl
+*              Switch Info Receive Controller.
+*
+*      nd_rcv_ctrl
+*              Node Description Receive Controller.
+*
+*      mad_ctrl
+*              MAD Controller.
+*
+*      smi_get_ctrl
+*              SM Info Get Controller.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+* SEE ALSO
+*      SM object
+*********/
+
+/****f* OpenSM: SM/osm_sm_construct
+* NAME
+*      osm_sm_construct
+*
+* DESCRIPTION
+*      This function constructs an SM object.
+*
+* SYNOPSIS
+*/
+void
+osm_sm_construct(
+       IN osm_sm_t* const p_sm );
+/*
+* PARAMETERS
+*      p_sm
+*              [in] Pointer to a SM object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_sm_init, osm_sm_destroy
+*
+*      Calling osm_sm_construct is a prerequisite to calling any other
+*      method except osm_sm_init.
+*
+* SEE ALSO
+*      SM object, osm_sm_init, osm_sm_destroy
+*********/
+
+/****f* OpenSM: SM/osm_sm_shutdown
+* NAME
+*      osm_sm_shutdown
+*
+* DESCRIPTION
+*      The osm_sm_shutdown function shutdowns an SM, stopping the sweeper
+*      and unregistering all messages from the dispatcher
+*
+* SYNOPSIS
+*/
+void
+osm_sm_shutdown(
+       IN osm_sm_t* const p_sm );
+/*
+* PARAMETERS
+*      p_sm
+*              [in] Pointer to a SM object to shutdown.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* SEE ALSO
+*      SM object, osm_sm_construct, osm_sm_init
+*********/
+
+/****f* OpenSM: SM/osm_sm_destroy
+* NAME
+*      osm_sm_destroy
+*
+* DESCRIPTION
+*      The osm_sm_destroy function destroys an SM, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_sm_destroy(
+       IN osm_sm_t* const p_sm );
+/*
+* PARAMETERS
+*      p_sm
+*              [in] Pointer to a SM object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified SM object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to osm_sm_construct or
+*      osm_sm_init.
+*
+* SEE ALSO
+*      SM object, osm_sm_construct, osm_sm_init
+*********/
+
+/****f* OpenSM: SM/osm_sm_init
+* NAME
+*      osm_sm_init
+*
+* DESCRIPTION
+*      The osm_sm_init function initializes a SM object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sm_init(
+       IN osm_sm_t* const p_sm,
+       IN osm_subn_t* const p_subn,
+   IN osm_db_t* const p_db,
+       IN osm_vendor_t* const p_vendor,
+       IN osm_mad_pool_t* const p_mad_pool,
+       IN osm_vl15_t* const p_vl15,
+       IN osm_log_t* const p_log,
+       IN osm_stats_t* const p_stats,
+       IN cl_dispatcher_t* const p_disp,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_sm
+*              [in] Pointer to an osm_sm_t object to initialize.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_vendor
+*              [in] Pointer to the vendor specific interfaces object.
+*
+*      p_mad_pool
+*              [in] Pointer to the MAD pool.
+*
+*      p_vl15
+*              [in] Pointer to the VL15 interface.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_stats
+*              [in] Pointer to the statistics object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the SM object was initialized successfully.
+*
+* NOTES
+*      Allows calling other SM methods.
+*
+* SEE ALSO
+*      SM object, osm_sm_construct, osm_sm_destroy
+*********/
+
+/****f* OpenSM: SM/osm_sm_sweep
+* NAME
+*      osm_sm_sweep
+*
+* DESCRIPTION
+*      Initiates a subnet sweep.
+*
+* SYNOPSIS
+*/
+void
+osm_sm_sweep(
+       IN osm_sm_t* const p_sm );
+/*
+* PARAMETERS
+*      p_sm
+*              [in] Pointer to an osm_sm_t object.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the sweep completed successfully.
+*
+* NOTES
+*
+* SEE ALSO
+*      SM object
+*********/
+
+/****f* OpenSM: SM/osm_sm_bind
+* NAME
+*      osm_sm_bind
+*
+* DESCRIPTION
+*      Binds the sm object to a port guid.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sm_bind(
+       IN osm_sm_t* const p_sm,
+       IN const ib_net64_t port_guid );
+/*
+* PARAMETERS
+*      p_sm
+*              [in] Pointer to an osm_sm_t object to bind.
+*
+*      port_guid
+*              [in] Local port GUID with which to bind.
+*
+*
+* RETURN VALUES
+*      None
+*
+* NOTES
+*      A given SM object can only be bound to one port at a time.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: SM/osm_sm_mcgrp_join
+* NAME
+*      osm_sm_mcgrp_join
+*
+* DESCRIPTION
+*      Adds a port to the multicast group.  Creates the multicast group
+*      if necessary.
+*
+*      This function is called by the SA.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sm_mcgrp_join(
+       IN osm_sm_t* const p_sm,
+       IN const ib_net16_t mlid,
+       IN const ib_net64_t port_guid,
+   IN osm_mcast_req_type_t req_type );
+/*
+* PARAMETERS
+*      p_sm
+*              [in] Pointer to an osm_sm_t object.
+*
+*      mlid
+*              [in] Multicast LID
+*
+*      port_guid
+*              [in] Port GUID to add to the group.
+*
+*  req_type
+*     [in] Type of the MC request that caused this join 
+*          (MC create/join).
+*
+* RETURN VALUES
+*      None
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: SM/osm_sm_mcgrp_leave
+* NAME
+*      osm_sm_mcgrp_leave
+*
+* DESCRIPTION
+*      Removes a port from the multicast group.
+*
+*      This function is called by the SA.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sm_mcgrp_leave(
+       IN osm_sm_t* const p_sm,
+       IN const ib_net16_t mlid,
+       IN const ib_net64_t port_guid );
+/*
+* PARAMETERS
+*      p_sm
+*              [in] Pointer to an osm_sm_t object.
+*
+*      mlid
+*              [in] Multicast LID
+*
+*      port_guid
+*              [in] Port GUID to remove from the group.
+*
+* RETURN VALUES
+*      None
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: OpenSM/osm_sm_wait_for_subnet_up
+* NAME
+*      osm_sm_wait_for_subnet_up
+*
+* DESCRIPTION
+*      Blocks the calling thread until the subnet is up.
+*
+* SYNOPSIS
+*/
+static inline cl_status_t
+osm_sm_wait_for_subnet_up(
+       IN osm_sm_t*                            const p_sm,
+       IN uint32_t                             const wait_us,
+       IN boolean_t                            const interruptible )
+{
+       return( cl_event_wait_on( &p_sm->subnet_up_event,
+                       wait_us, interruptible ) );
+}
+/*
+* PARAMETERS
+*      p_sm
+*              [in] Pointer to an osm_sm_t object.
+*
+*      wait_us 
+*              [in] Number of microseconds to wait.
+*
+*      interruptible
+*              [in] Indicates whether the wait operation can be interrupted
+*              by external signals.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the wait operation succeeded in response to the event 
+*      being set.
+*
+*      CL_TIMEOUT if the specified time period elapses.
+*
+*      CL_NOT_DONE if the wait was interrupted by an external signal.
+*
+*      CL_ERROR if the wait operation failed.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif         /* _OSM_SM_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sm_mad_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sm_mad_ctrl.h
new file mode 100644 (file)
index 0000000..b5d5fce
--- /dev/null
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sm_mad_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_sm_mad_ctrl_t.
+ *     This object represents a controller that receives the IBA NodeInfo
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SM_MAD_CTRL_H_
+#define _OSM_SM_MAD_CTRL_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_vl15intf.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SM MAD Controller
+* NAME
+*      SM MAD Controller
+*
+* DESCRIPTION
+*      The SM MAD Controller object encapsulates
+*      the information needed to receive MADs from the transport layer.
+*
+*      The SM MAD Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: SM MAD Controller/osm_sm_mad_ctrl_t
+* NAME
+*      osm_sm_mad_ctrl_t
+*
+* DESCRIPTION
+*      SM MAD Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sm_mad_ctrl
+{
+       osm_log_t                               *p_log;
+       osm_subn_t                              *p_subn;
+       osm_mad_pool_t                          *p_mad_pool;
+       osm_vl15_t                              *p_vl15;
+       osm_vendor_t                            *p_vendor;
+       osm_bind_handle_t                       h_bind;
+       cl_plock_t                              *p_lock;
+       cl_dispatcher_t                         *p_disp;
+       cl_disp_reg_handle_t                    h_disp;
+       osm_stats_t                             *p_stats;
+
+} osm_sm_mad_ctrl_t;
+/*
+* FIELDS
+*      p_log
+*              Pointer to the log object.
+*
+*      p_subn
+*              Pointer to the subnet object.
+*
+*      p_mad_pool
+*              Pointer to the MAD pool.
+*
+*      p_vendor
+*              Pointer to the vendor specific interfaces object.
+*
+*      h_bind
+*              Bind handle returned by the transport layer.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+*      p_stats
+*              Pointer to the OpenSM statistics block.
+*
+* SEE ALSO
+*      SM MAD Controller object
+*      SM MADr object
+*********/
+
+/****f* OpenSM: SM MAD Controller/osm_sm_mad_ctrl_construct
+* NAME
+*      osm_sm_mad_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a SM MAD Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_sm_mad_ctrl_construct(
+       IN osm_sm_mad_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a SM MAD Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_sm_mad_ctrl_init, and osm_sm_mad_ctrl_destroy.
+*
+*      Calling osm_sm_mad_ctrl_construct is a prerequisite to calling any other
+*      method except osm_sm_mad_ctrl_init.
+*
+* SEE ALSO
+*      SM MAD Controller object, osm_sm_mad_ctrl_init,
+*      osm_sm_mad_ctrl_destroy
+*********/
+
+/****f* OpenSM: SM MAD Controller/osm_sm_mad_ctrl_destroy
+* NAME
+*      osm_sm_mad_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_sm_mad_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_sm_mad_ctrl_destroy(
+       IN osm_sm_mad_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      SM MAD Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_sm_mad_ctrl_construct or osm_sm_mad_ctrl_init.
+*
+* SEE ALSO
+*      SM MAD Controller object, osm_sm_mad_ctrl_construct,
+*      osm_sm_mad_ctrl_init
+*********/
+
+/****f* OpenSM: SM MAD Controller/osm_sm_mad_ctrl_init
+* NAME
+*      osm_sm_mad_ctrl_init
+*
+* DESCRIPTION
+*      The osm_sm_mad_ctrl_init function initializes a
+*      SM MAD Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sm_mad_ctrl_init(
+       IN osm_sm_mad_ctrl_t* const p_ctrl,
+       IN osm_subn_t* const p_subn,
+       IN osm_mad_pool_t* const p_mad_pool,
+       IN osm_vl15_t* const p_vl15,
+       IN osm_vendor_t* const p_vendor,
+       IN osm_log_t* const p_log,
+       IN osm_stats_t* const p_stats,
+       IN cl_plock_t* const p_lock,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_sm_mad_ctrl_t object to initialize.
+*
+*      p_mad_pool
+*              [in] Pointer to the MAD pool.
+*
+*      p_vl15
+*              [in] Pointer to the VL15 interface object.
+*
+*      p_vendor
+*              [in] Pointer to the vendor specific interfaces object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_stats
+*              [in] Pointer to the OpenSM stastics block.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the SM MAD Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other SM MAD Controller methods.
+*
+* SEE ALSO
+*      SM MAD Controller object, osm_sm_mad_ctrl_construct,
+*      osm_sm_mad_ctrl_destroy
+*********/
+
+/****f* OpenSM: SM/osm_sm_mad_ctrl_bind
+* NAME
+*      osm_sm_mad_ctrl_bind
+*
+* DESCRIPTION
+*      Binds the SM MAD Controller object to a port guid.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sm_mad_ctrl_bind(
+       IN osm_sm_mad_ctrl_t* const p_ctrl,
+       IN const ib_net64_t port_guid );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_sm_mad_ctrl_t object to initialize.
+*
+*      port_guid
+*              [in] Local port GUID with which to bind.
+*
+*
+* RETURN VALUES
+*      None
+*
+* NOTES
+*      A given SM MAD Controller object can only be bound to one
+*      port at a time.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: SM/osm_sm_mad_ctrl_get_bind_handle
+* NAME
+*      osm_sm_mad_ctrl_get_bind_handle
+*
+* DESCRIPTION
+*      Returns the bind handle.
+*
+* SYNOPSIS
+*/
+static inline osm_bind_handle_t
+osm_sm_mad_ctrl_get_bind_handle(
+       IN const osm_sm_mad_ctrl_t* const p_ctrl )
+{
+       return( p_ctrl->h_bind );
+}
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_sm_mad_ctrl_t object.
+*
+* RETURN VALUES
+*      Returns the bind handle, which may be OSM_BIND_INVALID_HANDLE
+*      if no port has been bound.
+*
+* NOTES
+*      A given SM MAD Controller object can only be bound to one
+*      port at a time.
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SM_MAD_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sm_state_mgr.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sm_state_mgr.h
new file mode 100644 (file)
index 0000000..0b703f9
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sm_state_mgr.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_sm_state_mgr_t.
+ *     This object represents the SM State Manager object.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+#ifndef _OSM_SM_STATE_MGR_H_
+#define _OSM_SM_STATE_MGR_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_timer.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_lid_mgr.h>
+#include <opensm/osm_ucast_mgr.h>
+#include <opensm/osm_mcast_mgr.h>
+#include <opensm/osm_link_mgr.h>
+#include <opensm/osm_drop_mgr.h>
+#include <opensm/osm_sm_mad_ctrl.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_remote_sm.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SM State Manager
+* NAME
+*      SM State Manager
+*
+* DESCRIPTION
+*      The SM State Manager object encapsulates the information
+*      needed to control the state of the SM.
+*
+*      The SM State Manager object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Yael Kalka, Mellanox
+*
+*********/
+
+/****s* OpenSM: SM State Manager/osm_sm_state_mgr_t
+* NAME
+*      osm_sm_state_mgr_t
+*
+* DESCRIPTION
+*      SM State Manager structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sm_state_mgr
+{
+       cl_spinlock_t    state_lock;
+       cl_timer_t       polling_timer;
+       uint32_t         retry_number;
+       ib_net64_t       master_guid;
+       osm_state_mgr_t* p_state_mgr;
+       osm_subn_t*      p_subn;
+       osm_req_t*       p_req;
+       osm_log_t*       p_log;
+       osm_remote_sm_t* p_polling_sm;
+} osm_sm_state_mgr_t;
+
+/*
+* FIELDS
+*      state_lock
+*              Spinlock guarding the state and processes.
+*
+*      retry_number
+*              Used on Standby state - to count the number of retries
+*              of queries to the master SM.
+*
+*      polling_timer
+*              Timer for polling
+*
+*      p_state_mgr
+*              Point to the state manager object
+*
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_req
+*              Pointer to the generic attribute request object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_polling_sm
+*              Pointer to a osm_remote_sm_t object. When our SM needs
+*              to poll on a remote sm, this will be the pointer of the
+*              polled SM.
+*
+* SEE ALSO
+*      SM State Manager object
+*********/
+
+
+/****f* OpenSM: SM State Manager/osm_sm_state_mgr_construct
+* NAME
+*      osm_sm_state_mgr_construct
+*
+* DESCRIPTION
+*      This function constructs a SM State Manager object.
+*
+* SYNOPSIS
+*/
+void
+osm_sm_state_mgr_construct(
+       IN osm_sm_state_mgr_t* const p_sm_mgr );
+/*
+* PARAMETERS
+*      p_sm_mgr
+*              [in] Pointer to a SM State Manager object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows osm_sm_state_mgr_destroy
+*
+*      Calling osm_sm_state_mgr_construct is a prerequisite to calling any other
+*      method except osm_sm_state_mgr_init.
+*
+* SEE ALSO
+*      SM State Manager object, osm_sm_state_mgr_init,
+*      osm_sm_state_mgr_destroy
+*********/
+
+/****f* OpenSM: SM State Manager/osm_sm_state_mgr_destroy
+* NAME
+*      osm_sm_state_mgr_destroy
+*
+* DESCRIPTION
+*      The osm_sm_state_mgr_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_sm_state_mgr_destroy(
+       IN osm_sm_state_mgr_t* const p_sm_mgr );
+/*
+* PARAMETERS
+*      p_sm_mgr
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      SM State Manager object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_sm_state_mgr_construct or osm_sm_state_mgr_init.
+*
+* SEE ALSO
+*      SM State Manager object, osm_sm_state_mgr_construct,
+*      osm_sm_state_mgr_init
+*********/
+
+/****f* OpenSM: SM State Manager/osm_sm_state_mgr_init
+* NAME
+*      osm_sm_state_mgr_init
+*
+* DESCRIPTION
+*      The osm_sm_state_mgr_init function initializes a
+*      SM State Manager object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sm_state_mgr_init(
+       IN osm_sm_state_mgr_t*  const p_sm_mgr,
+       IN osm_state_mgr_t*     const p_state_mgr,
+       IN osm_subn_t*                          const p_subn,
+       IN osm_req_t*           const p_req,
+       IN osm_log_t*                           const p_log );
+/*
+* PARAMETERS
+*      p_sm_mgr
+*              [in] Pointer to an osm_sm_state_mgr_t object to initialize.
+*
+*
+*  p_state_mgr
+*     [in] Pointer to the State Manager object.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*  p_req
+*              [in] Pointer to an osm_req_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the SM State Manager object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other SM State Manager methods.
+*
+* SEE ALSO
+*      SM State Manager object, osm_sm_state_mgr_construct,
+*      osm_sm_state_mgr_destroy
+*********/
+
+/****f* OpenSM: SM State Manager/osm_sm_state_mgr_process
+* NAME
+*      osm_sm_state_mgr_process
+*
+* DESCRIPTION
+*      Processes and maintains the states of the SM.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sm_state_mgr_process(
+       IN osm_sm_state_mgr_t* const p_sm_mgr,
+       IN osm_sm_signal_t signal );
+/*
+* PARAMETERS
+*      p_sm_mgr
+*              [in] Pointer to an osm_sm_state_mgr_t object.
+*
+*      signal
+*              [in] Signal to the state SM engine.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      State Manager
+*********/
+       
+
+/****f* OpenSM: SM State Manager/osm_sm_state_mgr_signal_master_is_alive
+* NAME
+*      osm_sm_state_mgr_signal_master_is_alive
+*
+* DESCRIPTION
+*      Signals that the remote Master SM is alive.
+*      Need to clear the retry_number variable.
+*
+* SYNOPSIS
+*/
+void
+osm_sm_state_mgr_signal_master_is_alive(
+               IN osm_sm_state_mgr_t* const p_sm_mgr );
+/*
+* PARAMETERS
+*      p_sm_mgr
+*              [in] Pointer to an osm_sm_state_mgr_t object.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      State Manager
+*********/
+
+/****f* OpenSM: SM State Manager/osm_sm_state_mgr_check_legality
+* NAME
+*      osm_sm_state_mgr_check_legality
+*
+* DESCRIPTION
+*      Checks the legality of the signal received, according to the 
+*  current state of the SM state machine.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sm_state_mgr_check_legality(
+       IN osm_sm_state_mgr_t* const p_sm_mgr,
+       IN osm_sm_signal_t signal );
+/*
+* PARAMETERS
+*      p_sm_mgr
+*              [in] Pointer to an osm_sm_state_mgr_t object.
+*
+*      signal
+*              [in] Signal to the state SM engine.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      State Manager
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SM_STATE_MGR_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sminfo_rcv.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sminfo_rcv.h
new file mode 100644 (file)
index 0000000..c55a623
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sminfo_rcv.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_sminfo_rcv_t.
+ *     This object represents the SMInfo Receiver object.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SMINFO_RCV_H_
+#define _OSM_SMINFO_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_resp.h>
+#include <opensm/osm_remote_sm.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_state_mgr.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SMInfo Receiver
+* NAME
+*      SMInfo Receiver
+*
+* DESCRIPTION
+*      The SMInfo Receiver object encapsulates the information
+*      needed to receive the SMInfo attribute from a node.
+*
+*      The SMInfo Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: SMInfo Receiver/osm_sminfo_rcv_t
+* NAME
+*      osm_sminfo_rcv_t
+*
+* DESCRIPTION
+*      SMInfo Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sminfo_rcv
+{
+       osm_subn_t                                      *p_subn;
+       osm_stats_t                                     *p_stats;
+       osm_log_t                                       *p_log;
+       osm_resp_t                                      *p_resp;
+       osm_state_mgr_t                 *p_state_mgr;
+   struct _osm_sm_state_mgr      *p_sm_state_mgr;
+       cl_plock_t                                      *p_lock;
+
+} osm_sminfo_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_stats
+*              Pointer to the OpenSM statistics block.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_resp
+*              Pointer to the generic MAD responder object.
+*
+*      p_state_mgr
+*              Pointer to the State Manager object.
+*
+*      p_sm_state_mgr
+*              Pointer to the SM State Manager object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+* SEE ALSO
+*      SMInfo Receiver object
+*********/
+
+/****f* OpenSM: SMInfo Receiver/osm_sminfo_rcv_construct
+* NAME
+*      osm_sminfo_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a SMInfo Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_sminfo_rcv_construct(
+       IN osm_sminfo_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to a SMInfo Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_sminfo_rcv_init, osm_sminfo_rcv_destroy
+*
+*      Calling osm_sminfo_rcv_construct is a prerequisite to calling any other
+*      method except osm_sminfo_rcv_init.
+*
+* SEE ALSO
+*      SMInfo Receiver object, osm_sminfo_rcv_init,
+*      osm_sminfo_rcv_destroy
+*********/
+
+/****f* OpenSM: SMInfo Receiver/osm_sminfo_rcv_destroy
+* NAME
+*      osm_sminfo_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_sminfo_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_sminfo_rcv_destroy(
+       IN osm_sminfo_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      SMInfo Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_sminfo_rcv_construct or osm_sminfo_rcv_init.
+*
+* SEE ALSO
+*      SMInfo Receiver object, osm_sminfo_rcv_construct,
+*      osm_sminfo_rcv_init
+*********/
+
+/****f* OpenSM: SMInfo Receiver/osm_sminfo_rcv_init
+* NAME
+*      osm_sminfo_rcv_init
+*
+* DESCRIPTION
+*      The osm_sminfo_rcv_init function initializes a
+*      SMInfo Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_sminfo_rcv_init(
+       IN osm_sminfo_rcv_t* const p_rcv,
+       IN osm_subn_t* const p_subn,
+       IN osm_stats_t* const p_stats,
+       IN osm_resp_t* const p_resp,
+       IN osm_log_t* const p_log,
+       IN osm_state_mgr_t* const p_state_mgr,
+       IN struct _osm_sm_state_mgr* const p_sm_state_mgr,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_sminfo_rcv_t object to initialize.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_stats
+*              [in] Pointer to the OpenSM statistics block.
+*
+*      p_resp
+*              [in] Pointer to the generic MAD Responder object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_state_mgr
+*              [in] Pointer to the State Manager object.
+*
+*      p_sm_state_mgr
+*              [in] Pointer to the SM State Manager object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the SMInfo Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other SMInfo Receiver methods.
+*
+* SEE ALSO
+*      SMInfo Receiver object, osm_sminfo_rcv_construct,
+*      osm_sminfo_rcv_destroy
+*********/
+
+/****f* OpenSM: SMInfo Receiver/osm_sminfo_rcv_process
+* NAME
+*      osm_sminfo_rcv_process
+*
+* DESCRIPTION
+*      Process the SMInfo attribute.
+*
+* SYNOPSIS
+*/
+void osm_sminfo_rcv_process(
+       IN const osm_sminfo_rcv_t* const p_rcv,
+       IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_sminfo_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the node's SMInfo attribute.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the SMInfo processing was successful.
+*
+* NOTES
+*      This function processes a SMInfo attribute.
+*
+* SEE ALSO
+*      SMInfo Receiver, SMInfo Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SMINFO_RCV_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sminfo_rcv_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sminfo_rcv_ctrl.h
new file mode 100644 (file)
index 0000000..f34bb20
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sminfo_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_sminfo_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA SMInfo
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SMINFO_RCV_CTRL_H_
+#define _OSM_SMINFO_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sminfo_rcv.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/SMInfo Receive Controller
+* NAME
+*      SMInfo Receive Controller
+*
+* DESCRIPTION
+*      The SMInfo Receive Controller object encapsulates the information
+*      needed to receive the SMInfo attribute from a node.
+*
+*      The SMInfo Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: SMInfo Receive Controller/osm_sminfo_rcv_ctrl_t
+* NAME
+*      osm_sminfo_rcv_ctrl_t
+*
+* DESCRIPTION
+*      SMInfo Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sminfo_rcv_ctrl
+{
+       osm_sminfo_rcv_t                        *p_rcv;
+       osm_log_t                                       *p_log;
+       cl_dispatcher_t                         *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_sminfo_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the SMInfo Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      SMInfo Receive Controller object
+*********/
+
+/****f* OpenSM: SMInfo Receive Controller/osm_sminfo_rcv_ctrl_construct
+* NAME
+*      osm_sminfo_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a SMInfo Receive Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_sminfo_rcv_ctrl_construct(
+       IN osm_sminfo_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a SMInfo Receive Controller object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_sminfo_rcv_ctrl_init, osm_sminfo_rcv_ctrl_destroy
+*
+*      Calling osm_sminfo_rcv_ctrl_construct is a prerequisite to calling any other
+*      method except osm_sminfo_rcv_ctrl_init.
+*
+* SEE ALSO
+*      SMInfo Receive Controller object, osm_sminfo_rcv_ctrl_init,
+*      osm_sminfo_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: SMInfo Receive Controller/osm_sminfo_rcv_ctrl_destroy
+* NAME
+*      osm_sminfo_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_sminfo_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_sminfo_rcv_ctrl_destroy(
+       IN osm_sminfo_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      SMInfo Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_sminfo_rcv_ctrl_construct or osm_sminfo_rcv_ctrl_init.
+*
+* SEE ALSO
+*      SMInfo Receive Controller object, osm_sminfo_rcv_ctrl_construct,
+*      osm_sminfo_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: SMInfo Receive Controller/osm_sminfo_rcv_ctrl_init
+* NAME
+*      osm_sminfo_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_sminfo_rcv_ctrl_init function initializes a
+*      SMInfo Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sminfo_rcv_ctrl_init(
+       IN osm_sminfo_rcv_ctrl_t* const p_ctrl,
+       IN osm_sminfo_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_sminfo_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_sminfo_rcv_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the SMInfo Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other SMInfo Receive Controller methods.
+*
+* SEE ALSO
+*      SMInfo Receive Controller object, osm_sminfo_rcv_ctrl_construct,
+*      osm_sminfo_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif         /* OSM_SMINFO_RCV_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_state_mgr.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_state_mgr.h
new file mode 100644 (file)
index 0000000..e82d394
--- /dev/null
@@ -0,0 +1,518 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_state_mgr.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_state_mgr_t.
+ *     This object represents the State Manager object.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#ifndef _OSM_STATE_MGR_H_
+#define _OSM_STATE_MGR_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_lid_mgr.h>
+#include <opensm/osm_ucast_mgr.h>
+#include <opensm/osm_mcast_mgr.h>
+#include <opensm/osm_link_mgr.h>
+#include <opensm/osm_drop_mgr.h>
+#include <opensm/osm_sm_mad_ctrl.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/State Manager
+* NAME
+*      State Manager
+*
+* DESCRIPTION
+*      The State Manager object encapsulates the information
+*      needed to control subnet sweeps and configuration.
+*
+*      The State Manager object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: State Manager/osm_state_mgr_t
+* NAME
+*      osm_state_mgr_t
+*
+* DESCRIPTION
+*      State Manager structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_state_mgr
+{
+  osm_subn_t                                   *p_subn;
+  osm_log_t                                    *p_log;
+  osm_lid_mgr_t                                *p_lid_mgr;
+  osm_ucast_mgr_t                      *p_ucast_mgr;
+  osm_mcast_mgr_t                      *p_mcast_mgr;
+  osm_link_mgr_t                               *p_link_mgr;
+  osm_drop_mgr_t                               *p_drop_mgr;
+  osm_req_t                                    *p_req;
+  osm_stats_t                                  *p_stats;
+  struct _osm_sm_state_mgr  *p_sm_state_mgr;
+  const osm_sm_mad_ctrl_t      *p_mad_ctrl;
+  cl_spinlock_t                                state_lock;
+  cl_spinlock_t                                idle_lock;
+  cl_qlist_t                                   idle_time_list;
+  cl_plock_t                                   *p_lock;
+  cl_event_t                                   *p_subnet_up_event;
+  osm_sm_state_t                               state;
+  osm_state_mgr_mode_t     state_step_mode;
+  osm_signal_t             next_stage_signal;
+} osm_state_mgr_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lid_mgr
+*              Pointer to the LID Manager object.
+*
+*      p_ucast_mgr
+*              Pointer to the Unicast Manager object.
+*
+*      p_mcast_mgr
+*              Pointer to the Multicast Manager object.
+*
+*      p_link_mgr
+*              Pointer to the Link Manager object.
+*
+*      p_drop_mgr
+*              Pointer to the Drop Manager object.
+*
+*      p_req
+*              Pointer to the Requester object sending SMPs.
+*
+*  p_stats
+*     Pointer to the OpenSM statistics block.
+*
+*  p_sm_state_mgr
+*     Pointer to the SM state mgr object.
+*
+*      p_mad_ctrl
+*              Pointer to the SM's MAD Controller object.
+*
+*      state_lock
+*              Spinlock guarding the state and processes.
+*
+*      p_lock
+*              lock guarding the subnet object.
+*
+*      p_subnet_up_event
+*              Pointer to the event to set if/when the subnet comes up.
+*
+*      state
+*              State of the SM.
+*
+*  state_step_mode
+*     Controls the mode of progressing to next stage:
+*     OSM_STATE_STEP_CONTINUOUS - normal automatic progress mode
+*     OSM_STATE_STEP_TAKE_ONE - do one step and stop
+*     OSM_STATE_STEP_BREAK  - stop before taking next step
+*
+*  next_stage_signal
+*     Stores the signal to be provided when running the next stage.
+*
+* SEE ALSO
+*      State Manager object
+*********/
+
+/****s* OpenSM: State Manager/_osm_idle_item
+* NAME
+*      _osm_idle_item
+*
+* DESCRIPTION
+*      Idle item.  
+*
+* SYNOPSIS
+*/
+
+typedef osm_signal_t
+(*osm_pfn_start_t)(
+       IN                              void                                            *context1,
+       IN                              void                                            *context2 );
+
+typedef void
+(*osm_pfn_done_t)(
+       IN                              void                                            *context1,
+       IN                              void                                            *context2 );
+
+typedef struct _osm_idle_item
+{
+       cl_list_item_t  list_item;
+       void*                   context1;
+       void*                   context2;
+       osm_pfn_start_t pfn_start;
+       osm_pfn_done_t  pfn_done;       
+}osm_idle_item_t;
+
+/*
+* FIELDS
+*      list_item
+*              list item.
+*
+*      context1
+*              Context pointer
+*
+*      context2
+*              Context pointer
+*
+*      pfn_start
+*              Pointer to the start function.
+*
+*      pfn_done
+*              Pointer to the dine function.
+* SEE ALSO
+*      State Manager object
+*********/
+
+/****f* OpenSM: State Manager/osm_state_mgr_process_idle
+* NAME
+*      osm_state_mgr_process_idle
+*
+* DESCRIPTION
+*      Formulates the osm_idle_item and inserts it into the queue and 
+*      signals the state manager.
+*
+* SYNOPSIS
+*/
+
+ib_api_status_t
+osm_state_mgr_process_idle(
+       IN osm_state_mgr_t* const p_mgr,
+       IN osm_pfn_start_t      pfn_start,
+       IN osm_pfn_done_t       pfn_done,
+       void*                   context1,
+       void*                   context2
+       );
+
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to a State Manager object to construct.
+*
+*      pfn_start
+*              [in] Pointer the start function which will be called at
+*                      idle time.
+*
+*      pfn_done
+*              [in] pointer the done function which will be called
+*                      when outstanding smps is zero
+*
+*      context1
+*              [in] Pointer to void 
+*      
+*      context2
+*              [in] Pointer to void 
+*
+* RETURN VALUE
+*      IB_SUCCESS or IB_ERROR
+*
+* NOTES
+*      Allows osm_state_mgr_destroy
+*
+*      Calling osm_state_mgr_construct is a prerequisite to calling any other
+*      method except osm_state_mgr_init.
+*
+* SEE ALSO
+*      State Manager object, osm_state_mgr_init,
+*      osm_state_mgr_destroy
+*********/
+
+/****f* OpenSM: State Manager/osm_state_mgr_construct
+* NAME
+*      osm_state_mgr_construct
+*
+* DESCRIPTION
+*      This function constructs a State Manager object.
+*
+* SYNOPSIS
+*/
+void
+osm_state_mgr_construct(
+       IN osm_state_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to a State Manager object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows osm_state_mgr_destroy
+*
+*      Calling osm_state_mgr_construct is a prerequisite to calling any other
+*      method except osm_state_mgr_init.
+*
+* SEE ALSO
+*      State Manager object, osm_state_mgr_init,
+*      osm_state_mgr_destroy
+*********/
+
+/****f* OpenSM: State Manager/osm_state_mgr_destroy
+* NAME
+*      osm_state_mgr_destroy
+*
+* DESCRIPTION
+*      The osm_state_mgr_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_state_mgr_destroy(
+       IN osm_state_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      State Manager object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_state_mgr_construct or osm_state_mgr_init.
+*
+* SEE ALSO
+*      State Manager object, osm_state_mgr_construct,
+*      osm_state_mgr_init
+*********/
+
+/****f* OpenSM: State Manager/osm_state_mgr_init
+* NAME
+*      osm_state_mgr_init
+*
+* DESCRIPTION
+*      The osm_state_mgr_init function initializes a
+*      State Manager object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_state_mgr_init(
+       IN osm_state_mgr_t*                     const p_mgr,
+       IN osm_subn_t*                          const p_subn,
+       IN osm_lid_mgr_t*                       const p_lid_mgr,
+       IN osm_ucast_mgr_t*                     const p_ucast_mgr,
+       IN osm_mcast_mgr_t*                     const p_mcast_mgr,
+       IN osm_link_mgr_t*                      const p_link_mgr,
+       IN osm_drop_mgr_t*                      const p_drop_mgr,
+       IN osm_req_t*                           const p_req,
+   IN osm_stats_t*               const p_stats,
+   IN struct _osm_sm_state_mgr*  const p_sm_state_mgr,
+       IN const osm_sm_mad_ctrl_t* const p_mad_ctrl,
+       IN cl_plock_t*                          const p_lock,
+       IN cl_event_t*                          const p_subnet_up_event,
+       IN osm_log_t*                           const p_log );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to an osm_state_mgr_t object to initialize.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_lid_mgr
+*              [in] Pointer to the LID Manager object.
+*
+*      p_ucast_mgr
+*              [in] Pointer to the Unicast Manager object.
+*
+*      p_mcast_mgr
+*              [in] Pointer to the Multicast Manager object.
+*
+*      p_link_mgr
+*              [in] Pointer to the Link Manager object.
+*
+*      p_drop_mgr
+*              [in] Pointer to the Drop Manager object.
+*
+*      p_req
+*              [in] Pointer to the Request Controller object.
+*
+*  p_stats
+*     [in] Pointer to the OpenSM statistics block.
+*
+*  p_sm_state_mgr
+*     [in] Pointer to the SM state mgr object.
+*
+*      p_mad_ctrl
+*              [in] Pointer to the SM's mad controller.
+*
+*      p_subnet_up_event
+*              [in] Pointer to the event to set if/when the subnet comes up.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the State Manager object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other State Manager methods.
+*
+* SEE ALSO
+*      State Manager object, osm_state_mgr_construct,
+*      osm_state_mgr_destroy
+*********/
+
+/****f* OpenSM: State Manager/osm_sm_is_greater_than
+* NAME
+*      osm_sm_is_greater_than
+*
+* DESCRIPTION
+*  Compares two SM's (14.4.1.2)
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_sm_is_greater_than (
+  IN const uint8_t    l_priority,
+  IN const ib_net64_t l_guid,
+  IN const uint8_t    r_priority,
+  IN const ib_net64_t r_guid )
+{
+  if( l_priority > r_priority )
+  {
+    return( TRUE );
+  }
+  else
+  {
+    if( l_priority == r_priority )
+    {
+      if( cl_ntoh64(l_guid) <  cl_ntoh64(r_guid) )
+      {
+        return( TRUE );
+      }
+    }
+  }
+  return( FALSE );
+}
+/*
+* PARAMETERS
+*      l_priority
+*              [in] Priority of the SM on the "left"
+*
+*      l_guid
+*              [in] GUID of the SM on the "left"
+*
+*      r_priority
+*              [in] Priority of the SM on the "right"
+*
+*      r_guid
+*              [in] GUID of the SM on the "right"
+*
+* RETURN VALUES
+*  Return TRUE if an sm with l_priority and l_guid is higher than an sm
+*  with r_priority and r_guid,
+*  return FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*      State Manager
+*********/
+
+/****f* OpenSM: State Manager/osm_state_mgr_process
+* NAME
+*      osm_state_mgr_process
+*
+* DESCRIPTION
+*      Processes and maintains the states of the SM.
+*
+* SYNOPSIS
+*/
+void
+osm_state_mgr_process(
+       IN osm_state_mgr_t* const p_mgr,
+       IN osm_signal_t signal );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to an osm_state_mgr_t object.
+*
+*      signal
+*              [in] Signal to the state engine.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      State Manager
+*********/
+       
+END_C_DECLS
+
+#endif /* _OSM_STATE_MGR_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_state_mgr_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_state_mgr_ctrl.h
new file mode 100644 (file)
index 0000000..d89493f
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_state_mgr_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_state_mgr_ctrl_t.
+ *     This object represents a controller that receives the
+ *     State indication after a subnet sweep.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_STATE_MGR_CTRL_H_
+#define _OSM_STATE_MGR_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_state_mgr.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/State Manager Controller
+* NAME
+*      State Manager Controller
+*
+* DESCRIPTION
+*      The State Manager Controller object encapsulates the information
+*      needed to pass the dispatcher message from the dispatcher
+*      to the State Manager.
+*
+*      The State Manager Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: State Manager Controller/osm_state_mgr_ctrl_t
+* NAME
+*      osm_state_mgr_ctrl_t
+*
+* DESCRIPTION
+*      State Manager Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_state_mgr_ctrl
+{
+       osm_state_mgr_t                         *p_mgr;
+       osm_log_t                                       *p_log;
+       cl_dispatcher_t                         *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_state_mgr_ctrl_t;
+/*
+* FIELDS
+*      p_mgr
+*              Pointer to the State Manager object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      State Manager Controller object
+*********/
+
+/****f* OpenSM: State Manager Controller/osm_state_mgr_ctrl_construct
+* NAME
+*      osm_state_mgr_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a State Manager Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_state_mgr_ctrl_construct(
+       IN osm_state_mgr_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a State Manager Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_state_mgr_ctrl_init, and osm_state_mgr_ctrl_destroy.
+*
+*      Calling osm_state_mgr_ctrl_construct is a prerequisite to calling any
+*      other method except osm_state_mgr_ctrl_init.
+*
+* SEE ALSO
+*      State Manager Controller object, osm_state_mgr_ctrl_init,
+*      osm_state_mgr_ctrl_destroy
+*********/
+
+/****f* OpenSM: State Manager Controller/osm_state_mgr_ctrl_destroy
+* NAME
+*      osm_state_mgr_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_state_mgr_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_state_mgr_ctrl_destroy(
+       IN osm_state_mgr_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      State Manager Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_state_mgr_ctrl_construct or osm_state_mgr_ctrl_init.
+*
+* SEE ALSO
+*      State Manager Controller object, osm_state_mgr_ctrl_construct,
+*      osm_state_mgr_ctrl_init
+*********/
+
+/****f* OpenSM: State Manager Controller/osm_state_mgr_ctrl_init
+* NAME
+*      osm_state_mgr_ctrl_init
+*
+* DESCRIPTION
+*      The osm_state_mgr_ctrl_init function initializes a
+*      State Manager Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_state_mgr_ctrl_init(
+       IN osm_state_mgr_ctrl_t* const p_ctrl,
+       IN osm_state_mgr_t* const p_mgr,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_state_mgr_ctrl_t object to initialize.
+*
+*      p_mgr
+*              [in] Pointer to an osm_state_mgr_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the State Manager Controller object
+*      was initialized successfully.
+*
+* NOTES
+*      Allows calling other State Manager Controller methods.
+*
+* SEE ALSO
+*      State Manager Controller object, osm_state_mgr_ctrl_construct,
+*      osm_state_mgr_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif         /* OSM_STATE_MGR_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_stats.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_stats.h
new file mode 100644 (file)
index 0000000..b2a7003
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_stats.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_stats_t.
+ *     This object represents the OpenSM statistics object.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_STATS_H_
+#define _OSM_STATS_H_
+
+#include <opensm/osm_base.h>
+#include <complib/cl_atomic.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Statistics
+* NAME
+*      OpenSM
+*
+* DESCRIPTION
+*      The OpenSM object encapsulates the information needed by the
+*      OpenSM to track interesting traffic and internal statistics.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Statistics/osm_stats_t
+* NAME
+*      osm_stats_t
+*
+* DESCRIPTION
+*      OpenSM statistics block.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_stats
+{
+       atomic32_t                                      qp0_mads_outstanding;
+       atomic32_t                                      qp0_mads_outstanding_on_wire;
+       atomic32_t                                      qp0_mads_rcvd;
+       atomic32_t                                      qp0_mads_sent;
+       atomic32_t                                      qp0_unicasts_sent;
+       atomic32_t                                      qp1_mads_outstanding;
+       atomic32_t                                      qp1_mads_rcvd;
+       atomic32_t                                      qp1_mads_sent;
+
+} osm_stats_t;
+/*
+* FIELDS
+*      qp0_mads_outstanding
+*              Contains the number of MADs outstanding on QP0.
+*              When this value reaches zero, OpenSM has discovered all
+*              nodes on the subnet, and finished retrieving attributes.
+*              At that time, subnet configuration may begin.
+*              This variable must be manipulated using atomic instructions.
+*
+*      qp0_mads_outstanding_on_wire
+*              The number of MADs outstanding on the wire at any moment.
+*
+*      qp0_mads_rcvd
+*              Total number of QP0 MADs received.
+*
+*      qp0_mads_sent
+*              Total number of QP0 MADs sent.
+*
+*      qp0_unicasts_sent
+*              Total number of response-less MADs sent on the wire.  This count
+*              includes getresp(), send() and trap() methods.
+*
+* SEE ALSO
+***************/
+
+END_C_DECLS
+
+#endif /* _OSM_STATS_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_subnet.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_subnet.h
new file mode 100644 (file)
index 0000000..4732322
--- /dev/null
@@ -0,0 +1,1161 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_subnet.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_subn_t.
+ *     This object represents an IBA subnet.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.12 $
+ */
+
+#ifndef _OSM_SUBNET_H_
+#define _OSM_SUBNET_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_map.h>
+#include <complib/cl_ptr_vector.h>
+#include <complib/cl_list.h>
+#include <opensm/osm_base.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+#define OSM_SUBNET_VECTOR_MIN_SIZE                     0
+#define OSM_SUBNET_VECTOR_GROW_SIZE                    1
+#define OSM_SUBNET_VECTOR_CAPACITY                     256
+
+struct _osm_opensm_t;
+
+/****h* OpenSM/Subnet
+* NAME
+*      Subnet
+*
+* DESCRIPTION
+*      The Subnet object encapsulates the information needed by the
+*      OpenSM to manage a subnet.  The OpenSM allocates one Subnet object
+*      per IBA subnet.
+*
+*      The Subnet object is not thread safe, thus callers must provide
+*      serialization.
+*
+*      This object is essentially a container for the various components
+*      of a subnet.  Callers may directly access the member variables.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****f* OpenSM: Subnet/osm_pfn_ui_extension
+* NAME
+*      osm_pfn_ui_extension
+*
+* DESCRIPTION
+*      This typedef defines the prototype for UI extension functions
+*      The might be registered in the subnet options to handle pre_lid_assign,
+*  and ui_ucast_fwd_assign.
+*
+* SYNOPSIS
+*/
+typedef int
+(*osm_pfn_ui_extension_t)(
+       IN      void*                           context );
+/*
+* PARAMETERS
+*      context
+*              [in] Client specific context specified in the subnet opt
+*          Same prefix as the UI function (suffixed by ctx)
+*
+* RETURN VALUE
+*      This function returns an int (the semantic is different between 
+*  the different calls)
+*
+* SEE ALSO
+*
+*********/
+
+/****f* OpenSM: Subnet/osm_pfn_ui_mcast_extension
+* NAME
+*      osm_pfn_ui_mcast_extension
+*
+* DESCRIPTION
+*      This typedef defines the prototype for UI extension functions
+*      They might be registered in the subnet options to handle ui_mcast_fwd_assign
+*
+* SYNOPSIS
+*/
+typedef void
+(*osm_pfn_ui_mcast_extension_t)(
+  IN void                 *context,
+  IN ib_net16_t            mlid,
+  IN osm_mcast_req_type_t  request_type,
+  IN ib_net64_t            port_guid );
+/*
+* PARAMETERS
+*  context
+*     [in] Client specific context specified in the subnet opt
+*          Same prefix as the UI function (suffixed by ctx)
+*
+*  mlid
+*     [in] multicast lid of the group handled.
+*
+*  request_type
+*     [in] Type of MC request being handled (create/join/leave)
+*
+*  port_guid
+*     [in] port gui of the port that was added/removed from the
+*          multicast group handled.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* SEE ALSO
+*
+*********/
+
+/****d* OpenSM: Subnet/osm_testability_modes_t
+* NAME
+*      osm_testability_modes_t
+*
+* DESCRIPTION
+*      Enumerates the possible testability modes.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_testability_modes
+{
+  OSM_TEST_MODE_NONE = 0,
+  OSM_TEST_MODE_EXIT_BEFORE_SEND_HANDOVER,
+  OSM_TEST_MODE_MAX
+} osm_testability_modes_t;
+/***********/
+
+/****s* OpenSM: Subnet/osm_qos_options_t
+* NAME
+*      osm_qos_options_t
+*
+* DESCRIPTION
+*      Subnet QoS options structure.  This structure contains the various
+*      QoS specific configuration parameters for the subnet.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_qos_options_t {
+  unsigned max_vls;
+  unsigned high_limit;
+  char *vlarb_high;
+  char *vlarb_low;
+  char *sl2vl;
+} osm_qos_options_t;
+/*
+* FIELDS
+*
+*      max_vls
+*              The number of maximum VLs on the Subnet
+*
+*      high_limit
+*              The limit of High Priority component of VL Arbitration
+*              table (IBA 7.6.9)
+*
+*      vlarb_high
+*              High priority VL Arbitration table template.
+*
+*      vlarb_low
+*              Low priority VL Arbitration table template.
+*
+*      sl2vl
+*              SL2VL Mapping table (IBA 7.6.6) template.
+*
+*********/
+
+/****s* OpenSM: Subnet/osm_subn_opt_t
+* NAME
+*      osm_subn_opt_t
+*
+* DESCRIPTION
+*      Subnet options structure.  This structure contains the various
+*      site specific configuration parameters for the subnet.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_subn_opt
+{
+  ib_net64_t               guid;
+  ib_net64_t              m_key;
+  ib_net64_t               sm_key;
+  ib_net64_t              subnet_prefix;
+  ib_net16_t              m_key_lease_period;
+  uint32_t                sweep_interval;
+  uint32_t                max_wire_smps;
+  uint32_t                transaction_timeout;
+  uint8_t                 sm_priority;
+  uint8_t                 lmc;
+  boolean_t               lmc_esp0;
+  uint8_t                 max_op_vls;
+  uint8_t                 force_link_speed;    
+  boolean_t               reassign_lids;
+  boolean_t               reassign_lfts;
+  boolean_t               ignore_other_sm;
+  boolean_t               single_thread;
+  boolean_t               no_multicast_option;
+  boolean_t               disable_multicast;
+  boolean_t               force_log_flush;
+  uint8_t                  subnet_timeout;
+  uint8_t                  packet_life_time;
+  uint8_t                  vl_stall_count;
+  uint8_t                  leaf_vl_stall_count;
+  uint8_t                  head_of_queue_lifetime;
+  uint8_t                  leaf_head_of_queue_lifetime;
+  uint8_t                  local_phy_errors_threshold;
+  uint8_t                  overrun_errors_threshold;
+  uint32_t                 sminfo_polling_timeout;
+  uint32_t                 polling_retry_number;
+  uint32_t                max_msg_fifo_timeout;
+  boolean_t                force_heavy_sweep;
+  uint8_t                  log_flags;
+  char *                   dump_files_dir;
+  char *                   log_file;
+  unsigned long            log_max_size;
+  char *                   partition_config_file;
+  boolean_t                no_partition_enforcement;
+  boolean_t                no_qos;
+  boolean_t                accum_log_file;
+  boolean_t                console;
+  cl_map_t                 port_prof_ignore_guids;
+  boolean_t                port_profile_switch_nodes;
+  osm_pfn_ui_extension_t   pfn_ui_pre_lid_assign;
+  void *                   ui_pre_lid_assign_ctx;
+  osm_pfn_ui_mcast_extension_t pfn_ui_mcast_fdb_assign;
+  void *                   ui_mcast_fdb_assign_ctx;
+  boolean_t                sweep_on_trap;
+  osm_testability_modes_t  testability_mode;
+  char *                   routing_engine_name;
+  char *                   lid_matrix_dump_file;
+  char *                   ucast_dump_file;
+  char *                   updn_guid_file;
+  char *                   sa_db_file;
+  boolean_t                exit_on_fatal;
+  boolean_t                honor_guid2lid_file;
+  osm_qos_options_t        qos_options;
+  osm_qos_options_t        qos_ca_options;
+  osm_qos_options_t        qos_sw0_options;
+  osm_qos_options_t        qos_swe_options;
+  osm_qos_options_t        qos_rtr_options;
+  boolean_t                enable_quirks;
+  boolean_t                no_clients_rereg;
+} osm_subn_opt_t;
+/*
+* FIELDS
+*
+*      guid
+*              The port guid that the SM is binding to.
+*
+*      m_key
+*              M_Key value sent to all ports qualifing all Set(PortInfo).
+*
+*      sm_key
+*              SM_Key value of the SM to qualify rcv SA queries as "trusted".
+*
+*      subnet_prefix
+*              Subnet prefix used on this subnet.
+*
+*      m_key_lease_period
+*              The lease period used for the M_Key on this subnet.
+*
+*      sweep_interval
+*              The number of seconds between subnet sweeps.  A value of 0
+*              disables sweeping.
+*
+*      sm_priority
+*              The priority of this SM as specified by the user.  This
+*              value is made available in the SMInfo attribute.
+*
+*      lmc
+*              The LMC value used on this subnet.
+*
+*      lmc_esp0
+*              Whether LMC value used on subnet should be used for
+*              enhanced switch port 0 or not.  If TRUE, it is used.
+*              Otherwise (the default), LMC is set to 0 for ESP0.
+*
+*      max_op_vls
+*              Limit the maximal operational VLs. default is 1.
+*
+*      reassign_lids
+*              If TRUE cause all lids to be re-assigend.
+*              Otherwise (the default),
+*              OpenSM always tries to preserve as LIDs as much as possible.
+*
+*      reassign_lfts
+*              If TRUE ignore existing LFT entries on first sweep (default).
+*              Otherwise only non minimal hop cases are modified.
+*              NOTE: A standby SM clears its first sweep flag - since the
+*              master SM already sweeps...
+*
+*      ignore_other_sm_option
+*              This flag is TRUE if other SMs on the subnet should be ignored.
+*
+*      no_multicast_option
+*              This flag is TRUE if OpenSM should disable multicast support.
+*
+*      max_msg_fifo_timeout
+*              The maximal time a message can stay in the incoming message queue.
+*              If there is more than one message in the queue and the last
+*              message stayed in the queue more than this value the SA request
+*              will be immediately returned with a BUSY status. 
+*
+*      subnet_timeout
+*              The subnet_timeout that will be set for all the ports in the
+*              design SubnMgt.Set(PortInfo.vl_stall_life))
+*
+*      vl_stall_count
+*              The number of sequential packets dropped that cause the port
+*              to enter the VLStalled state.
+*
+*      leaf_vl_stall_count
+*              The number of sequential packets dropped that cause the port
+*              to enter the VLStalled state. This is for switch ports driving
+*              a CA or router port.
+*
+*      head_of_queue_lifetime
+*              The maximal time a packet can live at the head of a VL queue
+*              on any port not driving a CA or router port.
+*
+*      leaf_head_of_queue_lifetime
+*              The maximal time a packet can live at the head of a VL queue
+*              on switch ports driving a CA or router.
+*
+*      local_phy_errors_threshold
+*              Threshold of local phy errors for sending Trap 129
+*
+*      overrun_errors_threshold
+*              Threshold of credits overrun errors for sending Trap 129
+*
+*      sminfo_polling_timeout
+*              Specifies the polling timeout (in milliseconds) - the timeout
+*              between one poll to another.
+*
+*      packet_life_time
+*              The maximal time a packet can stay in a switch.
+*              The value is send to all switches as SubnMgt.Set(SwitchInfo.life_state)
+*
+*      dump_files_dir
+*              The directory to be used for subnet.lst osm.fdbs, osm.mcfdbs
+*              and default log file (the latter for Windows, not Linux).
+*
+*      log_file
+*              Name of the log file (or NULL) for stdout.
+*
+*      log_max_size
+*              This option defines maximal log file size in MB. When
+*              specified the log file will be truncated upon reaching
+*              this limit.
+*
+*      accum_log_file
+*              If TRUE (default) - the log file will be accumulated.
+*              If FALSE - the log file will be erased before starting current opensm run.
+*
+*      port_prof_ignore_guids
+*              A map of guids to be ignored by port profiling.
+*
+*      port_profile_switch_nodes
+*              If TRUE will count the number of switch nodes routed through
+*              the link. If FALSE - only CA/RT nodes are counted.
+*
+*      pfn_ui_pre_lid_assign
+*              A UI function to be invoked prior to lid assigment. It should
+*              return 1 if any change was made to any lid or 0 otherwise.
+*
+*      ui_pre_lid_assign_ctx
+*              A UI context (void *) to be provided to the pfn_ui_pre_lid_assign
+*
+*      pfn_ui_mcast_fdb_assign
+*              A UI function to be called inside the mcast manager instead of
+*              the call for the build spanning tree. This will be called on
+*              every multicast call for create, join and leave, and is
+*              responsible for the mcast FDB configuration.
+*
+*      ui_mcast_fdb_assign_ctx
+*              A UI context (void *) to be provided to the pfn_ui_mcast_fdb_assign
+*
+*      sweep_on_trap
+*              Received traps will initiate a new sweep.
+*
+*      testability_mode
+*              Object that indicates if we are running in a special testability mode.
+*
+*      routing_engine_name
+*              Name of used routing engine
+*              (other than default Min Hop Algorithm)
+*
+*      lid_matrix_dump_file
+*              Name of the lid matrix dump file from where switch
+*              lid matrices (min hops tables) will be loaded
+*
+*      ucast_dump_file
+*              Name of the unicast routing dump file from where switch
+*              forwarding tables will be loaded
+*
+*      updn_guid_file
+*              Pointer to name of the UPDN guid file given by User
+*
+*      sa_db_file
+*              Name of the SA database file.
+*
+*      exit_on_fatal
+*              If TRUE (default) - SM will exit on fatal subnet initialization issues.
+*              If FALSE - SM will not exit.
+*              Fatal initialization issues:
+*              a. SM recognizes 2 different nodes with the same guid, or
+*                 12x link with lane reversal badly configured.
+*
+*      honor_guid2lid_file
+*              Always honor the guid2lid file if it exists and is valid. This
+*              means that the file will be honored when SM is coming out of
+*              STANDBY. By default this is FALSE. 
+*
+*      qos_options
+*              Default set of QoS options
+*
+*      qos_ca_options
+*              QoS options for CA ports
+*
+*      qos_sw0_options
+*              QoS options for switches' port 0
+*
+*      qos_swe_options
+*              QoS options for switches' external ports
+*
+*      qos_rtr_options
+*              QoS options for router ports
+*
+*      enable_quirks
+*              Enable high risk new features and not fully qualified 
+*              hardware specific work arounds
+*
+*      no_clients_rereg
+*              When TRUE disables clients reregistration request.
+*
+* SEE ALSO
+*      Subnet object
+*********/
+
+/****s* OpenSM: Subnet/osm_subn_t
+* NAME
+*      osm_subn_t
+*
+* DESCRIPTION
+*      Subnet structure.  Callers may directly access member components,
+*      after grabbing a lock.
+*
+* TO DO
+*      This structure should probably be volatile.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_subn
+{
+  struct _osm_opensm_t *p_osm;
+  cl_qmap_t               sw_guid_tbl;
+  cl_qmap_t               node_guid_tbl;
+  cl_qmap_t               port_guid_tbl;
+  cl_qmap_t               rtr_guid_tbl;
+  cl_qmap_t               prtn_pkey_tbl;
+  cl_qmap_t               mgrp_mlid_tbl;
+  cl_qmap_t               sm_guid_tbl;
+  cl_list_t                light_sweep_physp_list;
+  cl_qlist_t              sa_sr_list;
+  cl_qlist_t              sa_infr_list;
+  cl_ptr_vector_t         node_lid_tbl;
+  cl_ptr_vector_t         port_lid_tbl;
+  ib_net16_t              master_sm_base_lid;
+  ib_net16_t              sm_base_lid;
+  ib_net64_t              sm_port_guid;
+  uint8_t                 sm_state;
+  osm_subn_opt_t          opt;
+  uint16_t                max_unicast_lid_ho;
+  uint16_t                max_multicast_lid_ho;
+  uint8_t                  min_ca_mtu;
+  uint8_t                  min_ca_rate;
+  boolean_t                ignore_existing_lfts;
+  boolean_t                subnet_initialization_error;
+  boolean_t                force_immediate_heavy_sweep;
+  boolean_t                force_delayed_heavy_sweep;
+  cl_list_t               new_ports_list;
+  boolean_t                in_sweep_hop_0;
+  boolean_t                moved_to_master_state;
+  boolean_t                first_time_master_sweep;
+  boolean_t                coming_out_of_standby;
+} osm_subn_t;
+/*
+* FIELDS
+*      sw_guid_tbl
+*              Container of pointers to all Switch objects in the subent.
+*              Indexed by node GUID.
+*
+*      node_guid_tbl
+*              Container of pointers to all Node objects in the subent.
+*              Indexed by node GUID.
+*
+*      port_guid_tbl
+*              Container of pointers to all Port objects in the subent.
+*              Indexed by port GUID - network order!
+*
+*      rtr_guid_tbl
+*              Container of pointers to all Router objects in the subent.
+*              Indexed by node GUID.
+*
+*      prtn_pkey_tbl
+*              Container of pointers to all Partition objects in the subnet.
+*              Indexed by P_KEY.
+*
+*      mgrp_mlid_tbl
+*              Container of pointers to all Multicast Group objects in the subnet.
+*              Indexed by MLID.
+*
+*      sm_guid_tbl
+*              Container of pointers to SM objects representing other SMs
+*              on the subnet.
+*
+*      light_sweep_physp_list
+*              A list of all phys ports to scan for a change in remote
+*              side state in next light sweep. These ports are not down 
+*              but for some reason the remote side did not answer.
+*
+*      node_lid_tbl
+*              Container of pointers to all Node objects in the subent.
+*              Indexed by node LID.
+*
+*      port_ptr_tbl
+*              Container of pointers to all Port objects in the subent.
+*              Indexed by port LID.
+*
+*      master_sm_base_lid
+*              The base LID owned by the subnet's master SM.
+*
+*      sm_base_lid
+*              The base LID of the local port where the SM is.
+*
+*      sm_port_guid
+*              This SM's own port GUID.
+*
+*      sm_state
+*              The high-level state of the SM.  This value is made available
+*              in the SMInfo attribute.
+*
+*      opt
+*              Subnet options structure contains site specific configuration.
+*
+*      max_unicast_lid_ho
+*              The minimal max unicast lid reported by all switches
+*
+*      max_multicast_lid_ho
+*              The minimal max multicast lid reported by all switches
+*
+*      min_ca_mtu
+*              The minimal MTU reported by all CAs ports on the subnet
+*
+*      min_ca_rate
+*              The minimal rate reported by all CA ports on the subnet
+*
+*  ignore_existing_lfts
+*     This flag is a dynamic flag to instruct the LFT assignment to
+*     ignore existing legal LFT settings.
+*     The value will be set according to :
+*     - During SM init set to the reassign_lfts flag value
+*     - Coming out of STANDBY it will be cleared (other SM worked)
+*     - Any change to the list of switches will set it to high
+*     - Set to FALSE upon end of all lft assignments.
+*
+*  subnet_initalization_error
+*     Similar to the force_immediate_heavy_sweep flag. If TRUE -
+*     means that we had errors during initialization (due to SubnSet requests
+*     that failed). We want to declare the subnet as unhealthy, and force
+*     another heavy sweep.
+*
+*  force_immediate_heavy_sweep
+*     If TRUE - we want to force a heavy sweep. This can be done either
+*     due to receiving of trap - meaning there is some change on the subnet,
+*     or we received a handover from a remote sm.
+*     In this case we want to sweep and reconfigure the entire subnet.
+*     This will cause another heavy sweep to occure when the current sweep
+*     is done.
+*
+*  force_delayed_heavy_sweep
+*     In some means - similar to the force_immediate_heavy_sweep flag, only
+*     it'll cause a heavy sweep in the next sweep. Note that this means that
+*     if we are running with -s 0 (no sweeps) - then this forced heavy sweep
+*     will not occur.
+*     If we had some trouble on the subnet, that caused a strange dropping
+*     of ports - we will try to do another heavy sweep on our next sweep.
+*
+*  new_ports_list
+*     Container of pointers to port objects that were discovered for
+*     the first time during a current sweep.
+*
+*  in_sweep_hop_0
+*     When in_sweep_hop_0 flag is set to TRUE - this means we are
+*     in sweep_hop_0 - meaning we do not want to continue beyond
+*     the current node.
+*     This is relevant for the case of SM on switch, since in the
+*     switch info we need to signal somehow not to continue
+*     the sweeping.
+*
+*  moved_to_master_state
+*     Used for the writing of "SUBNET UP" into /var/log/messages.
+*     Will be TRUE when the SM switches to Master state, and returned
+*     to FALSE once the sunbet is up.
+*
+*  first_time_master_sweep
+*     This flag is used for the PortInfo setting. On the first sweep as master
+*     (meaning after moving from Standby|Discovering state), the SM must send
+*     a PortInfoSet to all ports. After that - we want to minimize the number of
+*     PortInfoSet requests sent, and to send only requests that change the value
+*     from what is updated in the port (or send a first request if this is a new
+*     port). We will set this flag to TRUE when entering the master state, and 
+*     set it back to FALSE at the end of the drop manager. This is done since at
+*     the end of the drop manager we have updated all the ports that are 
+*     reachable, and from now on these are the only ports we have data of. We 
+*     don't want to send extra set requests to these ports anymore.
+*
+*  coming_out_of_standby
+*     TRUE on the first sweep after the SM was in standby.
+*     Used for nulling any cache of LID and Routing.
+*     The flag is set true if the SM state was standby and now changed to MASTER
+*     it is reset at the end of the sweep.
+*
+* SEE ALSO
+*      Subnet object
+*********/
+
+/****f* OpenSM: Subnet/osm_subn_construct
+* NAME
+*      osm_subn_construct
+*
+* DESCRIPTION
+*      This function constructs a Subnet object.
+*
+* SYNOPSIS
+*/
+void
+osm_subn_construct(
+       IN osm_subn_t* const p_subn );
+/*
+* PARAMETERS
+*      p_subn
+*              [in] Pointer to a Subnet object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_subn_init, and osm_subn_destroy.
+*
+*      Calling osm_subn_construct is a prerequisite to calling any other
+*      method except osm_subn_init.
+*
+* SEE ALSO
+*      Subnet object, osm_subn_init, osm_subn_destroy
+*********/
+
+/****f* OpenSM: Subnet/osm_subn_destroy
+* NAME
+*      osm_subn_destroy
+*
+* DESCRIPTION
+*      The osm_subn_destroy function destroys a subnet, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_subn_destroy(
+       IN osm_subn_t* const p_subn );
+/*
+* PARAMETERS
+*      p_subn
+*              [in] Pointer to a Subnet object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified Subnet object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to osm_subn_construct or
+*      osm_subn_init.
+*
+* SEE ALSO
+*      Subnet object, osm_subn_construct, osm_subn_init
+*********/
+
+/****f* OpenSM: Subnet/osm_subn_init
+* NAME
+*      osm_subn_init
+*
+* DESCRIPTION
+*      The osm_subn_init function initializes a Subnet object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_subn_init(
+       IN osm_subn_t* const p_subn,
+       IN struct _osm_opensm_t * const p_osm,
+       IN const osm_subn_opt_t* const p_opt );
+/*
+* PARAMETERS
+*      p_subn
+*              [in] Pointer to an osm_subn_t object to initialize.
+*
+*      p_opt
+*              [in] Pointer to the subnet options structure.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the Subnet object was initialized successfully.
+*
+* NOTES
+*      Allows calling other Subnet methods.
+*
+* SEE ALSO
+*      Subnet object, osm_subn_construct, osm_subn_destroy
+*********/
+
+/*
+  Forward references.
+*/
+struct _osm_mad_addr;
+struct _osm_log;
+struct _osm_switch;
+struct _osm_physp;
+struct _osm_port;
+
+/****f* OpenSM: Helper/osm_get_gid_by_mad_addr
+* NAME
+*      osm_get_gid_by_mad_addr
+*
+* DESCRIPTION
+*      Looks for the requester gid in the mad address.
+*
+* Note: This code is not thread safe. Need to grab the lock before
+* calling it.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_get_gid_by_mad_addr(
+   IN struct _osm_log      *p_log,
+   IN const osm_subn_t     *p_subn,
+   IN const struct _osm_mad_addr *p_mad_addr,
+   OUT ib_gid_t            *p_gid);
+/*
+* PARAMETERS
+*  p_log
+*     [in] Pointer to a log object.
+*
+*  p_subn
+*     [in] Pointer to subnet object.
+*
+*  p_mad_addr
+*     [in] Pointer to mad address object.
+*
+*  p_gid
+*     [out] Pointer to the GID structure to fill in.
+* 
+* RETURN VALUES
+*     IB_SUCCESS if able to find the GID by address given.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Helper/osm_get_physp_by_mad_addr
+* NAME
+*      osm_get_physp_by_mad_addr
+*
+* DESCRIPTION
+*      Looks for the requester physical port in the mad address.
+*
+* Note: This code is not thread safe. Need to grab the lock before
+* calling it.
+*
+* SYNOPSIS
+*/
+struct _osm_physp *
+osm_get_physp_by_mad_addr(
+   IN struct _osm_log      *p_log,
+   IN const osm_subn_t     *p_subn,
+   IN struct _osm_mad_addr *p_mad_addr );
+/*
+* PARAMETERS
+*  p_log
+*     [in] Pointer to a log object.
+*
+*  p_subn
+*     [in] Pointer to subnet object.
+*
+*  p_mad_addr
+*     [in] Pointer to mad address object.
+*
+* RETURN VALUES
+*      Pointer to requester physical port object if found. Null otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Helper/osm_get_port_by_mad_addr
+* NAME
+*      osm_get_port_by_mad_addr
+*
+* DESCRIPTION
+*      Looks for the requester port in the mad address.
+*
+* Note: This code is not thread safe. Need to grab the lock before
+* calling it.
+*
+* SYNOPSIS
+*/
+struct _osm_port *
+osm_get_port_by_mad_addr(
+   IN struct _osm_log      *p_log,
+   IN const osm_subn_t     *p_subn,
+   IN struct _osm_mad_addr *p_mad_addr );
+/*
+* PARAMETERS
+*  p_log
+*     [in] Pointer to a log object.
+*
+*  p_subn
+*     [in] Pointer to subnet object.
+*
+*  p_mad_addr
+*     [in] Pointer to mad address object.
+*
+* RETURN VALUES
+*      Pointer to requester port object if found. Null otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Subnet/osm_get_switch_by_guid
+* NAME
+*      osm_get_switch_by_guid
+*
+* DESCRIPTION
+*      Looks for the given switch guid in the subnet table of switches by guid.
+*  NOTE: this code is not thread safe. Need to grab the lock before
+*  calling it.
+*
+* SYNOPSIS
+*/
+struct _osm_switch *
+osm_get_switch_by_guid(
+   IN const osm_subn_t *p_subn,
+   IN uint64_t          guid );
+/*
+* PARAMETERS
+*      p_subn
+*              [in] Pointer to an osm_subn_t object
+*
+*      guid
+*              [in] The node guid in host order
+*
+* RETURN VALUES
+*      The switch structure pointer if found. NULL otherwise.
+*
+* SEE ALSO
+*      Subnet object, osm_subn_construct, osm_subn_destroy,
+*      osm_switch_t
+*********/
+
+/****f* OpenSM: Subnet/osm_get_node_by_guid
+* NAME
+*      osm_get_node_by_guid
+*
+* DESCRIPTION
+*      The looks for the given node giud in the subnet table of nodes by guid.
+*  NOTE: this code is not thread safe. Need to grab the lock before
+*  calling it.
+*
+* SYNOPSIS
+*/
+struct _osm_node *
+osm_get_node_by_guid(
+   IN osm_subn_t  const *p_subn,
+   IN uint64_t    guid );
+/*
+* PARAMETERS
+*      p_subn
+*              [in] Pointer to an osm_subn_t object
+*
+*      guid
+*              [in] The node guid in host order
+*
+* RETURN VALUES
+*      The node structure pointer if found. NULL otherwise.
+*
+* SEE ALSO
+*      Subnet object, osm_subn_construct, osm_subn_destroy,
+*      osm_node_t
+*********/
+
+/****f* OpenSM: Subnet/osm_get_port_by_guid
+* NAME
+*      osm_get_port_by_guid
+*
+* DESCRIPTION
+*      The looks for the given port guid in the subnet table of ports by guid.
+*  NOTE: this code is not thread safe. Need to grab the lock before
+*  calling it.
+*
+* SYNOPSIS
+*/
+struct _osm_port *
+osm_get_port_by_guid(
+   IN osm_subn_t  const *p_subn,
+   IN uint64_t    guid );
+/*
+* PARAMETERS
+*      p_subn
+*              [in] Pointer to an osm_subn_t object
+*
+*      guid
+*              [in] The port guid in host order
+*
+* RETURN VALUES
+*      The port structure pointer if found. NULL otherwise.
+*
+* SEE ALSO
+*      Subnet object, osm_subn_construct, osm_subn_destroy,
+*      osm_port_t
+*********/
+
+/****f* OpenSM: Helper/osm_get_physp_by_mad_addr
+* NAME
+*      osm_get_physp_by_mad_addr
+*
+* DESCRIPTION
+*      Looks for the requester physical port in the mad address.
+*
+* Note: This code is not thread safe. Need to grab the lock before
+* calling it.
+*
+* SYNOPSIS
+*/
+struct _osm_physp *
+osm_get_physp_by_mad_addr(
+   IN struct _osm_log      *p_log,
+   IN const osm_subn_t     *p_subn,
+   IN struct _osm_mad_addr *p_mad_addr );
+/*
+* PARAMETERS
+*  p_log
+*     [in] Pointer to a log object.
+*
+*  p_subn
+*     [in] Pointer to subnet object.
+*
+*  p_mad_addr
+*     [in] Pointer to mad address object.
+*
+* RETURN VALUES
+*      Pointer to requester physical port object if found. Null otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Subnet/osm_subn_set_default_opt
+* NAME
+*      osm_subn_set_default_opt
+*
+* DESCRIPTION
+*      The osm_subn_set_default_opt function sets the default options.
+*
+* SYNOPSIS
+*/
+void
+osm_subn_set_default_opt(
+       IN osm_subn_opt_t* const p_opt );
+/*
+* PARAMETERS
+*
+*      p_opt
+*              [in] Pointer to the subnet options structure.
+*
+* RETURN VALUES
+*      None
+*
+* NOTES
+*
+* SEE ALSO
+*      Subnet object, osm_subn_construct, osm_subn_destroy
+*********/
+
+/****f* OpenSM: Subnet/osm_subn_set_default_opt
+* NAME
+*      osm_subn_set_default_opt
+*
+* DESCRIPTION
+*      The osm_subn_set_default_opt function sets the default options.
+*
+* SYNOPSIS
+*/
+void
+osm_subn_set_default_opt(
+       IN osm_subn_opt_t* const p_opt );
+/*
+* PARAMETERS
+*
+*      p_opt
+*              [in] Pointer to the subnet options structure.
+*
+* RETURN VALUES
+*      None
+*
+* NOTES
+*
+* SEE ALSO
+*      Subnet object, osm_subn_construct, osm_subn_destroy
+*********/
+
+/****f* OpenSM: Subnet/osm_subn_parse_conf_file
+* NAME
+*      osm_subn_parse_conf_file
+*
+* DESCRIPTION
+*      The osm_subn_parse_conf_file function parses the configuration file
+*      and sets the defaults accordingly.
+*
+* SYNOPSIS
+*/
+void
+osm_subn_parse_conf_file(
+  IN osm_subn_opt_t* const p_opt );
+/*
+* PARAMETERS
+*
+*      p_opt
+*              [in] Pointer to the subnet options structure.
+*
+* RETURN VALUES
+*      None
+*
+* NOTES
+*  Assumes the conf file is part of the cache dir which defaults to
+*  OSM_DEFAULT_CACHE_DIR or OSM_CACHE_DIR the name is opensm.opts
+*
+* SEE ALSO
+*      Subnet object, osm_subn_construct, osm_subn_destroy
+*********/
+
+/****f* OpenSM: Subnet/osm_subn_parse_conf_file
+* NAME
+*      osm_subn_rescan_conf_file
+*
+* DESCRIPTION
+*      The osm_subn_rescan_conf_file function parses the configuration
+*      file and update selected subnet options
+*
+* SYNOPSIS
+*/
+void
+osm_subn_rescan_conf_file(
+  IN osm_subn_opt_t* const p_opts );
+/*
+* PARAMETERS
+*
+*      p_opt
+*              [in] Pointer to the subnet options structure.
+*
+* RETURN VALUES
+*      None
+*
+* NOTES
+*  This uses the same file as osm_subn_parse_conf_file()
+*
+*********/
+
+/****f* OpenSM: Subnet/osm_subn_write_conf_file
+* NAME
+*      osm_subn_write_conf_file
+*
+* DESCRIPTION
+*  Write the configuration file into the cache
+*
+* SYNOPSIS
+*/
+void
+osm_subn_write_conf_file(
+  IN osm_subn_opt_t* const p_opt );
+/*
+* PARAMETERS
+*
+*      p_opt
+*              [in] Pointer to the subnet options structure.
+*
+* RETURN VALUES
+*      None
+*
+* NOTES
+*  Assumes the conf file is part of the cache dir which defaults to
+*  OSM_DEFAULT_CACHE_DIR or OSM_CACHE_DIR the name is opensm.opts
+*
+* SEE ALSO
+*      Subnet object, osm_subn_construct, osm_subn_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SUBNET_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sw_info_rcv.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sw_info_rcv.h
new file mode 100644 (file)
index 0000000..ecb976c
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sw_info_rcv.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_si_rcv_t.
+ *     This object represents the SwitchInfo Receiver object.
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SI_RCV_H_
+#define _OSM_SI_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_state_mgr.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Switch Info Receiver
+* NAME
+*      Switch Info Receiver
+*
+* DESCRIPTION
+*      The Switch Info Receiver object encapsulates the information
+*      needed to receive the SwitchInfo attribute from a node.
+*
+*      The Switch Info Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Switch Info Receiver/osm_si_rcv_t
+* NAME
+*      osm_si_rcv_t
+*
+* DESCRIPTION
+*      Switch Info Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_si_rcv
+{
+       osm_subn_t                              *p_subn;
+       osm_log_t                               *p_log;
+       osm_req_t                               *p_req;
+       osm_state_mgr_t                         *p_state_mgr;
+       cl_plock_t                              *p_lock;
+
+} osm_si_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_req
+*              Pointer to the Request object.
+*
+*      p_state_mgr
+*              Pointer to the State Manager object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+* SEE ALSO
+*      Switch Info Receiver object
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_si_rcv_construct
+* NAME
+*      osm_si_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a Switch Info Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_si_rcv_construct(
+       IN osm_si_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Switch Info Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_si_rcv_init, osm_si_rcv_destroy,
+*      and osm_si_rcv_is_inited.
+*
+*      Calling osm_si_rcv_construct is a prerequisite to calling any other
+*      method except osm_si_rcv_init.
+*
+* SEE ALSO
+*      Switch Info Receiver object, osm_si_rcv_init,
+*      osm_si_rcv_destroy, osm_si_rcv_is_inited
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_si_rcv_destroy
+* NAME
+*      osm_si_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_si_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_si_rcv_destroy(
+       IN osm_si_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Switch Info Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_si_rcv_construct or osm_si_rcv_init.
+*
+* SEE ALSO
+*      Switch Info Receiver object, osm_si_rcv_construct,
+*      osm_si_rcv_init
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_si_rcv_init
+* NAME
+*      osm_si_rcv_init
+*
+* DESCRIPTION
+*      The osm_si_rcv_init function initializes a
+*      Switch Info Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_si_rcv_init(
+       IN osm_si_rcv_t* const p_ctrl,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN osm_req_t* const p_req,
+       IN osm_state_mgr_t* const p_state_mgr,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_si_rcv_t object to initialize.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_req
+*              [in] Pointer to an osm_req_t object.
+*
+*      p_state_mgr
+*              [in] Pointer to the State Manager object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the Switch Info Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Switch Info Receiver methods.
+*
+* SEE ALSO
+*      Switch Info Receiver object, osm_si_rcv_construct,
+*      osm_si_rcv_destroy, osm_si_rcv_is_inited
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_si_rcv_is_inited
+* NAME
+*      osm_si_rcv_is_inited
+*
+* DESCRIPTION
+*      Indicates if the object has been initialized with osm_si_rcv_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_si_rcv_is_inited(
+       IN const osm_si_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_si_rcv_t object.
+*
+* RETURN VALUES
+*      TRUE if the object was initialized successfully,
+*      FALSE otherwise.
+*
+* NOTES
+*      The osm_si_rcv_construct or osm_si_rcv_init must be
+*      called before using this function.
+*
+* SEE ALSO
+*      Switch Info Receiver object, osm_si_rcv_construct,
+*      osm_si_rcv_init
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_si_rcv_process
+* NAME
+*      osm_si_rcv_process
+*
+* DESCRIPTION
+*      Process the SwitchInfo attribute.
+*
+* SYNOPSIS
+*/
+void osm_si_rcv_process(
+       IN const osm_si_rcv_t* const p_ctrl,
+       IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_si_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the node's SwitchInfo attribute.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the SwitchInfo processing was successful.
+*
+* NOTES
+*      This function processes a SwitchInfo attribute.
+*
+* SEE ALSO
+*      Switch Info Receiver, Switch Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SI_RCV_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sw_info_rcv_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sw_info_rcv_ctrl.h
new file mode 100644 (file)
index 0000000..5f502cc
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sw_info_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_si_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA SwitchInfo
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SI_RCV_CTRL_H_
+#define _OSM_SI_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sw_info_rcv.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Switch Info Receive Controller
+* NAME
+*      Switch Info Receive Controller
+*
+* DESCRIPTION
+*      The Switch Info Receive Controller object encapsulates
+*      the information needed to receive the SwitchInfo attribute from a node.
+*
+*      The Switch Info Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Switch Info Receive Controller/osm_si_rcv_ctrl_t
+* NAME
+*      osm_si_rcv_ctrl_t
+*
+* DESCRIPTION
+*      Switch Info Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_si_rcv_ctrl
+{
+       osm_si_rcv_t                    *p_rcv;
+       osm_log_t                       *p_log;
+       cl_dispatcher_t                 *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_si_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the Switch Info Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      Switch Info Receive Controller object
+*      Switch Info Receiver object
+*********/
+
+/****f* OpenSM: Switch Info Receive Controller/osm_si_rcv_ctrl_construct
+* NAME
+*      osm_si_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Switch Info Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_si_rcv_ctrl_construct(
+       IN osm_si_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Switch Info Receive Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_si_rcv_ctrl_init, osm_si_rcv_ctrl_destroy,
+*      and osm_si_rcv_ctrl_is_inited.
+*
+*      Calling osm_si_rcv_ctrl_construct is a prerequisite to calling any other
+*      method except osm_si_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Switch Info Receive Controller object, osm_si_rcv_ctrl_init,
+*      osm_si_rcv_ctrl_destroy, osm_si_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Switch Info Receive Controller/osm_si_rcv_ctrl_destroy
+* NAME
+*      osm_si_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_si_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_si_rcv_ctrl_destroy(
+       IN osm_si_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Switch Info Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_si_rcv_ctrl_construct or osm_si_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Switch Info Receive Controller object, osm_si_rcv_ctrl_construct,
+*      osm_si_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Switch Info Receive Controller/osm_si_rcv_ctrl_init
+* NAME
+*      osm_si_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_si_rcv_ctrl_init function initializes a
+*      Switch Info Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_si_rcv_ctrl_init(
+       IN osm_si_rcv_ctrl_t* const p_ctrl,
+       IN osm_si_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_si_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_si_rcv_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Switch Info Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Switch Info Receive Controller methods.
+*
+* SEE ALSO
+*      Switch Info Receive Controller object, osm_si_rcv_ctrl_construct,
+*      osm_si_rcv_ctrl_destroy, osm_si_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Switch Info Receive Controller/osm_si_rcv_ctrl_is_inited
+* NAME
+*      osm_si_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+*      Indicates if the object has been initialized with osm_si_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_si_rcv_ctrl_is_inited(
+       IN const osm_si_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_si_rcv_ctrl_t object.
+*
+* RETURN VALUES
+*      TRUE if the object was initialized successfully,
+*      FALSE otherwise.
+*
+* NOTES
+*      The osm_si_rcv_ctrl_construct or osm_si_rcv_ctrl_init must be
+*      called before using this function.
+*
+* SEE ALSO
+*      Switch Info Receive Controller object, osm_si_rcv_ctrl_construct,
+*      osm_si_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SI_RCV_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sweep_fail_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_sweep_fail_ctrl.h
new file mode 100644 (file)
index 0000000..3979a4d
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sweep_fail_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_sweep_fail_ctrl_t.
+ *     This object represents a controller that
+ *     handles transport failures during sweeps.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SWEEP_FAIL_CTRL_H_
+#define _OSM_SWEEP_FAIL_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_state_mgr.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Sweep Fail Controller
+* NAME
+*      Sweep Fail Controller
+*
+* DESCRIPTION
+*      The Sweep Fail Controller object encapsulates
+*      the information needed to handle transport failures during
+*      sweeps.
+*
+*      The Sweep Fail Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Sweep Fail Controller/osm_sweep_fail_ctrl_t
+* NAME
+*      osm_sweep_fail_ctrl_t
+*
+* DESCRIPTION
+*      Sweep Fail Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sweep_fail_ctrl
+{
+       osm_log_t                                       *p_log;
+       osm_state_mgr_t                         *p_state_mgr;
+       cl_dispatcher_t                         *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+
+} osm_sweep_fail_ctrl_t;
+/*
+* FIELDS
+*      p_log
+*              Pointer to the log object.
+*
+*      p_sate_mgr
+*              Pointer to the state manager object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      Sweep Fail Controller object
+*      Sweep Failr object
+*********/
+
+/****f* OpenSM: Sweep Fail Controller/osm_sweep_fail_ctrl_construct
+* NAME
+*      osm_sweep_fail_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Sweep Fail Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_sweep_fail_ctrl_construct(
+       IN osm_sweep_fail_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Sweep Fail Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_sweep_fail_ctrl_init, osm_sweep_fail_ctrl_destroy
+*
+*      Calling osm_sweep_fail_ctrl_construct is a prerequisite to calling any other
+*      method except osm_sweep_fail_ctrl_init.
+*
+* SEE ALSO
+*      Sweep Fail Controller object, osm_sweep_fail_ctrl_init,
+*      osm_sweep_fail_ctrl_destroy
+*********/
+
+/****f* OpenSM: Sweep Fail Controller/osm_sweep_fail_ctrl_destroy
+* NAME
+*      osm_sweep_fail_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_sweep_fail_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_sweep_fail_ctrl_destroy(
+       IN osm_sweep_fail_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Sweep Fail Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_sweep_fail_ctrl_construct or osm_sweep_fail_ctrl_init.
+*
+* SEE ALSO
+*      Sweep Fail Controller object, osm_sweep_fail_ctrl_construct,
+*      osm_sweep_fail_ctrl_init
+*********/
+
+/****f* OpenSM: Sweep Fail Controller/osm_sweep_fail_ctrl_init
+* NAME
+*      osm_sweep_fail_ctrl_init
+*
+* DESCRIPTION
+*      The osm_sweep_fail_ctrl_init function initializes a
+*      Sweep Fail Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sweep_fail_ctrl_init(
+       IN osm_sweep_fail_ctrl_t* const p_ctrl,
+       IN osm_log_t* const p_log,
+       IN osm_state_mgr_t* const p_state_mgr,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_sweep_fail_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_sweep_fail_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_state_mgr
+*              [in] Pointer to the state manager object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Sweep Fail Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Sweep Fail Controller methods.
+*
+* SEE ALSO
+*      Sweep Fail Controller object, osm_sweep_fail_ctrl_construct,
+*      osm_sweep_fail_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SWEEP_FAIL_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_switch.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_switch.h
new file mode 100644 (file)
index 0000000..27e5f74
--- /dev/null
@@ -0,0 +1,1552 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_switch.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_switch_t.
+ *     This object represents an IBA switch.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#ifndef _OSM_SWITCH_H_
+#define _OSM_SWITCH_H_
+
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_matrix.h>
+#include <opensm/osm_fwd_tbl.h>
+#include <opensm/osm_mcast_tbl.h>
+#include <opensm/osm_port_profile.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Switch
+* NAME
+*      Switch
+*
+* DESCRIPTION
+*      The Switch object encapsulates the information needed by the
+*      OpenSM to manage switches.  The OpenSM allocates one switch object
+*      per switch in the IBA subnet.
+*
+*      The Switch object is not thread safe, thus callers must provide
+*      serialization.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Switch/osm_switch_t
+* NAME
+*      osm_switch_t
+*
+* DESCRIPTION
+*      Switch structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_switch
+{
+       cl_map_item_t                           map_item;
+       osm_node_t                              *p_node;
+       ib_switch_info_t                        switch_info;
+       osm_fwd_tbl_t                           fwd_tbl;
+       osm_lid_matrix_t                        lmx;
+       uint16_t                                max_lid_ho;
+       osm_port_profile_t                      *p_prof;
+       osm_mcast_tbl_t                         mcast_tbl;
+       uint32_t                                discovery_count;
+} osm_switch_t;
+/*
+* FIELDS
+*      map_item
+*              Linkage structure for cl_qmap.  MUST BE FIRST MEMBER!
+*
+*      p_node
+*              Pointer to the Node object for this switch.
+*
+*      switch_info
+*              IBA defined SwitchInfo structure for this switch.
+*
+*      fwd_tbl
+*              This switch's forwarding table.
+*
+*      lmx
+*              LID Matrix for this switch containing the hop count
+*              to every LID from every port.
+*
+*      max_lid_ho
+*              Max LID that is accessible from this switch.
+* 
+*      p_pro
+*              Pointer to array of Port Profile objects for this switch.
+*
+*      mcast_tbl
+*              Multicast forwarding table for this switch.
+*
+*      discovery_count
+*              The number of times this switch has been discovered
+*              during the current fabric sweep.  This number is reset
+*              to zero at the start of a sweep.
+*
+* SEE ALSO
+*      Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_construct
+* NAME
+*      osm_switch_construct
+*
+* DESCRIPTION
+*      This function constructs a Switch object.
+*
+* SYNOPSIS
+*/
+void
+osm_switch_construct(
+       IN osm_switch_t* const p_sw );
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to a Switch object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_switch_init, and osm_switch_destroy.
+*
+*      Calling osm_switch_construct is a prerequisite to calling any other
+*      method except osm_switch_init.
+*
+* SEE ALSO
+*      Switch object, osm_switch_init, osm_switch_destroy
+*********/
+
+/****f* OpenSM: Switch/osm_switch_destroy
+* NAME
+*      osm_switch_destroy
+*
+* DESCRIPTION
+*      The osm_switch_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_switch_destroy(
+       IN osm_switch_t* const p_sw );
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to osm_switch_construct
+*      or osm_switch_init.
+*
+* SEE ALSO
+*      Switch object, osm_switch_construct, osm_switch_init
+*********/
+
+/****f* OpenSM: Switch/osm_switch_destroy
+* NAME
+*      osm_switch_destroy
+*
+* DESCRIPTION
+*      Destroys and deallocates the object.
+*
+* SYNOPSIS
+*/
+void
+osm_switch_delete(
+       IN OUT osm_switch_t** const pp_sw );
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      Switch object, osm_switch_construct, osm_switch_init
+*********/
+
+/****f* OpenSM: Switch/osm_switch_init
+* NAME
+*      osm_switch_init
+*
+* DESCRIPTION
+*      The osm_switch_init function initializes a Switch object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_switch_init(
+       IN osm_switch_t* const p_sw,
+       IN osm_node_t* const p_node,
+       IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to an osm_switch_t object to initialize.
+*
+*      p_node
+*              [in] Pointer to the node object of this switch
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the switch's
+*              SwitchInfo attribute.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the Switch object was initialized successfully.
+*
+* NOTES
+*      Allows calling other node methods.
+*
+* SEE ALSO
+*      Switch object, osm_switch_construct, osm_switch_destroy
+*********/
+
+/****f* OpenSM: Switch/osm_switch_new
+* NAME
+*      osm_switch_new
+*
+* DESCRIPTION
+*      The osm_switch_init function initializes a Switch object for use.
+*
+* SYNOPSIS
+*/
+osm_switch_t*
+osm_switch_new(
+       IN osm_node_t* const p_node,
+       IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_node
+*              [in] Pointer to the node object of this switch
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the switch's
+*              SwitchInfo attribute.
+*
+* RETURN VALUES
+*      Pointer to the new initialized switch object.
+*
+* NOTES
+*
+* SEE ALSO
+*      Switch object, osm_switch_construct, osm_switch_destroy,
+*********/
+
+/****f* OpenSM: Switch/osm_switch_is_leaf_lid
+* NAME
+*      osm_switch_is_leaf_lid
+*
+* DESCRIPTION
+*      Indicates if the specified LID is the switch's LID, or is a leaf
+*      of the switch.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_switch_is_leaf_lid(
+       IN const osm_switch_t* const p_sw,
+       IN const uint16_t lid_ho )
+{
+       return( osm_lid_matrix_get_least_hops( &p_sw->lmx, lid_ho ) <= 1 );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to an osm_switch_t object.
+*
+*      lid_ho
+*              [in] LID (host order) to compare.
+*
+* RETURN VALUES
+*      TRUE if the LID is the switch's LID or is a leaf of the switch,
+*      FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*      Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_hop_count
+* NAME
+*      osm_switch_get_hop_count
+*
+* DESCRIPTION
+*      Returns the hop count at the specified LID/Port intersection.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_switch_get_hop_count(
+       IN const osm_switch_t* const p_sw,
+       IN const uint16_t lid_ho,
+       IN const uint8_t port_num )
+{
+       return( osm_lid_matrix_get( &p_sw->lmx, lid_ho, port_num ) );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to a Switch object.
+*
+*      lid_ho
+*              [in] LID value (host order) for which to return the hop count
+*
+*      port_num
+*              [in] Port number in the switch
+*
+* RETURN VALUES
+*      Returns the hop count at the specified LID/Port intersection.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_fwd_tbl_ptr
+* NAME
+*      osm_switch_get_fwd_tbl_ptr
+*
+* DESCRIPTION
+*      Returns a pointer to the switch's forwarding table.
+*
+* SYNOPSIS
+*/
+static inline osm_fwd_tbl_t*
+osm_switch_get_fwd_tbl_ptr(
+       IN const osm_switch_t* const p_sw )
+{
+       return( (osm_fwd_tbl_t*)&p_sw->fwd_tbl );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to a Switch object.
+*
+* RETURN VALUES
+*      Returns a pointer to the switch's forwarding table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_set_hops
+* NAME
+*      osm_switch_set_hops
+*
+* DESCRIPTION
+*      Sets the hop count at the specified LID/Port intersection.
+*
+* SYNOPSIS
+*/
+static inline cl_status_t
+osm_switch_set_hops(
+       IN osm_switch_t* const p_sw,
+       IN const uint16_t lid_ho,
+       IN const uint8_t port_num,
+       IN const uint8_t num_hops )
+{
+       return( osm_lid_matrix_set( &p_sw->lmx, lid_ho, port_num, num_hops ) );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to a Switch object.
+*
+*      lid_ho
+*              [in] LID value (host order) for which to set the count.
+*
+*      port_num
+*              [in] port number for which to set the count.
+*
+*      num_hops
+*              [in] value to assign to this entry.
+*
+* RETURN VALUES
+*      Returns the hop count at the specified LID/Port intersection.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_set_min_lid_size
+* NAME
+*      osm_switch_set_min_lid_size
+*
+* DESCRIPTION
+*      Sets the size of the switch's routing table to at least accomodate the
+*      specified LID value (host ordered)
+*
+* SYNOPSIS
+*/
+static inline cl_status_t
+osm_switch_set_min_lid_size(
+       IN osm_switch_t* const p_sw,
+       IN const uint16_t lid_ho )
+{
+       return( osm_lid_matrix_set_min_lid_size( &p_sw->lmx, lid_ho ) );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to a Switch object.
+*
+*      lid_ho
+*              [in] LID value (host order) for which to set the count.
+*
+* RETURN VALUES
+*      Sets the size of the switch's routing table to at least accomodate the
+*      specified LID value (host ordered)
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_least_hops
+* NAME
+*      osm_switch_get_least_hops
+*
+* DESCRIPTION
+*      Returns the number of hops in the short path to this lid from
+*      any port on the switch.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_switch_get_least_hops(
+       IN const osm_switch_t* const p_sw,
+       IN const uint16_t lid_ho )
+{
+       return( osm_lid_matrix_get_least_hops( &p_sw->lmx, lid_ho ) );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to an osm_switch_t object.
+*
+*      lid_ho
+*              [in] LID (host order) for which to retrieve the shortest hop count.
+*
+* RETURN VALUES
+*      Returns the number of hops in the short path to this lid from
+*      any port on the switch.
+*
+* NOTES
+*
+* SEE ALSO
+*      Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_port_by_lid
+* NAME
+*      osm_switch_get_port_by_lid
+*
+* DESCRIPTION
+*      Returns the switch port number on which the specified LID is routed.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_switch_get_port_by_lid(
+       IN const osm_switch_t* const p_sw,
+       IN const uint16_t lid_ho )
+{
+       return( osm_fwd_tbl_get( &p_sw->fwd_tbl, lid_ho ) );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to an osm_switch_t object.
+*
+*      lid_ho
+*              [in] LID (host order) for which to retrieve the shortest hop count.
+*
+* RETURN VALUES
+*      Returns the switch port on which the specified LID is routed.
+*
+* NOTES
+*
+* SEE ALSO
+*      Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_physp_ptr
+* NAME
+*      osm_switch_get_physp_ptr
+*
+* DESCRIPTION
+*      Gets the Physical Port Object at the specified port number.
+*
+* SYNOPSIS
+*/
+osm_physp_t*
+osm_switch_get_physp_ptr(
+       IN const osm_switch_t* const p_sw,
+       IN const uint32_t port_num );
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to an osm_switch_t object.
+*
+*      port_num
+*              [in] Port number for which to retrieve the Physical Port Object.
+*
+* RETURN VALUES
+*      Returns a pointer to the Physical Port Object object at the specified
+*      port number.
+*      A return value of zero means the port number was out of range.
+*      
+*
+* NOTES
+*
+* SEE ALSO
+*      Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_route_by_lid
+* NAME
+*      osm_switch_get_route_by_lid
+*
+* DESCRIPTION
+*      Gets the physical port object that routes the specified LID.
+*
+* SYNOPSIS
+*/
+static inline osm_physp_t*
+osm_switch_get_route_by_lid(
+       IN const osm_switch_t* const p_sw,
+       IN const ib_net16_t lid )
+{
+       uint8_t port_num;
+
+       CL_ASSERT( p_sw );
+       CL_ASSERT( lid );
+
+       port_num = osm_fwd_tbl_get( &p_sw->fwd_tbl, cl_ntoh16( lid ) );
+       /*
+          In order to avoid holes in the subnet (usually happens when
+          running UPDN algorithm), i.e. cases where port is
+          unreachable through a switch (we put an OSM_NO_PATH value at
+          the port entry, we do not assert on unreachable lid entries
+          at the fwd table but return NULL
+       */
+       if (port_num != OSM_NO_PATH)
+               return( osm_node_get_physp_ptr( p_sw->p_node, port_num ) );
+       else
+               return NULL;
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to an osm_switch_t object.
+*
+*      lid
+*              [in] LID for which to find a route.  This must be a unicast
+*              LID value < 0xC000.
+*
+* RETURN VALUES
+*      Returns a pointer to the Physical Port Object object that
+*      routes the specified LID.  A return value of zero means
+*      there is no route for the lid through this switch.
+*      The lid value must be a unicast LID.
+*      
+* NOTES
+*
+* SEE ALSO
+*      Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_si_ptr
+* NAME
+*      osm_switch_get_si_ptr
+*
+* DESCRIPTION
+*      Returns a pointer to the SwitchInfo for this switch.
+*
+* SYNOPSIS
+*/
+static inline ib_switch_info_t*
+osm_switch_get_si_ptr(
+       IN const osm_switch_t* const p_sw )
+{
+       return( (ib_switch_info_t*)&p_sw->switch_info );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+*      Returns a pointer to the SwitchInfo for this switch.
+*      
+* NOTES
+*
+* SEE ALSO
+*      Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_sp0_is_lmc_capable
+* NAME
+*      osm_switch_sp0_is_lmc_capable
+*
+* DESCRIPTION
+*      Returns whether switch port 0 (SP0) can support LMC
+*
+*/
+static inline unsigned
+osm_switch_sp0_is_lmc_capable(
+       IN const osm_switch_t* const p_sw,
+       IN osm_subn_t *p_subn)
+{
+       return (p_subn->opt.lmc_esp0 &&
+               ib_switch_info_is_enhanced_port0(&p_sw->switch_info)) ? 1 : 0;
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to an osm_switch_t object.
+*
+*      p_subn
+*              [in] Pointer to an osm_subn_t object.
+*
+* RETURN VALUES
+*      TRUE if SP0 is enhanced and globally enabled. FALSE otherwise.
+*       
+* NOTES
+*      This is workaround function, it takes into account user defined
+*      p_subn->opt.lmc_esp0 parameter.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_max_block_id
+* NAME
+*      osm_switch_get_max_block_id
+*
+* DESCRIPTION
+*      Returns the maximum block ID (host order) of this switch.
+*
+* SYNOPSIS
+*/
+static inline uint32_t
+osm_switch_get_max_block_id(
+       IN const osm_switch_t* const p_sw )
+{
+       return( (uint32_t)(osm_fwd_tbl_get_size( &p_sw->fwd_tbl ) /
+               osm_fwd_tbl_get_lids_per_block( &p_sw->fwd_tbl ) ) );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+*      Returns the maximum block ID (host order) of this switch.
+*      
+* NOTES
+*
+* SEE ALSO
+*      Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_max_block_id_in_use
+* NAME
+*      osm_switch_get_max_block_id_in_use
+*
+* DESCRIPTION
+*      Returns the maximum block ID (host order) of this switch that
+*      is used for unicast routing.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_switch_get_max_block_id_in_use(
+       IN const osm_switch_t* const p_sw )
+{
+       return( osm_fwd_tbl_get_max_block_id_in_use( &p_sw->fwd_tbl,
+                       cl_ntoh16( p_sw->switch_info.lin_top ) ) );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+*      Returns the maximum block ID (host order) of this switch.
+*      
+* NOTES
+*
+* SEE ALSO
+*      Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_node_ptr
+* NAME
+*      osm_switch_get_node_ptr
+*
+* DESCRIPTION
+*      Returns a pointer to the Node object for this switch.
+*
+* SYNOPSIS
+*/
+static inline osm_node_t*
+osm_switch_get_node_ptr(
+       IN const osm_switch_t* const p_sw )
+{
+       return( p_sw->p_node );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+*      Returns a pointer to the Node object for this switch.
+*      
+* NOTES
+*
+* SEE ALSO
+*      Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_max_lid_ho
+* NAME
+*      osm_switch_get_max_lid_ho
+*
+* DESCRIPTION
+*      Returns the maximum LID (host order) value contained
+*      in the switch routing tables.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_switch_get_max_lid_ho(
+       IN const osm_switch_t* const p_sw )
+{
+       if (p_sw->max_lid_ho != 0)
+               return p_sw->max_lid_ho;
+       return( osm_lid_matrix_get_max_lid_ho( &p_sw->lmx ) );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to a switch object.
+*
+* RETURN VALUES
+*      Returns the maximum LID (host order) value contained
+*      in the switch routing tables.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_num_ports
+* NAME
+*      osm_switch_get_num_ports
+*
+* DESCRIPTION
+*      Returns the number of ports in this switch.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_switch_get_num_ports(
+       IN const osm_switch_t* const p_sw )
+{
+       return( osm_lid_matrix_get_num_ports( &p_sw->lmx ) );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+*      Returns the number of ports in this switch.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_fwd_tbl_block
+* NAME
+*      osm_switch_get_fwd_tbl_block
+*
+* DESCRIPTION
+*      Retrieve a forwarding table block.
+*
+* SYNOPSIS
+*/
+boolean_t
+osm_switch_get_fwd_tbl_block(
+       IN const osm_switch_t* const p_sw,
+       IN const uint32_t block_id,
+       OUT uint8_t* const p_block );
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to an osm_switch_t object.
+*
+*      block_ID
+*              [in] The block_id to retrieve.
+*
+*      p_block
+*              [out] Pointer to the 64 byte array to store the
+*              forwarding table clock specified by block_id.
+*
+* RETURN VALUES
+*      Returns true if there are more blocks necessary to 
+*      configure all the LIDs reachable from this switch.
+*      FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_supports_mcast
+* NAME
+*      osm_switch_supports_mcast
+*
+* DESCRIPTION
+*      Indicates if a switch supports multicast.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_switch_supports_mcast(
+       IN const osm_switch_t* const p_sw )
+{
+       return( p_sw->switch_info.mcast_cap != 0 );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+*      Returns TRUE if the switch supports multicast.
+*      FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_set_switch_info
+* NAME
+*      osm_switch_set_switch_info
+*
+* DESCRIPTION
+*      Updates the switch info attribute of this switch.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_switch_set_switch_info(
+       IN osm_switch_t* const p_sw,
+       IN const ib_switch_info_t* const p_si )
+{
+       CL_ASSERT( p_sw );
+       CL_ASSERT( p_si );
+       p_sw->switch_info = *p_si;
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to a Switch object.
+*
+*      p_si
+*              [in] Pointer to the SwitchInfo attribute for this switch.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_count_path
+* NAME
+*      osm_switch_count_path
+*
+* DESCRIPTION
+*      Counts this path in port profile.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_switch_count_path(
+       IN osm_switch_t* const p_sw,
+       IN const uint8_t port
+       )
+{
+         osm_port_prof_path_count_inc( &p_sw->p_prof[port] );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to the switch object.
+*
+*      port
+*              [in] Port to count path.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_set_ft_block
+* NAME
+*      osm_switch_set_ft_block
+*
+* DESCRIPTION
+*      Copies in the specified block into the switch's Forwarding Table object.
+*
+* SYNOPSIS
+*/
+static inline ib_api_status_t
+osm_switch_set_ft_block(
+       IN osm_switch_t* const p_sw,
+       IN const uint8_t* const p_block,
+       IN const uint32_t block_num )
+{
+       CL_ASSERT( p_sw );
+       return( osm_fwd_tbl_set_block( &p_sw->fwd_tbl, p_block, block_num ) );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to the switch object.
+*
+*      p_block
+*              [in] Pointer to the forwarding table block.
+*
+*      block_num
+*              [in] Block number for this block
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_set_mft_block
+* NAME
+*      osm_switch_set_mft_block
+*
+* DESCRIPTION
+*      Sets a block of multicast port masks into the multicast table.
+*
+* SYNOPSIS
+*/
+static inline ib_api_status_t
+osm_switch_set_mft_block(
+       IN osm_switch_t* const p_sw,
+       IN const ib_net16_t* const p_block,
+       IN const uint16_t block_num,
+       IN const uint8_t position )
+{
+       CL_ASSERT( p_sw );
+       return( osm_mcast_tbl_set_block( &p_sw->mcast_tbl, p_block,
+                       block_num, position ) );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to the switch object.
+*
+*      p_block
+*              [in] Pointer to the block of port masks to set.
+*
+*      block_num
+*              [in] Block number (0-511) to set.
+*
+*      position
+*              [in] Port mask position (0-15) to set.
+*
+* RETURN VALUE
+*      IB_SUCCESS on success.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_mft_block
+* NAME
+*      osm_switch_get_mft_block
+*
+* DESCRIPTION
+*      Retrieve a block of multicast port masks from the multicast table.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_switch_get_mft_block(
+       IN osm_switch_t* const p_sw,
+       IN const uint16_t block_num,
+       IN const uint8_t position,
+       OUT ib_net16_t* const p_block )
+{
+       CL_ASSERT( p_sw );
+       return( osm_mcast_tbl_get_block( &p_sw->mcast_tbl,
+                       block_num, position, p_block ) );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to the switch object.
+*
+*      block_num
+*              [in] Block number (0-511) to set.
+*
+*      position
+*              [in] Port mask position (0-15) to set.
+*
+*      p_block
+*              [out] Pointer to the block of port masks stored.
+*
+* RETURN VALUES
+*      Returns true if there are more blocks necessary to 
+*      configure all the MLIDs reachable from this switch.
+*      FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_mft_max_block
+* NAME
+*      osm_switch_get_mft_max_block
+*
+* DESCRIPTION
+*       Get the max_block from the associated multicast table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_switch_get_mft_max_block(
+       IN osm_switch_t* const p_sw )
+{
+       CL_ASSERT( p_sw );
+       return( osm_mcast_tbl_get_max_block( &p_sw->mcast_tbl ) );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to the switch object.
+*
+* RETURN VALUE
+*/
+
+/****f* OpenSM: Switch/osm_switch_get_mft_max_block_in_use
+* NAME
+*      osm_switch_get_mft_max_block_in_use
+*
+* DESCRIPTION
+*      Get the max_block_in_use from the associated multicast table.
+*
+* SYNOPSIS
+*/
+static inline int16_t
+osm_switch_get_mft_max_block_in_use(
+       IN osm_switch_t* const p_sw )
+{
+       CL_ASSERT( p_sw );
+       return( osm_mcast_tbl_get_max_block_in_use( &p_sw->mcast_tbl ) );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to the switch object.
+*
+* RETURN VALUES
+*      Returns the maximum block ID in use in this switch's mcast table.
+*      A value of -1 indicates no blocks are in use.
+*
+* NOTES
+*
+* SEE ALSO
+*/
+
+/****f* OpenSM: Switch/osm_switch_get_mft_max_position
+* NAME
+*      osm_switch_get_mft_max_position
+*
+* DESCRIPTION
+*       Get the max_position from the associated multicast table.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_switch_get_mft_max_position(
+       IN osm_switch_t* const p_sw )
+{
+       CL_ASSERT( p_sw );
+       return( osm_mcast_tbl_get_max_position( &p_sw->mcast_tbl ) );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to the switch object.
+*
+* RETURN VALUE
+*/
+
+/****f* OpenSM: Switch/osm_switch_recommend_path
+* NAME
+*      osm_switch_recommend_path
+*
+* DESCRIPTION
+*      Returns the recommended port on which to route this LID.
+*      In cases where LMC > 0, the remote side system and node
+*      used for the routing are tracked in the provided arrays
+*      (and counts) such that other lid for the same port will
+*      try and avoid going through the same remote system/node.
+*
+* SYNOPSIS
+*/
+uint8_t
+osm_switch_recommend_path(
+       IN const osm_switch_t* const p_sw,
+       IN const uint16_t lid_ho,
+       IN const boolean_t ignore_existing,
+       IN OUT uint64_t *remote_sys_guids,
+       IN OUT uint16_t *p_num_used_sys,
+       IN OUT uint64_t *remote_node_guids,
+       IN OUT uint16_t *p_num_used_nodes
+ );
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to the switch object.
+*
+*      lid_ho
+*              [in] LID value (host order) for which to get a path advisory.
+*
+*      ignore_existing
+*              [in] Set to cause the switch to choose the optimal route
+*              regardless of existing paths.
+*              If false, the switch will choose an existing route if one
+*              exists, otherwise will choose the optimal route.
+*
+*      remote_sys_guids
+*              [in out] The array of remote system guids already used to
+*              route the other lids of the same target port (if LMC > 0).
+*  
+*      p_num_used_sys
+*              [in out] The number of remote systems used for routing to
+*              the port.
+*
+*      remote_node_guids
+*              [in out] The array of remote node guids already used to route
+*              the other lids of the same target port (if LMC > 0).
+*  
+*      p_num_used_nodes
+*              [in out] The number of remote nodes used for routing to
+*              the port.
+*
+* RETURN VALUE
+*      Returns the recommended port on which to route this LID.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_recommend_mcast_path
+* NAME
+*      osm_switch_recommend_mcast_path
+*
+* DESCRIPTION
+*      Returns the recommended port on which to route this LID.
+*
+* SYNOPSIS
+*/
+uint8_t
+osm_switch_recommend_mcast_path(
+       IN osm_switch_t* const p_sw,
+       IN const uint16_t lid_ho,
+       IN const uint16_t mlid_ho,
+       IN const boolean_t ignore_existing );
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to the switch object.
+*
+*      lid_ho
+*              [in] LID value (host order) for of the node for with to get
+*              the multicast path.
+*
+*      mlid_ho
+*              [in] MLID for the multicast group in question.
+*
+*      ignore_existing
+*              [in] Set to cause the switch to choose the optimal route
+*              regardless of existing paths.
+*              If false, the switch will choose an existing route if one exists,
+*              otherwise will choose the optimal route.
+*
+* RETURN VALUE
+*      Returns the recommended port on which to route this LID.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_fwd_tbl_size
+* NAME
+*      osm_switch_get_fwd_tbl_size
+*
+* DESCRIPTION
+*      Returns the number of entries available in the forwarding table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_switch_get_fwd_tbl_size(
+       IN const osm_switch_t* const p_sw )
+{
+       return( osm_fwd_tbl_get_size( &p_sw->fwd_tbl ) );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to the switch.
+*
+* RETURN VALUE
+*      Returns the number of entries available in the forwarding table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_mcast_fwd_tbl_size
+* NAME
+*      osm_switch_get_mcast_fwd_tbl_size
+*
+* DESCRIPTION
+*      Returns the number of entries available in the multicast forwarding table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_switch_get_mcast_fwd_tbl_size(
+       IN const osm_switch_t* const p_sw )
+{
+       return( cl_ntoh16( p_sw->switch_info.mcast_cap ) );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to the switch.
+*
+* RETURN VALUE
+*      Returns the number of entries available in the multicast forwarding table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_path_count_get
+* NAME
+*      osm_switch_path_count_get
+*
+* DESCRIPTION
+*      Returns the count of the number of paths going through this port.
+*
+* SYNOPSIS
+*/
+static inline uint32_t
+osm_switch_path_count_get(
+       IN const osm_switch_t* const p_sw,
+       IN const uint8_t port_num )
+{
+       return( osm_port_prof_path_count_get( &p_sw->p_prof[port_num] ) );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to the Switch object.
+*
+*      port_num
+*              [in] Port number for which to get path count.
+*
+* RETURN VALUE
+*      Returns the count of the number of paths going through this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_prepare_path_rebuild
+* NAME
+*      osm_switch_prepare_path_rebuild
+*
+* DESCRIPTION
+*      Prepares a switch to rebuild pathing information.
+*
+* SYNOPSIS
+*/
+void
+osm_switch_prepare_path_rebuild(
+       IN osm_switch_t* const p_sw );
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to the Switch object.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_mcast_tbl_ptr
+* NAME
+*      osm_switch_get_mcast_tbl_ptr
+*
+* DESCRIPTION
+*      Returns a pointer to the switch's multicast table.
+*
+* SYNOPSIS
+*/
+static inline osm_mcast_tbl_t*
+osm_switch_get_mcast_tbl_ptr(
+       IN const osm_switch_t* const p_sw )
+{
+       return( (osm_mcast_tbl_t*)&p_sw->mcast_tbl );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to the switch.
+*
+* RETURN VALUE
+*      Returns a pointer to the switch's multicast table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_is_in_mcast_tree
+* NAME
+*      osm_switch_is_in_mcast_tree
+*
+* DESCRIPTION
+*      Returns true if this switch already belongs in the tree for the specified
+*      multicast group.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_switch_is_in_mcast_tree(
+       IN const osm_switch_t* const p_sw,
+       IN const uint16_t mlid_ho )
+{
+       const osm_mcast_tbl_t* p_tbl;
+
+       p_tbl = &p_sw->mcast_tbl;
+       if( p_tbl )
+               return( osm_mcast_tbl_is_any_port( &p_sw->mcast_tbl, mlid_ho ) );
+       else
+               return( FALSE );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to the switch.
+*
+*      mlid_ho
+*              [in] MLID (host order) of the multicast tree to check.
+*
+* RETURN VALUE
+*      Returns true if this switch already belongs in the tree for the specified
+*      multicast group.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Node/osm_switch_discovery_count_get
+* NAME
+*      osm_switch_discovery_count_get
+*
+* DESCRIPTION
+*      Returns a pointer to the physical port object at the
+*      specified local port number.
+*
+* SYNOPSIS
+*/
+static inline uint32_t
+osm_switch_discovery_count_get(
+       IN const osm_switch_t* const p_switch )
+{
+       return( p_switch->discovery_count );
+}
+/*
+* PARAMETERS
+*      p_switch
+*              [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+*      Returns the discovery count for this node.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+/****f* OpenSM: Node/osm_switch_discovery_count_reset
+* NAME
+*      osm_switch_discovery_count_reset
+*
+* DESCRIPTION
+*      Resets the discovery count for this node to zero.
+*      This operation should be performed at the start of a sweep.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_switch_discovery_count_reset(
+       IN osm_switch_t* const p_switch )
+{
+       p_switch->discovery_count = 0;
+}
+/*
+* PARAMETERS
+*      p_switch
+*              [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+/****f* OpenSM: Node/osm_switch_discovery_count_inc
+* NAME
+*      osm_switch_discovery_count_inc
+*
+* DESCRIPTION
+*      Increments the discovery count for this node.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_switch_discovery_count_inc(
+       IN osm_switch_t* const p_switch )
+{
+       p_switch->discovery_count++;
+}
+/*
+* PARAMETERS
+*      p_switch
+*              [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      Node object
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SWITCH_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_trap_rcv.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_trap_rcv.h
new file mode 100644 (file)
index 0000000..68938b8
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_trap_rcv.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_trap_rcv_t.
+ *     This object represents the Trap Receiver object.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#ifndef _OSM_TRAP_RCV_H_
+#define _OSM_TRAP_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_event_wheel.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_resp.h>
+#include <opensm/osm_remote_sm.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_state_mgr.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/Trap Receiver
+* NAME
+*      Trap Receiver
+*
+* DESCRIPTION
+*      The Trap Receiver object encapsulates the information
+*      needed to receive the Trap attribute from a node.
+*
+*      The Trap Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Trap Receiver/osm_trap_rcv_t
+* NAME
+*      osm_trap_rcv_t
+*
+* DESCRIPTION
+*      Trap Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_trap_rcv
+{
+  osm_subn_t                           *p_subn;
+  osm_stats_t                          *p_stats;
+  osm_log_t                            *p_log;
+  osm_resp_t                           *p_resp;
+  osm_state_mgr_t                      *p_state_mgr;
+  cl_plock_t                           *p_lock;
+  cl_event_wheel_t                     trap_aging_tracker;
+} osm_trap_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_stats
+*              Pointer to the OpenSM statistics block.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_resp
+*              Pointer to the generic MAD responder object.
+*
+*      p_state_mgr
+*              Pointer to the State Manager object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+*      trap_aging_tracker
+*              An event wheel tracking erceived traps and their aging.
+*              Basically we can start a timer every time we receive a specific 
+*              trap and check to seee if not expired next time it is received.
+*
+* SEE ALSO
+*      Trap Receiver object
+*********/
+
+/****f* OpenSM: Trap Receiver/osm_trap_rcv_construct
+* NAME
+*      osm_trap_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a Trap Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_trap_rcv_construct(
+       IN osm_trap_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to a Trap Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_trap_rcv_init, osm_trap_rcv_destroy
+*
+*      Calling osm_trap_rcv_construct is a prerequisite to calling any other
+*      method except osm_trap_rcv_init.
+*
+* SEE ALSO
+*      Trap Receiver object, osm_trap_rcv_init,
+*      osm_trap_rcv_destroy
+*********/
+
+/****f* OpenSM: Trap Receiver/osm_trap_rcv_destroy
+* NAME
+*      osm_trap_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_trap_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_trap_rcv_destroy(
+       IN osm_trap_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Trap Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_trap_rcv_construct or osm_trap_rcv_init.
+*
+* SEE ALSO
+*      Trap Receiver object, osm_trap_rcv_construct,
+*      osm_trap_rcv_init
+*********/
+
+/****f* OpenSM: Trap Receiver/osm_trap_rcv_init
+* NAME
+*      osm_trap_rcv_init
+*
+* DESCRIPTION
+*      The osm_trap_rcv_init function initializes a
+*      Trap Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_trap_rcv_init(
+       IN osm_trap_rcv_t* const p_rcv,
+       IN osm_subn_t* const p_subn,
+       IN osm_stats_t* const p_stats,
+       IN osm_resp_t* const p_resp,
+       IN osm_log_t* const p_log,
+       IN osm_state_mgr_t* const p_state_mgr,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_trap_rcv_t object to initialize.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_stats
+*              [in] Pointer to the OpenSM statistics block.
+*
+*      p_resp
+*              [in] Pointer to the generic MAD Responder object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_state_mgr
+*              [in] Pointer to the State Manager object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the Trap Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Trap Receiver methods.
+*
+* SEE ALSO
+*      Trap Receiver object, osm_trap_rcv_construct,
+*      osm_trap_rcv_destroy
+*********/
+
+/****f* OpenSM: Trap Receiver/osm_trap_rcv_process
+* NAME
+*      osm_trap_rcv_process
+*
+* DESCRIPTION
+*      Process the Trap attribute.
+*
+* SYNOPSIS
+*/
+void osm_trap_rcv_process(
+       IN osm_trap_rcv_t* const p_rcv,
+       IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_rcv
+*              [in] Pointer to an osm_trap_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the node's Trap attribute.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the Trap processing was successful.
+*
+* NOTES
+*      This function processes a Trap attribute.
+*
+* SEE ALSO
+*      Trap Receiver, Trap Response Controller
+*********/
+
+/****f* OpenSM: Trap Receiver/osm_trap_rcv_aging_tracker_callback
+* NAME
+*      osm_trap_rcv_aging_tracker_callback
+*
+* DESCRIPTION
+*      Callback function called by the aging tracker mechanism.
+*
+* SYNOPSIS
+*/
+uint64_t
+osm_trap_rcv_aging_tracker_callback(
+  IN uint64_t key,
+  IN uint32_t num_regs,
+  IN void*    context );
+
+/*
+* PARAMETERS
+*      key
+*              [in] The key by which the event was inserted.
+*
+*      num_regs
+*              [in] The number of times the same event (key)  was registered.
+*
+*      context
+*              [in] Pointer to the context given in the registering of the event.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*      This function is called by the cl_event_wheel when the aging tracker
+*  event has ended.
+*
+* SEE ALSO
+*      Trap Receiver, Trap Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_TRAP_RCV_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_trap_rcv_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_trap_rcv_ctrl.h
new file mode 100644 (file)
index 0000000..e30da0d
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_trap_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_trap_rcv_ctrl_t.
+ *     This object represents a controller that receives the IBA Trap
+ *     attribute from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+#ifndef _OSM_TRAP_RCV_CTRL_H_
+#define _OSM_TRAP_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_trap_rcv.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/***** OpenSM/Trap Receive Controller
+* NAME
+*      Trap Receive Controller
+*
+* DESCRIPTION
+*      The Trap Receive Controller object encapsulates the information
+*      needed to receive the Trap attribute from a node.
+*
+*      The Trap Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Yael Kalka, Mellanox
+*
+*********/
+
+/****s* OpenSM: Trap Receive Controller/osm_trap_rcv_ctrl_t
+* NAME
+*      osm_trap_rcv_ctrl_t
+*
+* DESCRIPTION
+*      Trap Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_trap_rcv_ctrl
+{
+       osm_trap_rcv_t                          *p_rcv;
+       osm_log_t                                       *p_log;
+       cl_dispatcher_t                         *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_trap_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the Trap Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      Trap Receive Controller object
+*********/
+
+/****f* OpenSM: Trap Receive Controller/osm_trap_rcv_ctrl_construct
+* NAME
+*      osm_trap_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Trap Receive Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_trap_rcv_ctrl_construct(
+       IN osm_trap_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Trap Receive Controller object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_trap_rcv_ctrl_init, osm_trap_rcv_ctrl_destroy
+*
+*      Calling osm_trap_rcv_ctrl_construct is a prerequisite to calling any other
+*      method except osm_trap_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Trap Receive Controller object, osm_trap_rcv_ctrl_init,
+*      osm_trap_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: Trap Receive Controller/osm_trap_rcv_ctrl_destroy
+* NAME
+*      osm_trap_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_trap_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_trap_rcv_ctrl_destroy(
+       IN osm_trap_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Trap Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_trap_rcv_ctrl_construct or osm_trap_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Trap Receive Controller object, osm_trap_rcv_ctrl_construct,
+*      osm_trap_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Trap Receive Controller/osm_trap_rcv_ctrl_init
+* NAME
+*      osm_trap_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_trap_rcv_ctrl_init function initializes a
+*      Trap Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_trap_rcv_ctrl_init(
+       IN osm_trap_rcv_ctrl_t* const p_ctrl,
+       IN osm_trap_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_trap_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_trap_rcv_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the Trap Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Trap Receive Controller methods.
+*
+* SEE ALSO
+*      Trap Receive Controller object, osm_trap_rcv_ctrl_construct,
+*      osm_trap_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif         /* OSM_TRAP_RCV_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_ts_useraccess.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_ts_useraccess.h
new file mode 100644 (file)
index 0000000..57cfceb
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_ts_useraccess.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#include "ts_ib_useraccess.h"
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+typedef struct ib_user_mad_filter      osm_ts_user_mad_filter;
+typedef struct ib_set_port_info_ioctl  osm_ts_set_port_info_ioctl;
+typedef struct ib_get_port_info_ioctl  osm_ts_get_port_info_ioctl;
+typedef struct ib_gid_entry_ioctl      osm_ts_gid_entry_ioctl;
+
+END_C_DECLS
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_ucast_mgr.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_ucast_mgr.h
new file mode 100644 (file)
index 0000000..9ff81aa
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_ucast_mgr.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_ucast_mgr_t.
+ *     This object represents the Unicast Manager object.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_UCAST_MGR_H_
+#define _OSM_UCAST_MGR_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+#define OSM_UCAST_MGR_LIST_SIZE_MIN 256
+
+/****h* OpenSM/Unicast Manager
+* NAME
+*      Unicast Manager
+*
+* DESCRIPTION
+*      The Unicast Manager object encapsulates the information
+*      needed to control unicast LID forwarding on the subnet.
+*
+*      The Unicast Manager object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Unicast Manager/osm_ucast_mgr_t
+* NAME
+*      osm_ucast_mgr_t
+*
+* DESCRIPTION
+*      Unicast Manager structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_ucast_mgr
+{
+       osm_subn_t      *p_subn;
+       osm_req_t       *p_req;
+       osm_log_t       *p_log;
+       cl_plock_t      *p_lock;
+       boolean_t        any_change;
+       uint8_t         *lft_buf;
+} osm_ucast_mgr_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_req
+*              Pointer to the Requester object sending SMPs.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+*      any_change
+*              Initialized to FALSE at the beginning of the algorithm,
+*              set to TRUE by osm_ucast_mgr_set_fwd_table() if any mad 
+*              was sent.
+*
+*      lft_buf
+*              LFT buffer - used during LFT calculation/setup.
+*
+* SEE ALSO
+*      Unicast Manager object
+*********/
+
+/****f* OpenSM: Unicast Manager/osm_ucast_mgr_construct
+* NAME
+*      osm_ucast_mgr_construct
+*
+* DESCRIPTION
+*      This function constructs a Unicast Manager object.
+*
+* SYNOPSIS
+*/
+void
+osm_ucast_mgr_construct(
+       IN osm_ucast_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to a Unicast Manager object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows osm_ucast_mgr_destroy
+*
+*      Calling osm_ucast_mgr_construct is a prerequisite to calling any other
+*      method except osm_ucast_mgr_init.
+*
+* SEE ALSO
+*      Unicast Manager object, osm_ucast_mgr_init,
+*      osm_ucast_mgr_destroy
+*********/
+
+/****f* OpenSM: Unicast Manager/osm_ucast_mgr_destroy
+* NAME
+*      osm_ucast_mgr_destroy
+*
+* DESCRIPTION
+*      The osm_ucast_mgr_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_ucast_mgr_destroy(
+       IN osm_ucast_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      Unicast Manager object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_ucast_mgr_construct or osm_ucast_mgr_init.
+*
+* SEE ALSO
+*      Unicast Manager object, osm_ucast_mgr_construct,
+*      osm_ucast_mgr_init
+*********/
+
+/****f* OpenSM: Unicast Manager/osm_ucast_mgr_init
+* NAME
+*      osm_ucast_mgr_init
+*
+* DESCRIPTION
+*      The osm_ucast_mgr_init function initializes a
+*      Unicast Manager object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_ucast_mgr_init(
+       IN osm_ucast_mgr_t* const p_mgr,
+       IN osm_req_t* const p_req,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to an osm_ucast_mgr_t object to initialize.
+*
+*      p_req
+*              [in] Pointer to the attribute Requester object.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the Unicast Manager object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Unicast Manager methods.
+*
+* SEE ALSO
+*      Unicast Manager object, osm_ucast_mgr_construct,
+*      osm_ucast_mgr_destroy
+*********/
+
+/****f* OpenSM: Unicast Manager/osm_ucast_mgr_set_fwd_table
+* NAME
+*      osm_ucast_mgr_set_fwd_table
+*
+* DESCRIPTION
+*      Setup forwarding table for the switch (from prepared lft_buf).
+*
+* SYNOPSIS
+*/
+void
+osm_ucast_mgr_set_fwd_table(
+       IN osm_ucast_mgr_t* const p_mgr,
+       IN osm_switch_t* const p_sw );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to an osm_ucast_mgr_t object.
+*
+*      p_mgr
+*              [in] Pointer to an osm_switch_t object.
+*
+* SEE ALSO
+*      Unicast Manager
+*********/
+
+/****f* OpenSM: Unicast Manager/osm_ucast_mgr_build_lid_matrices
+* NAME
+*      osm_ucast_mgr_build_lid_matrices
+*
+* DESCRIPTION
+*      Build switches's lid matrices.
+*
+* SYNOPSIS
+*/
+void
+osm_ucast_mgr_build_lid_matrices(
+       IN osm_ucast_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to an osm_ucast_mgr_t object.
+*
+* NOTES
+*      This function processes the subnet, configuring switches'
+*      min hops tables (aka lid matrices).
+*
+* SEE ALSO
+*      Unicast Manager
+*********/
+
+/****f* OpenSM: Unicast Manager/osm_ucast_mgr_process
+* NAME
+*      osm_ucast_mgr_process
+*
+* DESCRIPTION
+*      Process and configure the subnet's unicast forwarding tables.
+*
+* SYNOPSIS
+*/
+osm_signal_t
+osm_ucast_mgr_process(
+       IN osm_ucast_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to an osm_ucast_mgr_t object.
+*
+* RETURN VALUES
+*      Returns the appropriate signal to the caller:
+*              OSM_SIGNAL_DONE - operation is complete
+*              OSM_SIGNAL_DONE_PENDING - local operations are complete, but
+*                      transactions are still pending on the wire.
+*
+* NOTES
+*      This function processes the subnet, configuring switch
+*      unicast forwarding tables.
+*
+* SEE ALSO
+*      Unicast Manager, Node Info Response Controller
+*********/
+END_C_DECLS
+
+#endif /* _OSM_UCAST_MGR_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_umadt.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_umadt.h
new file mode 100644 (file)
index 0000000..c0bfed8
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_umadt.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_mad_wrapper_t.
+ *     This object represents the context wrapper for OpenSM MAD processing.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_UMADT_h_
+#define _OSM_UMADT_h_
+
+#include "iba/ib_types.h"
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_log.h>
+#include "umadt.h"
+#include "ibt.h"
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+typedef struct _umadt_obj_t{
+       void*           umadt_handle;
+       UMADT_INTERFACE uMadtInterface;
+       IBT_INTERFACE   IbtInterface;
+       boolean         init_done;
+       cl_spinlock_t   register_lock;
+       cl_qlist_t      register_list;
+       osm_log_t               *p_log;
+       uint32_t                timeout;
+
+}umadt_obj_t;
+/*********/
+
+/****s* OpenSM: Umadt MAD Wrapper/osm_bind_info
+* NAME
+*      osm_bind_info
+*
+* DESCRIPTION
+*      Context needed for processing individual MADs
+*
+* SYNOPSIS
+*/
+
+typedef struct _mad_bind_info_t{
+    cl_list_item_t              list_item;
+       umadt_obj_t                                     *p_umadt_obj;
+    osm_mad_pool_t              *p_mad_pool;
+    osm_vend_mad_recv_callback_t    mad_recv_callback;
+    void                        *client_context;
+    cl_thread_t                 recv_processor_thread;
+       cl_spinlock_t                           trans_ctxt_lock;        
+       cl_qlist_t                                      trans_ctxt_list;        
+       cl_timer_t                                      timeout_timer;
+       cl_spinlock_t                           timeout_list_lock;
+       cl_qlist_t                                      timeout_list;   
+    RegisterClassStruct         umadt_reg_class;    
+    MADT_HANDLE                 umadt_handle;       /* Umadt type */
+
+}mad_bind_info_t;
+
+typedef struct _trans_context_t {
+       cl_list_item_t  list_item;
+       uint64_t                trans_id;
+        uint64_t               sent_time;      /* micro secs */
+       void*                   context;
+} trans_context_t;
+
+/*
+* FIELDS
+*      list_item
+*              List linkage for pools and lists.  MUST BE FIRST MEMBER!
+*
+*      p_mad_pool
+*              Pointer to the MAD pool to be used by mads with this bind handle.       
+*
+*      mad_recv_callback
+*              Callback function called by the mad receive processor.
+*
+*      client_context
+*              context to be passed to the receive callback.
+*
+*      recv_processor_thread
+*              Thread structure for the receive processor thread.
+*
+*      umadt_reg_class
+*              Umadt register class struct used to register with Umadt.
+*
+*      umadt_handle
+*              Umadt returns this handle from a registration call. The transport layer
+*              uses this handle to talk to Umadt.
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /*_OSM_UMADT_h_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_version.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_version.h
new file mode 100644 (file)
index 0000000..4b1d03c
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_version.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_VERSION_H_
+#define _OSM_VERSION_H_
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****s* OpenSM: Base/OSM_VERSION
+* NAME
+*      OSM_VERSION
+*
+* DESCRIPTION
+*      The version string for OpenSM 
+*
+* SYNOPSIS
+*/
+#define OSM_VERSION "OpenSM Rev:openib-3.0.0"
+/********/
+
+END_C_DECLS
+
+#endif /* _OSM_VERSION_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_vl15intf.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_vl15intf.h
new file mode 100644 (file)
index 0000000..0a8b177
--- /dev/null
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_vl15intf.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_vl15_t.
+ *     This object represents an IBA subnet.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#ifndef _OSM_VL15INTF_H_
+#define _OSM_VL15INTF_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_spinlock.h>
+#include <complib/cl_event.h>
+#include <complib/cl_thread.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.h>
+#include <vendor/osm_vendor.h>
+#include <opensm/osm_subnet.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/VL15
+* NAME
+*      VL15
+*
+* DESCRIPTION
+*      The VL15 object encapsulates the information needed by the
+*      OpenSM to instantiate the VL15 interface.  The OpenSM allocates
+*      one VL15 object per subnet.
+*
+*      The VL15 object transmits MADs to the wire at a throttled rate,
+*      so as to not overload the VL15 buffering of subnet components.
+*      OpenSM modules may post VL15 MADs to the VL15 interface as fast
+*      as possible.
+*
+*      The VL15 object is thread safe.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+/****d* OpenSM: SM/osm_vl15_state_t
+* NAME
+*      osm_vl15_state_t
+*
+* DESCRIPTION
+*      Enumerates the possible states of SM object.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_vl15_state
+{
+       OSM_VL15_STATE_INIT = 0,
+       OSM_VL15_STATE_READY
+
+} osm_vl15_state_t;
+/***********/
+
+/****s* OpenSM: VL15/osm_vl15_t
+* NAME
+*      osm_vl15_t
+*
+* DESCRIPTION
+*      VL15 structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_vl15
+{
+       osm_thread_state_t                              thread_state;
+       osm_vl15_state_t                                state;
+       uint32_t                                                max_wire_smps;
+       cl_event_t                                              signal;
+       cl_thread_t                                             poller;
+       cl_qlist_t                                              rfifo;
+       cl_qlist_t                                              ufifo;
+       cl_spinlock_t                                   lock;
+       osm_vendor_t                                    *p_vend;
+       osm_log_t                                               *p_log;
+       osm_stats_t                                             *p_stats;
+       osm_subn_t                                              *p_subn;
+       cl_disp_reg_handle_t                    h_disp;
+       cl_plock_t                                              *p_lock;
+
+} osm_vl15_t;
+/*
+* FIELDS
+*      thread_state
+*              Tracks the thread state of the poller thread.
+*
+*      state
+*              Tracks the state of the VL15 interface itself.
+*
+*      max_wire_smps
+*              Maximum number of VL15 MADs allowed on the wire at one time.
+*
+*      signal
+*              Event on which the poller sleeps.
+*
+*      rfifo
+*              First-in First-out queue for outbound VL15 MADs for which
+*              a response is expected, aka the "response fifo"
+*
+*      ufifo
+*              First-in First-out queue for outbound VL15 MADs for which
+*              no response is expected, aka the "unicast fifo".
+*
+*      poller
+*              Worker thread pool that services the fifo to transmit VL15 MADs
+*
+*      lock
+*              Spinlock guarding the FIFO.
+*
+*      p_vend
+*              Pointer to the vendor transport object.
+*              
+*      p_log
+*              Pointer to the log object.
+*
+*      p_stats
+*              Pointer to the OpenSM statistics block.
+*
+*  p_subn
+*     Pointer to the Subnet object for this subnet.
+*
+*  h_disp
+*    Handle returned from dispatcher registration.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+* SEE ALSO
+*      VL15 object
+*********/
+
+/****f* OpenSM: VL15/osm_vl15_construct
+* NAME
+*      osm_vl15_construct
+*
+* DESCRIPTION
+*      This function constructs an VL15 object.
+*
+* SYNOPSIS
+*/
+void
+osm_vl15_construct(
+       IN osm_vl15_t* const p_vl15 );
+/*
+* PARAMETERS
+*      p_vl15
+*              [in] Pointer to a VL15 object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_vl15_init, osm_vl15_destroy, and osm_vl15_is_inited.
+*
+*      Calling osm_vl15_construct is a prerequisite to calling any other
+*      method except osm_vl15_init.
+*
+* SEE ALSO
+*      VL15 object, osm_vl15_init, osm_vl15_destroy, osm_vl15_is_inited
+*********/
+
+/****f* OpenSM: VL15/osm_vl15_destroy
+* NAME
+*      osm_vl15_destroy
+*
+* DESCRIPTION
+*      The osm_vl15_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_vl15_destroy(
+       IN osm_vl15_t* const p_vl15,
+   IN struct _osm_mad_pool *p_pool);
+/*
+* PARAMETERS
+*      p_vl15
+*              [in] Pointer to a VL15 object to destroy.
+*
+*  p_pool
+*     [in] The pointer to the mad pool to return outstanding mads to
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified VL15 object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to osm_vl15_construct or
+*      osm_vl15_init.
+*
+* SEE ALSO
+*      VL15 object, osm_vl15_construct, osm_vl15_init
+*********/
+
+/*
+       Initialization.
+       Rate specifies the minimum number of microseconds between transmissions
+       on VL15.
+*/
+/****f* OpenSM: VL15/osm_vl15_init
+* NAME
+*      osm_vl15_init
+*
+* DESCRIPTION
+*      The osm_vl15_init function initializes a VL15 object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_vl15_init(
+       IN osm_vl15_t* const p_vl15,
+       IN osm_vendor_t* const p_vend,
+       IN osm_log_t* const p_log,
+       IN osm_stats_t* const p_stats,
+       IN const int32_t max_wire_smps,
+       IN osm_subn_t* const p_subn,
+       IN cl_dispatcher_t* const p_disp,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_vl15
+*              [in] Pointer to an osm_vl15_t object to initialize.
+*
+*      p_vend
+*              [in] Pointer to the vendor transport object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_stats
+*              [in] Pointer to the OpenSM stastics block.
+*
+*      max_wire_smps
+*              [in] Maximum number of MADs allowed on the wire at one time.
+*
+*  p_subn
+*     [in] Pointer to the subnet object.
+*
+*  p_disp
+*     [in] Pointer to the dispatcher object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the VL15 object was initialized successfully.
+*
+* NOTES
+*      Allows calling other VL15 methods.
+*
+* SEE ALSO
+*      VL15 object, osm_vl15_construct, osm_vl15_destroy,
+*      osm_vl15_is_inited
+*********/
+
+/****f* OpenSM: VL15/osm_vl15_post
+* NAME
+*      osm_vl15_post
+*
+* DESCRIPTION
+*      Posts a MAD to the VL15 interface for transmission.
+*
+* SYNOPSIS
+*/
+void
+osm_vl15_post(
+       IN osm_vl15_t* const p_vl15,
+       IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_vl15
+*              [in] Pointer to an osm_vl15_t object.
+*
+*      p_madw
+*              [in] Pointer to a MAD wrapper structure containing the MAD.
+*
+* RETURN VALUES
+*      This function does not return a value.
+*
+* NOTES
+*      The osm_vl15_construct or osm_vl15_init must be called before using
+*      this function.
+*
+* SEE ALSO
+*      VL15 object, osm_vl15_construct, osm_vl15_init
+*********/
+
+/****f* OpenSM: VL15/osm_vl15_poll
+* NAME
+*      osm_vl15_poll
+*
+* DESCRIPTION
+*      Causes the VL15 Interface to consider sending another QP0 MAD.
+*
+* SYNOPSIS
+*/
+void
+osm_vl15_poll(
+       IN osm_vl15_t* const p_vl );
+/*
+* PARAMETERS
+*      p_vl15
+*              [in] Pointer to an osm_vl15_t object.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*      This function signals the VL15 that it may be possible to send
+*      a SMP.  This function checks three criteria before sending a SMP:
+*      1) The VL15 worker is IDLE
+*      2) There are no QP0 SMPs currently outstanding
+*      3) There is something on the VL15 FIFO to send
+*
+* SEE ALSO
+*      VL15 object, osm_vl15_construct, osm_vl15_init
+*********/
+
+/****f* OpenSM: VL15/osm_vl15_shutdown
+* NAME
+*      osm_vl15_shutdown
+*
+* DESCRIPTION
+*      Cleanup all outstanding MADs on both fifo's.
+*  This is required to return all outstanding MAD resources.
+*
+* SYNOPSIS
+*/
+void
+osm_vl15_shutdown(
+       IN osm_vl15_t* const p_vl,
+       IN osm_mad_pool_t* const p_mad_pool);
+/*
+* PARAMETERS
+*      p_vl15
+*              [in] Pointer to an osm_vl15_t object.
+*
+*  p_mad_pool
+*     [in] The MAD pool owning the mads.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      VL15 object, osm_vl15_construct, osm_vl15_init
+*********/
+
+END_C_DECLS
+
+#endif         /* _OSM_VL15INTF_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_vl_arb_rcv.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_vl_arb_rcv.h
new file mode 100644 (file)
index 0000000..d32c105
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_vl_arb_rcv.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_vla_rcv_t.
+ *     This object represents the VL Arbitration Receiver object.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#ifndef _OSM_VLA_RCV_H_
+#define _OSM_VLA_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_log.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/VL Arbitration Receiver
+* NAME
+*      VL Arbitration Receiver
+*
+* DESCRIPTION
+*      The VL Arbitration Receiver object encapsulates the information
+*      needed to set or get the vl arbitration attribute from a port.
+*
+*      The VL Arbitration Receiver object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: VL Arbitration Receiver/osm_vla_rcv_t
+* NAME
+*      osm_vla_rcv_t
+*
+* DESCRIPTION
+*      VL Arbitration Receiver structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_vla_rcv
+{
+       osm_subn_t                                      *p_subn;
+       osm_req_t                                       *p_req;
+       osm_log_t                                       *p_log;
+       cl_plock_t                                      *p_lock;
+
+} osm_vla_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_req
+*              Pointer to the generic attribute request object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+* SEE ALSO
+*      VL Arbitration Receiver object
+*********/
+
+/****f* OpenSM: VL Arbitration Receiver/osm_vla_rcv_construct
+* NAME
+*      osm_vla_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a VL Arbitration Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_vla_rcv_construct(
+       IN osm_vla_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a VL Arbitration Receiver object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_vla_rcv_destroy
+*
+*      Calling osm_vla_rcv_construct is a prerequisite to calling any other
+*      method except osm_vla_rcv_init.
+*
+* SEE ALSO
+*      VL Arbitration Receiver object, osm_vla_rcv_init,
+*      osm_vla_rcv_destroy
+*********/
+
+/****f* OpenSM: VL Arbitration Receiver/osm_vla_rcv_destroy
+* NAME
+*      osm_vla_rcv_destroy
+*
+* DESCRIPTION
+*      The osm_vla_rcv_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_vla_rcv_destroy(
+       IN osm_vla_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      VL Arbitration Receiver object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_vla_rcv_construct or osm_vla_rcv_init.
+*
+* SEE ALSO
+*      VL Arbitration Receiver object, osm_vla_rcv_construct,
+*      osm_vla_rcv_init
+*********/
+
+/****f* OpenSM: VL Arbitration Receiver/osm_vla_rcv_init
+* NAME
+*      osm_vla_rcv_init
+*
+* DESCRIPTION
+*      The osm_vla_rcv_init function initializes a
+*      VL Arbitration Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_vla_rcv_init(
+       IN osm_vla_rcv_t* const p_ctrl,
+       IN osm_req_t* const p_req,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_vla_rcv_t object to initialize.
+*
+*      p_req
+*              [in] Pointer to an osm_req_t object.
+*
+*      p_subn
+*              [in] Pointer to the Subnet object for this subnet.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the VL Arbitration Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other VL Arbitration Receiver methods.
+*
+* SEE ALSO
+*      VL Arbitration Receiver object, osm_vla_rcv_construct,
+*      osm_vla_rcv_destroy
+*********/
+
+/****f* OpenSM: VL Arbitration Receiver/osm_vla_rcv_process
+* NAME
+*      osm_vla_rcv_process
+*
+* DESCRIPTION
+*      Process the vl arbitration attribute.
+*
+* SYNOPSIS
+*/
+void osm_vla_rcv_process(
+       IN const osm_vla_rcv_t* const p_ctrl,
+       IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_vla_rcv_t object.
+*
+*      p_madw
+*              [in] Pointer to the MAD Wrapper containing the MAD
+*              that contains the node's SLtoVL attribute.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the SLtoVL processing was successful.
+*
+* NOTES
+*      This function processes a SLtoVL attribute.
+*
+* SEE ALSO
+*      VL Arbitration Receiver, VL Arbitration Response Controller
+*********/
+       
+END_C_DECLS
+
+#endif /* _OSM_VLA_RCV_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_vl_arb_rcv_ctrl.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/osm_vl_arb_rcv_ctrl.h
new file mode 100644 (file)
index 0000000..7b66a40
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_vl_arb_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_vla_rcv_ctrl_t.
+ *     This object represents a controller that set or get resp the 
+ * IBA VL Arbitration Table attribute from a port.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#ifndef _OSM_VLA_RCV_CTRL_H_
+#define _OSM_VLA_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_vl_arb_rcv.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****h* OpenSM/VL Arbitration Table Receive Controller
+* NAME
+*      VL Arbitration Receive Controller
+*
+* DESCRIPTION
+*      The VL Arbitration Receive Controller object encapsulates
+*      the information needed to get or set VL Arbitration of a port.
+*
+*      The VL Arbitration Receive Controller object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: VL Arbitration Receive Controller/osm_vla_rcv_ctrl_t
+* NAME
+*      osm_vla_rcv_ctrl_t
+*
+* DESCRIPTION
+*      VL Arbitration Receive Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_vla_rcv_ctrl
+{
+       osm_vla_rcv_t                   *p_rcv;
+       osm_log_t                       *p_log;
+       cl_dispatcher_t                 *p_disp;
+       cl_disp_reg_handle_t            h_disp;
+
+} osm_vla_rcv_ctrl_t;
+/*
+* FIELDS
+*      p_rcv
+*              Pointer to the VL Arbitration Receiver object.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+*      h_disp
+*              Handle returned from dispatcher registration.
+*
+* SEE ALSO
+*      VL Arbitration Receive Controller object
+*      VL Arbitration Receiver object
+*********/
+
+/****f* OpenSM: VL Arbitration Receive Controller/osm_vla_rcv_ctrl_construct
+* NAME
+*      osm_vla_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a VL Arbitration Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_vla_rcv_ctrl_construct(
+       IN osm_vla_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a VL Arbitration Receive Controller
+*              object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_vla_rcv_ctrl_init, osm_vla_rcv_ctrl_destroy,
+*      and osm_vla_rcv_ctrl_is_inited.
+*
+*      Calling osm_vla_rcv_ctrl_construct is a prerequisite to calling any other
+*      method except osm_vla_rcv_ctrl_init.
+*
+* SEE ALSO
+*      VL Arbitration Receive Controller object, osm_vla_rcv_ctrl_init,
+*      osm_vla_rcv_ctrl_destroy, osm_vla_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: VL Arbitration Receive Controller/osm_vla_rcv_ctrl_destroy
+* NAME
+*      osm_vla_rcv_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_vla_rcv_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_vla_rcv_ctrl_destroy(
+       IN osm_vla_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified
+*      VL Arbitration Receive Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_vla_rcv_ctrl_construct or osm_vla_rcv_ctrl_init.
+*
+* SEE ALSO
+*      VL Arbitration Receive Controller object, osm_vla_rcv_ctrl_construct,
+*      osm_vla_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: VL Arbitration Receive Controller/osm_vla_rcv_ctrl_init
+* NAME
+*      osm_vla_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_vla_rcv_ctrl_init function initializes a
+*      VL Arbitration Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_vla_rcv_ctrl_init(
+       IN osm_vla_rcv_ctrl_t* const p_ctrl,
+       IN osm_vla_rcv_t* const p_rcv,
+       IN osm_log_t* const p_log,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_vla_rcv_ctrl_t object to initialize.
+*
+*      p_rcv
+*              [in] Pointer to an osm_vla_rcv_t object.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the VL Arbitration Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other VL Arbitration Receive Controller methods.
+*
+* SEE ALSO
+*      VL Arbitration Receive Controller object, osm_vla_rcv_ctrl_construct,
+*      osm_vla_rcv_ctrl_destroy, osm_vla_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: VL Arbitration Receive Controller/osm_vla_rcv_ctrl_is_inited
+* NAME
+*      osm_vla_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+*      Indicates if the object has been initialized with osm_vla_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_vla_rcv_ctrl_is_inited(
+       IN const osm_vla_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_vla_rcv_ctrl_t object.
+*
+* RETURN VALUES
+*      TRUE if the object was initialized successfully,
+*      FALSE otherwise.
+*
+* NOTES
+*      The osm_vla_rcv_ctrl_construct or osm_vla_rcv_ctrl_init must be
+*      called before using this function.
+*
+* SEE ALSO
+*      VL Arbitration Receive Controller object, osm_vla_rcv_ctrl_construct,
+*      osm_vla_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_VLA_RCV_CTRL_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/st.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/opensm/st.h
new file mode 100644 (file)
index 0000000..b715a06
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: st.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/* @(#) st.h 5.1 89/12/14 */
+
+#ifndef ST_INCLUDED
+#define ST_INCLUDED
+
+#include <stdlib.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+#if (__WORDSIZE == 64) || defined (_WIN64)
+#define st_ptr_t unsigned long long
+#else
+#define st_ptr_t unsigned long
+#endif
+
+typedef st_ptr_t st_data_t;
+
+#define ST_DATA_T_DEFINED
+
+typedef struct st_table st_table;
+
+struct st_hash_type {
+  int (*compare)(void *, void *);
+  st_ptr_t (*hash)(void *);
+};
+
+struct st_table {
+    struct st_hash_type *type;
+    int num_bins;
+    int num_entries;
+    struct st_table_entry **bins;
+};
+
+#define st_is_member(table,key) st_lookup(table,key,(st_data_t *)0)
+
+enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE};
+
+st_table *st_init_table(struct st_hash_type *);
+st_table *st_init_table_with_size(struct st_hash_type *, size_t);
+st_table *st_init_numtable(void);
+st_table *st_init_numtable_with_size(size_t);
+st_table *st_init_strtable(void);
+st_table *st_init_strtable_with_size(size_t);
+int st_delete(st_table *, st_data_t *, st_data_t *);
+int st_delete_safe(st_table *, st_data_t *, st_data_t *, st_data_t);
+int st_insert(st_table *, st_data_t, st_data_t);
+int st_lookup(st_table *, st_data_t, st_data_t *);
+void st_foreach(st_table *, int (*)(st_data_t key, st_data_t val, st_data_t arg), st_data_t);
+void st_add_direct(st_table *, st_data_t, st_data_t);
+void st_free_table(st_table *);
+void st_cleanup_safe(st_table *, st_data_t);
+st_table *st_copy(st_table *);
+
+#define ST_NUMCMP      ((int (*)()) 0)
+#define ST_NUMHASH     ((int (*)()) -2)
+
+#define st_numcmp      ST_NUMCMP
+#define st_numhash     ST_NUMHASH
+
+/* int st_strhash(void); */
+
+END_C_DECLS
+
+#endif /* ST_INCLUDED */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/unistd.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/unistd.h
new file mode 100644 (file)
index 0000000..08fb537
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_base.h 1689 2006-09-12 20:55:47Z eitan $
+ */
+
+
+
+/*
+ * Abstract:
+ *     Work around for cmpatibility mode with Linux.
+ *
+ */
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor.h
new file mode 100644 (file)
index 0000000..7745272
--- /dev/null
@@ -0,0 +1,78 @@
+/*\r
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.\r
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.\r
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: osm_vendor.h 1923 2009-01-30 22:20:39Z stansmith $\r
+ */\r
+\r
+\r
+\r
+/*\r
+ * Abstract:\r
+ *     Include file used by OpenSM to pull in the correct vendor file.\r
+ *\r
+ * Environment:\r
+ *     Linux User Mode\r
+ *\r
+ * $Revision: 1.6 $\r
+ */\r
+\r
+/*\r
+  this is the generic include file which includes\r
+  the proper vendor specific file\r
+*/\r
+#include <vendor/osm_vendor_select.h>\r
+\r
+#if defined( OSM_VENDOR_INTF_TEST )\r
+#include <vendor/osm_vendor_test.h>\r
+#elif defined( OSM_VENDOR_INTF_UMADT )\r
+#include <vendor/osm_vendor_umadt.h>\r
+#elif defined( OSM_VENDOR_INTF_MTL )\r
+/* HACK - I do not know how to prevent complib from loading kernel H files */\r
+#undef __init\r
+#include <vendor/osm_vendor_mlx.h>\r
+#elif defined( OSM_VENDOR_INTF_TS )\r
+#undef __init\r
+#include <vendor/osm_vendor_mlx.h>\r
+#elif defined( OSM_VENDOR_INTF_ANAFA )\r
+#undef __init\r
+#include <vendor/osm_vendor_mlx.h>\r
+#elif defined( OSM_VENDOR_INTF_SIM )\r
+#undef __init\r
+#include <vendor/osm_vendor_mlx.h>\r
+#elif defined( OSM_VENDOR_INTF_OPENIB )\r
+#include <vendor/osm_vendor_ibumad.h>\r
+#elif defined( OSM_VENDOR_INTF_AL )\r
+#include <vendor/osm_vendor_al.h>\r
+#elif\r
+#error No MAD Interface selected!\r
+#error Choose an interface in osm_vendor_select.h\r
+#endif\r
+\r
+\r
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_al.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_al.h
new file mode 100644 (file)
index 0000000..32ee0f4
--- /dev/null
@@ -0,0 +1,372 @@
+/*\r
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.\r
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.\r
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.\r
+ * Portions Copyright (c) 2008 Microsoft Corporation.  All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: osm_vendor_al.h 1375 2008-07-13 08:55:53Z leonidk $\r
+ */\r
+\r
+\r
+\r
+/*\r
+ * Abstract:\r
+ *     Declaration of osm_mad_wrapper_t.\r
+ *     This object represents the context wrapper for OpenSM MAD processing.\r
+ *     This object is part of the OpenSM family of objects.\r
+ *\r
+ * Environment:\r
+ *     Linux User Mode\r
+ *\r
+ * $Revision: 1.4 $\r
+ */\r
+\r
+\r
+\r
+\r
+#ifndef _OSM_VENDOR_AL_H_\r
+#define _OSM_VENDOR_AL_H_\r
+\r
+#include <iba/ib_types.h>\r
+#include <iba/ib_al.h>\r
+#include <complib/cl_qlist.h>\r
+#include <complib/cl_thread.h>\r
+#include <opensm/osm_base.h>\r
+#include <opensm/osm_log.h>\r
+\r
+#ifdef __cplusplus\r
+#  define BEGIN_C_DECLS extern "C" {\r
+#  define END_C_DECLS   }\r
+#else /* !__cplusplus */\r
+#  define BEGIN_C_DECLS\r
+#  define END_C_DECLS\r
+#endif /* __cplusplus */\r
+\r
+BEGIN_C_DECLS\r
+\r
+/****h* OpenSM/Vendor AL\r
+* NAME\r
+*      Vendor AL\r
+*\r
+* DESCRIPTION\r
+*\r
+*      The Vendor AL object is thread safe.\r
+*\r
+*      This object should be treated as opaque and should be\r
+*      manipulated only through the provided functions.\r
+*\r
+*      Enable various hacks to compensate for bugs in external code...\r
+*\r
+*\r
+* AUTHOR\r
+*      \r
+*\r
+*********/\r
+\r
+\r
+\r
+/****h* OpenSM/Vendor Access Layer (AL)\r
+* NAME\r
+*      Vendor AL\r
+*\r
+* DESCRIPTION\r
+*      This file is the vendor specific file for the AL Infiniband API.\r
+*\r
+* AUTHOR\r
+*      Steve King, Intel\r
+*\r
+*********/\r
+\r
+#define OSM_AL_SQ_SGE 256\r
+#define OSM_AL_RQ_SGE 256\r
+#define OSM_DEFAULT_RETRY_COUNT 3\r
+\r
+/* AL supports RMPP */\r
+#define VENDOR_RMPP_SUPPORT 1\r
+\r
+/****s* OpenSM: Vendor AL/osm_ca_info_t\r
+* NAME\r
+*   osm_ca_info_t\r
+*\r
+* DESCRIPTION\r
+*      Structure containing information about local Channle Adapters.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _osm_ca_info\r
+{\r
+       ib_net64_t                              guid;\r
+       size_t                                  attr_size;\r
+       ib_ca_attr_t                    *p_attr;\r
+\r
+} osm_ca_info_t;\r
+/*\r
+* FIELDS\r
+*      guid\r
+*              Node GUID of the local CA.\r
+*\r
+*      attr_size\r
+*              Size of the CA attributes for this CA.\r
+*\r
+*      p_attr\r
+*              Pointer to dynamicly allocated CA Attribute structure.\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* OpenSM: CA Info/osm_ca_info_get_num_ports\r
+* NAME\r
+*      osm_ca_info_get_num_ports\r
+*\r
+* DESCRIPTION\r
+*      Returns the number of ports owned by this CA.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t\r
+osm_ca_info_get_num_ports(\r
+       IN const osm_ca_info_t* const p_ca_info )\r
+{\r
+       return( p_ca_info->p_attr->num_ports );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_ca_info\r
+*              [in] Pointer to a CA Info object.\r
+*\r
+* RETURN VALUE\r
+*      Returns the number of ports owned by this CA.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* OpenSM: CA Info/osm_ca_info_get_port_guid\r
+* NAME\r
+*      osm_ca_info_get_port_guid\r
+*\r
+* DESCRIPTION\r
+*      Returns the port GUID of the specified port owned by this CA.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net64_t\r
+osm_ca_info_get_port_guid(\r
+       IN const osm_ca_info_t* const p_ca_info,\r
+       IN const uint8_t index )\r
+{\r
+       return( p_ca_info->p_attr->p_port_attr[index].port_guid );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_ca_info\r
+*              [in] Pointer to a CA Info object.\r
+*\r
+*      index\r
+*              [in] Port "index" for which to retrieve the port GUID.\r
+*              The index is the offset into the ca's internal array\r
+*              of port attributes.\r
+*\r
+* RETURN VALUE\r
+*      Returns the port GUID of the specified port owned by this CA.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* OpenSM: CA Info/osm_ca_info_get_port_num\r
+* NAME\r
+*      osm_ca_info_get_port_num\r
+*\r
+* DESCRIPTION\r
+*      Returns the port number of the specified port owned by this CA.\r
+*      Port numbers start with 1 for HCA's.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t\r
+osm_ca_info_get_port_num(\r
+       IN const osm_ca_info_t* const p_ca_info,\r
+       IN const uint8_t index )\r
+{\r
+       return( p_ca_info->p_attr->p_port_attr[index].port_num );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_ca_info\r
+*              [in] Pointer to a CA Info object.\r
+*\r
+*      index\r
+*              [in] Port "index" for which to retrieve the port GUID.\r
+*              The index is the offset into the ca's internal array\r
+*              of port attributes.\r
+*\r
+* RETURN VALUE\r
+*      Returns the port GUID of the specified port owned by this CA.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* OpenSM: CA Info/osm_ca_info_get_ca_guid\r
+* NAME\r
+*      osm_ca_info_get_ca_guid\r
+*\r
+* DESCRIPTION\r
+*      Returns the GUID of the specified CA.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net64_t\r
+osm_ca_info_get_ca_guid(\r
+       IN const osm_ca_info_t* const p_ca_info )\r
+{\r
+       return( p_ca_info->p_attr->ca_guid );\r
+}\r
+/*\r
+* PARAMETERS\r
+*      p_ca_info\r
+*              [in] Pointer to a CA Info object.\r
+*\r
+* RETURN VALUE\r
+*      Returns the GUID of the specified CA.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****s* OpenSM: Vendor AL/osm_bind_handle_t\r
+* NAME\r
+*   osm_bind_handle_t\r
+*\r
+* DESCRIPTION\r
+*      handle returned by the vendor transport bind call.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef        struct _osm_vendor\r
+{\r
+       ib_al_handle_t          h_al;\r
+       osm_log_t                       *p_log;\r
+       uint32_t                        ca_count;\r
+       osm_ca_info_t           *p_ca_info;\r
+       uint32_t                        timeout;\r
+       ib_ca_handle_t          h_ca;\r
+       ib_pd_handle_t          h_pd;\r
+\r
+} osm_vendor_t;\r
+/*\r
+* FIELDS\r
+*      h_al\r
+*              Handle returned by AL open call (ib_open_al).   \r
+*\r
+*      p_log\r
+*              Pointer to the log object.\r
+*\r
+*      ca_count\r
+*              Number of CA's in the array pointed to by p_ca_info.\r
+*\r
+*      p_ca_info\r
+*              Pointer to dynamically allocated array of CA info objects.\r
+*\r
+*      h_pool\r
+*              MAD Pool handle returned by ib_create_mad_pool at init time.\r
+*\r
+*      timeout\r
+*              Transaction timeout time in milliseconds.\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+\r
+#define OSM_BIND_INVALID_HANDLE 0\r
+\r
+\r
+/****s* OpenSM: Vendor AL/osm_bind_handle_t\r
+* NAME\r
+*   osm_bind_handle_t\r
+*\r
+* DESCRIPTION\r
+*      handle returned by the vendor transport bind call.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef        void*   osm_bind_handle_t;\r
+/***********/\r
+\r
+/****s* OpenSM/osm_vend_wrap_t\r
+* NAME\r
+*   AL Vendor MAD Wrapper\r
+*\r
+* DESCRIPTION\r
+*      AL specific MAD wrapper. AL transport layer uses this for\r
+*      housekeeping.\r
+*\r
+* SYNOPSIS\r
+*********/\r
+typedef struct _osm_vend_wrap_t\r
+{\r
+    uint32_t                                   size;\r
+       osm_bind_handle_t                       h_bind;\r
+       ib_mad_element_t                        *p_elem;\r
+       ib_av_handle_t                          h_av;\r
+       void*                                           p_resp_madw;\r
+\r
+}osm_vend_wrap_t;\r
+/*\r
+* FIELDS\r
+*      size\r
+*              Size of the allocated MAD\r
+*\r
+*      h_bind\r
+*              Bind handle used on this transaction\r
+*\r
+*      p_elem\r
+*              Pointer to the mad element structure associated with\r
+*              this mad.\r
+*\r
+*      h_av\r
+*              Address vector handle used for this transaction.\r
+*\r
+*      p_resp_madw\r
+*              Pointer to the mad wrapper structure used to hold the pending\r
+*              reponse to the mad, if any.  If a response is expected, the\r
+*              wrapper for the reponse is allocated during the send call.\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+\r
+END_C_DECLS\r
+\r
+#endif /* _OSM_VENDOR_AL_H_ */\r
+\r
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_api.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_api.h
new file mode 100644 (file)
index 0000000..664dc99
--- /dev/null
@@ -0,0 +1,519 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_vendor_api.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *  Specification of the OpenSM transport API. This API is OpenSM's view
+ *  of the Infiniband transport.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_VENDOR_API_H_
+#define _OSM_VENDOR_API_H_
+
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.h>
+#include <vendor/osm_vendor.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****s* OpenSM Vendor API/osm_vend_mad_recv_callback_t
+* NAME
+*  osm_vend_mad_recv_callback_t
+*
+* DESCRIPTION
+*  Function prototype for the vendor MAD receive callback.
+*  The vendor layer calls this function for MAD receives.
+*
+* SYNOPSIS
+*/
+typedef void (*osm_vend_mad_recv_callback_t)(
+   IN osm_madw_t *p_madw,
+   IN void* bind_context,
+   IN osm_madw_t *p_req_madw );
+/*
+* PARAMETERS
+*  p_madw
+*     [in] The received MAD wrapper.
+*
+*  bind_context
+*     [in] User context supplied during the bind call.
+*
+*  p_req_madw
+*     [in] Pointer to the request mad wrapper that generated this response.
+*     If the inbound MAD is not a response, this field is NULL.
+*
+* RETURN VALUES
+*  None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****s* OpenSM Vendor API/osm_vend_mad_send_err_callback_t
+* NAME
+*  osm_vend_mad_send_err_callback_t
+*
+* DESCRIPTION
+*  Function prototype for the vendor send failure callback.
+*  The vendor layer calls this function when MADs expecting
+*  a response are completed in error, most likely due to a 
+*  timeout.
+*
+* SYNOPSIS
+*/
+typedef void (*osm_vend_mad_send_err_callback_t)(
+   IN void* bind_context,
+   IN osm_madw_t *p_madw );
+/*
+* PARAMETERS
+*  bind_context
+*     [in] User context supplied during the bind call.
+*
+*  p_madw
+*     [in] Pointer to the request mad that failed.
+*
+* RETURN VALUES
+*  None.
+*
+* NOTES
+*  The vendor layer does not call this function (or any other)
+*  for MADs that were not expecting a response.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM Vendor API/osm_vendor_new
+* NAME
+*  osm_vendor_new
+*
+* DESCRIPTION
+*  Allocates and initializes a new osm_vendor_t object.
+*  OpenSM calls this function before any other in the vendor API.
+*  This object is passed as a parameter to all other vendor functions.
+*
+* SYNOPSIS
+*/
+osm_vendor_t*
+osm_vendor_new(
+   IN osm_log_t* const p_log,
+   IN const uint32_t timeout );
+/*
+* PARAMETERS
+*  p_log
+*     [in] Pointer to the log object to use.
+*
+*  timeout
+*     [in] transaction timeout
+*
+* RETURN VALUES
+*  Returns a pointer to the vendor object.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****s* OpenSM Vendor API/osm_vendor_delete
+* NAME
+*  osm_vendor_delete
+*
+* DESCRIPTION
+*  Dealocate the vendor object.
+*  
+* SYNOPSIS
+*/
+void
+osm_vendor_delete(
+   IN osm_vendor_t** const pp_vend );
+/*
+* PARAMETERS
+*  pp_vend
+*     [in/out] pointer to pointer to vendor objcet to be deleted
+*
+* RETURN VALUES
+*  None
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM Vendor API/osm_vendor_get_ports
+* NAME
+*  osm_vendor_get_ports
+*
+* DESCRIPTION
+*  Returns an array of available port attribute structures.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_vendor_get_all_port_attr(
+   IN osm_vendor_t*        const p_vend,
+   IN ib_port_attr_t*      const p_attr_array,
+   IN uint32_t*            const p_num_ports );
+/*
+* PARAMETERS
+*  p_vend
+*     [in] Pointer to the vendor object to initialize.
+*
+*  p_attr_array
+*     [in/out] Pointer to pre-allocated array of port attributes.
+*     If it is NULL - then the command only updates the p_num_ports,
+*     and return IB_INSUFFICIENT_MEMORY.
+*
+*  p_num_ports
+*     [in/out] Pointer to a variable to hold the total number of ports
+*     available on the local machine..
+*
+* RETURN VALUES
+*  IB_SUCCESS on success.
+*  IB_INSUFFICIENT_MEMORY if the attribute array was not large enough.
+*  The number of attributes needed is returned in num_guids.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM Vendor API/osm_vendor_init
+* NAME
+*  osm_vendor_init
+*
+* DESCRIPTION
+*  The osm_vendor_init function initializes the vendor transport layer.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_vendor_init(
+   IN osm_vendor_t* const p_vend,
+   IN osm_log_t * const p_log,
+   IN const uint32_t timeout );
+/*
+* PARAMETERS
+*  p_vend
+*     [in] Pointer to the vendor object to initialize.
+*
+*  p_log
+*     [in] Pointer to OpenSM's log object.  Vendor code may
+*     use the log object to send messages to OpenSM's log.
+*
+*  timeout
+*     [in] Transaction timeout value in milliseconds.
+*     A value of 0 disables timeouts.
+*
+* RETURN VALUE
+* 
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM Vendor API/osm_vendor_bind
+* NAME
+*   osm_vendor_bind
+*
+* DESCRIPTION
+*   The osm_vendor_bind function registers with the vendor transport layer
+*   per Mad Class per PortGuid for mad transport capability.
+*
+* SYNOPSIS
+*/
+osm_bind_handle_t
+osm_vendor_bind(
+   IN osm_vendor_t* const p_vend,
+    IN osm_bind_info_t* const p_bind_info,
+    IN osm_mad_pool_t* const p_mad_pool,
+    IN osm_vend_mad_recv_callback_t mad_recv_callback,
+    IN osm_vend_mad_send_err_callback_t send_err_callback,
+    IN void* context );
+/*
+* PARAMETERS
+*  p_vend
+*    [in] pointer to the vendor object
+*
+*  p_osm_bind_info
+*    [in] pointer to a struct defining the type of bind to perform.
+*
+*  p_mad_pool
+*    [in] pointer to a mad wrappers pool to be used for allocating 
+*    mad wrappers on send and receive.
+*
+*  mad_recv_callback
+*    [in] the callback function to be invoked on mad receive.
+*
+*  send_err_callback
+*    [in] the callback function to be invoked on mad transaction errors.
+*
+*  context
+*    [in] the context to be provided to the callbacks as bind_ctx.
+*
+* RETURN VALUE
+*  On success, a valid bind handle.
+*  OSM_BIND_INVALID_HANDLE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM Vendor API/osm_vendor_unbind
+* NAME
+*   osm_vendor_unbind
+*
+* DESCRIPTION
+*   Unbind the given bind handle (obtained by osm_vendor_bind).
+*
+* SYNOPSIS
+*/
+void
+osm_vendor_unbind(
+    IN osm_bind_handle_t h_bind );
+/*
+* PARAMETERS
+*  h_bind
+*    [in] the bind handle to release.
+*
+* RETURN VALUE
+*    NONE.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM Vendor API/osm_vendor_get
+* NAME
+*   osm_vendor_get
+*
+* DESCRIPTION
+*   Obtain a mad wrapper holding actual mad buffer to be sent via 
+*   the transport.
+*
+* SYNOPSIS
+*/
+ib_mad_t*
+osm_vendor_get(
+    IN osm_bind_handle_t      h_bind,
+    IN const uint32_t         mad_size,
+    IN osm_vend_wrap_t* const p_vend_wrap );
+/*
+* PARAMETERS
+*   h_bind
+*      [in] the bind handle obtained by calling osm_vendor_bind
+*
+*   mad_size
+*      [in] the actual mad size required
+*
+*   p_vend_wrap
+*      [out] the returned mad vendor wrapper
+*
+* RETURN VALUE
+*   IB_SUCCESS on succesful completion.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM Vendor API/osm_vendor_send
+* NAME
+*   osm_vendor_send
+*
+* DESCRIPTION
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_vendor_send(
+    IN osm_bind_handle_t h_bind,
+    IN osm_madw_t* const p_madw,
+    IN boolean_t const resp_expected);
+/*
+* PARAMETERS
+*   h_bind
+*      [in] the bind handle obtained by calling osm_vendor_bind
+*
+*   p_madw
+*      [in] pointer to the Mad Wrapper structure for the MAD to be sent.
+*
+*   resp_expected
+*      [in] boolean value declaring the mad as a request (expecting a response).
+*  
+* RETURN VALUE
+*   IB_SUCCESS on succesful completion.
+* 
+* NOTES
+*   1. Only mads that expect a response are tracked for transaction competion.
+*   2. A mad that does not expect a response is being put back immediatly after
+*      being sent.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM Vendor API/osm_vendor_put
+* NAME
+*   osm_vendor_put
+*
+* DESCRIPTION
+*   Return a mad vandor wrapper to the mad pool. It also means that the
+*   mad buffer is returned to the transport.
+*
+* SYNOPSIS
+*/
+void
+osm_vendor_put(
+    IN osm_bind_handle_t h_bind,
+    IN osm_vend_wrap_t* const p_vend_wrap );
+/*
+* PARAMETERS
+*   h_bind
+*      [in] the bind handle obtained by calling osm_vendor_bind
+*
+*   p_vend_wrap
+*      [in] pointer to the mad vendor wrapper to put back into the pool.
+*
+* RETURN VALUE
+*   None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****i* OpenSM Vendor API/osm_vendor_local_lid_change
+* NAME
+*   osm_vendor_local_lid_change
+*
+* DESCRIPTION
+*  Notifies the vendor transport layer that the local address
+*  has changed.  This allows the vendor layer to perform housekeeping
+*  functions such as address vector updates.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_vendor_local_lid_change(
+    IN osm_bind_handle_t h_bind );
+/*
+* PARAMETERS
+*   h_bind
+*      [in] the bind handle obtained by calling osm_vendor_bind
+*
+* RETURN VALUE
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM Vendor API/osm_vendor_set_sm
+* NAME
+*   osm_vendor_set_sm
+*
+* DESCRIPTION
+*  Modifies the port info for the bound port to set the "IS_SM" bit
+*  according to the value given (TRUE or FALSE).
+*
+* SYNOPSIS
+*/
+void
+osm_vendor_set_sm(
+    IN osm_bind_handle_t h_bind,
+    IN boolean_t         is_sm_val );
+/*
+* PARAMETERS
+*   h_bind
+*     [in] bind handle for this port.
+*
+*   is_sm_val
+*     [in] If TRUE - will set the is_sm to TRUE, if FALSE - will set the 
+*          the is_sm to FALSE.
+*
+* RETURN VALUE
+*  None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM Vendor API/osm_vendor_set_debug
+* NAME
+*   osm_vendor_set_debug
+*
+* DESCRIPTION
+*  Modifies the vendor specific debug level.
+*
+* SYNOPSIS
+*/
+void
+osm_vendor_set_debug(
+    IN osm_vendor_t*        const p_vend,
+    IN int32_t         level );
+/*
+* PARAMETERS
+*   p_vend
+*     [in] vendor handle.
+*
+*   level
+*     [in] vendor specific debug level.
+*
+* RETURN VALUE
+*  None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif   /* _OSM_VENDOR_API_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_sa_api.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_sa_api.h
new file mode 100644 (file)
index 0000000..b9198cb
--- /dev/null
@@ -0,0 +1,879 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_vendor_sa_api.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Specification of the OpenSM SA Client API. This API uses the basic osm
+ *    vendor API to provide SA Client interface.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_VENDOR_SA_API_H_
+#define _OSM_VENDOR_SA_API_H_
+
+#include <iba/ib_types.h>
+
+#ifdef __cplusplus
+#  define BEGIN_C_DECLS extern "C" {
+#  define END_C_DECLS   }
+#else /* !__cplusplus */
+#  define BEGIN_C_DECLS
+#  define END_C_DECLS
+#endif /* __cplusplus */
+
+BEGIN_C_DECLS
+
+/****d* OpenSM Vendor SA Client/osmv_flags_t
+* NAME
+*      osmv_flags_t
+*
+* DESCRIPTION
+*      Access layer flags used to direct the operation of various calls.
+*
+* SYNOPSIS
+*/
+typedef uint32_t                                       osmv_flags_t;
+#define OSM_SA_FLAGS_SYNC                              0x00000001
+/*
+* VALUES
+*      OSM_SA_FLAGS_SYNC
+*              Indicates that the given operation should be performed synchronously.
+*              The call will block until it completes.  Callbacks will still be
+*              invoked.
+*
+* SEE ALSO
+*  osmv_query_sa
+*****/
+
+/****d* OpenSM Vendor SA Client/osmv_query_type_t
+* NAME
+*      osmv_query_type_t
+*
+* DESCRIPTION
+*      Abstracted queries supported by the access layer.
+*
+* SYNOPSIS
+*/
+typedef enum _osmv_query_type
+{
+       OSMV_QUERY_USER_DEFINED,
+
+       OSMV_QUERY_ALL_SVC_RECS,
+       OSMV_QUERY_SVC_REC_BY_NAME,
+       OSMV_QUERY_SVC_REC_BY_ID,
+
+       OSMV_QUERY_CLASS_PORT_INFO,
+
+       OSMV_QUERY_NODE_REC_BY_NODE_GUID,
+       OSMV_QUERY_PORT_REC_BY_LID,
+       OSMV_QUERY_PORT_REC_BY_LID_AND_NUM,
+
+       OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK,
+       OSMV_QUERY_SLVL_BY_LID_AND_PORTS,
+
+       OSMV_QUERY_PATH_REC_BY_PORT_GUIDS,
+       OSMV_QUERY_PATH_REC_BY_GIDS,
+       OSMV_QUERY_PATH_REC_BY_LIDS,
+
+       OSMV_QUERY_UD_MULTICAST_SET,
+       OSMV_QUERY_UD_MULTICAST_DELETE,
+
+       OSMV_QUERY_MULTIPATH_REC,
+
+}      osmv_query_type_t;
+/*
+* VALUES
+*      OSMV_QUERY_USER_DEFINED
+*              Query the SA based on user-defined input.  Queries of this type
+*              should reference an osmv_user_query_t structure as input to the
+*              query.
+*
+*      OSMV_QUERY_SVC_REC_BY_NAME
+*              Query for service records based on the service name.  Queries of
+*              this type should reference an ib_svc_name_t structure as input
+*              to the query.
+*
+*      OSMV_QUERY_SVC_REC_BY_ID
+*              Query for service records based on the service ID.  Queries of
+*              this type should reference an ib_net64_t value that indicates
+*              the ID of the service being requested.
+*
+*      OSMV_QUERY_NODE_REC_BY_NODE_GUID
+*              Query for node information based on the node's GUID.  Queries of
+*              this type should reference an ib_net64_t value that indicates
+*              the GUID of the node being requested.
+*
+*      OSMV_QUERY_PORT_REC_BY_LID
+*              Query for port information based on the port's base LID. Queries
+*              of this type should reference an ib_net16_t value that indicates
+*              the base LID of the port being requested.
+*
+*      OSMV_QUERY_PORT_REC_BY_LID_AND_NUM
+*              Query for port information based on the port's LID and port num.
+*              Queries of this type should reference an osmv_user_query_t
+*              structure as input to the query. The port num and lid should
+*              be provided by it.
+*
+*      OSMV_QUERY_PATH_REC_BY_PORT_GUIDS
+*              Query for path records between the specified pair of port GUIDs.
+*              Queries of this type should reference an osmv_guid_pair_t
+*              structure that indicates the GUIDs of the path being requested.
+*
+*      OSMV_QUERY_PATH_REC_BY_GIDS
+*              Query for path records between the specified pair of port GIDs.
+*              Queries of this type should reference an osmv_gid_pair_t
+*              structure that indicates the GIDs of the path being requested.
+*
+*      OSMV_QUERY_PATH_REC_BY_LIDS
+*              Query for path records between the specified pair of port LIDs.
+*              Queries of this type should reference an osmv_lid_pair_t
+*              structure that indicates the LIDs of the path being requested.
+*
+* NOTES
+*      This enum is used to define abstracted queries provided by the access
+*      layer.  Users may issue queries not listed here by sending MADs directly
+*      to subnet administration or a class manager.  These queries are
+*      intended to represent those most often used by clients.
+*
+* SEE ALSO
+*      osmv_query, osmv_query_req_t, osmv_user_query_t, osmv_gid_pair_t,
+*      osmv_lid_pair_t osmv_guid_pair_t
+*****/
+
+/****s* OpenSM Vendor SA Client/osmv_user_query_t
+* NAME
+*      osmv_user_query_t
+*
+* DESCRIPTION
+*      User-defined query information.
+*
+* SYNOPSIS
+*/
+typedef struct _osmv_user_query
+{
+       uint8_t                                 method;
+       ib_net16_t                              attr_id;
+       ib_net16_t                              attr_offset;
+       ib_net32_t                              attr_mod;
+       ib_net64_t                              comp_mask;
+       void                                    *p_attr;
+}      osmv_user_query_t;
+/*
+* FIELDS
+*
+*      method
+*              Method to be used
+*
+*      attr_id
+*              Attribute identifier of query data.
+*
+*      attr_offset
+*              Size of the query attribute, in 8-byte words.  Users can set
+*              this value by passing in the sizeof( attribute ) into the
+*              ib_get_attr_offset() routine.
+*
+*      attr_mod
+*              Attribute modifier for query request.
+*
+*      comp_mask
+*              Indicates the attribute components that are specified for the
+*              query.
+*
+*      p_attr
+*              References the attribute structure used as input into the query.
+*              This field is ignored if comp_mask is set to 0.
+*
+* NOTES
+*      This structure is used to describe a user-defined query.  The attribute
+*      ID, attribute offset, component mask, and attribute structure must match
+*      those defined by the IBA specification.  Users should refer to chapter
+*      15 of the IBA specification for additional details.
+*
+* SEE ALSO
+*      osmv_query_type_t, ib_get_attr_offset, ib_get_attr_size, osmv_query_sa
+*****/
+
+/****s* OpenSM Vendor SA Client/osmv_gid_pair_t
+* NAME
+*      osmv_gid_pair_t
+*
+* DESCRIPTION
+*      Source and destination GIDs.
+*
+* SYNOPSIS
+*/
+typedef struct _osmv_gid_pair
+{
+       ib_gid_t                                src_gid;
+       ib_gid_t                                dest_gid;
+}      osmv_gid_pair_t;
+/*
+* FIELDS
+*      src_gid
+*              Source GID of a path.
+*
+*      dest_gid
+*              Destination GID of a path.
+*
+* NOTES
+*      This structure is used to describe the endpoints of a path.
+*
+* SEE ALSO
+*      ib_gid_t
+*****/
+
+/****s* OpenSM Vendor SA Client/osmv_lid_pair_t
+* NAME
+*      osmv_lid_pair_t
+*
+* DESCRIPTION
+*      Source and destination LIDs.
+*
+* SYNOPSIS
+*/
+typedef struct _osmv_lid_pair
+{
+       ib_net16_t                              src_lid;
+       ib_net16_t                              dest_lid;
+}      osmv_lid_pair_t;
+/*
+* FIELDS
+*      src_lid
+*              Source LID of a path.
+*
+*      dest_lid
+*              Destination LID of a path.
+*
+* NOTES
+*      This structure is used to describe the endpoints of a path.
+*****/
+
+/****s* OpenSM Vendor SA Client/osmv_guid_pair_t
+* NAME
+*      osmv_guid_pair_t
+*
+* DESCRIPTION
+*      Source and destination GUIDs.  These may be port or channel adapter
+*      GUIDs, depending on the context in which this structure is used.
+*
+* SYNOPSIS
+*/
+typedef struct _osmv_guid_pair
+{
+       ib_net64_t                              src_guid;
+       ib_net64_t                              dest_guid;
+}      osmv_guid_pair_t;
+/*
+* FIELDS
+*      src_guid
+*              Source GUID of a path.
+*
+*      dest_guid
+*              Destination GUID of a path.
+*
+* NOTES
+*      This structure is used to describe the endpoints of a path.  The given
+*      GUID pair may belong to either ports or channel adapters.
+*
+* SEE ALSO
+*      ib_guid_t
+*****/
+
+/****s* OpenSM Vendor SA Client/osmv_multipath_req_t
+* NAME
+*       osmv_multipath_req_t
+*
+* DESCRIPTION
+*       Fields from which to generate a MultiPathRecord request.
+*
+* SYNOPSIS
+*/
+typedef struct _osmv_multipath_req_t
+{
+       ib_net64_t      comp_mask;
+       uint16_t        pkey;
+       boolean_t       reversible;
+       uint8_t         num_path;
+       uint8_t         sl;
+       uint8_t         independence;
+       uint8_t         sgid_count;
+       uint8_t         dgid_count;
+       ib_gid_t        gids[IB_MULTIPATH_MAX_GIDS];
+} osmv_multipath_req_t;
+/*
+* FIELDS
+*
+* NOTES
+*       This structure is used to describe a multipath request.
+*
+* SEE ALSO
+*****/
+
+/****s* OpenSM Vendor SA Client/osmv_query_res_t
+* NAME
+*      osmv_query_res_t
+*
+* DESCRIPTION
+*      Contains the results of a subnet administration query.
+*
+* SYNOPSIS
+*/
+typedef struct _osmv_query_res
+{
+       const void                              *query_context;
+       ib_api_status_t                          status;
+       osmv_query_type_t                        query_type;
+       uint32_t                                 result_cnt;
+       osm_madw_t                              *p_result_madw;
+}      osmv_query_res_t;
+/*
+* FIELDS
+*      query_context
+*              User-defined context information associated with the query
+*              through the osm_vendor_query_sa call.
+*
+*      status
+*              Indicates the success of the query operation.
+*
+*      query_type
+*              Indicates the type of query for which the results are being
+*              returned.  This matches the query_type specified through the
+*               osm_vendor_query_sa call.
+*
+*      result_cnt
+*              The number of result structures that were returned by the query.
+*
+*      p_result_madw
+*              For queries returning IB_SUCCESS or IB_REMOTE_ERROR, this
+*              references the MAD wrapper returned by subnet administration
+*              containing the list of results or the returned error code.
+*
+* NOTES
+*      A query result structure is returned to a client through their
+*      osmv_pfn_query_cb_t routine to notify them of the results of a subnet
+*      administration query.  If the query was successful or received an error
+*      from subnet administration, p_result_madw will reference a MAD wrapper
+*      containing the results.  The MAD referenced by p_result_madw is owned by
+*      the user and remains available even after their callback returns.  Users
+*      must call osm_mad_pool_put() to return the MAD wrapper back to the
+*      mad pool when they are done accessing the results.
+*
+*      To retrieve individual result structures from the p_result_madw, users
+*      may call osmv_get_query_result().
+*
+* SEE ALSO
+*      osmv_query_sa, osmv_pfn_query_cb_t, ib_api_status_t, 
+*      osmv_query_status_t, osmv_query_type_t,
+*      osmv_get_query_result
+*****/
+
+/****f* OpenSM Vendor SA Client/osmv_get_query_result
+* NAME
+*      osmv_get_query_result
+*
+* DESCRIPTION
+*      Retrieves a result structure from a MADW returned by a call to
+*      osmv_query_sa(). 
+*
+* SYNOPSIS
+*/
+static inline void*
+osmv_get_query_result(
+       IN osm_madw_t           *p_result_madw,
+       IN uint32_t             result_index )
+{
+       ib_sa_mad_t             *p_sa_mad;
+
+       CL_ASSERT( p_result_madw );
+       p_sa_mad = (ib_sa_mad_t*)osm_madw_get_mad_ptr( p_result_madw );
+       CL_ASSERT( p_sa_mad );
+       CL_ASSERT( ib_get_attr_size( p_sa_mad->attr_offset ) * (result_index + 1) +
+               IB_SA_MAD_HDR_SIZE <= p_result_madw->mad_size );
+
+       return( p_sa_mad->data +
+               (ib_get_attr_size( p_sa_mad->attr_offset ) * result_index) );
+}
+/*
+* PARAMETERS
+*      p_result_madw
+*              [in] This is a reference to the MAD returned as a result of the
+*              query.
+*
+*      result_index
+*              [in] A zero-based index indicating which result to return.
+*
+* NOTES
+*      This call returns a pointer to the start of a result structure from a
+*      call to osmv_query_sa().  The type of result structure must be known to
+*      the user either through the user's context or the query_type returned as
+*      part of the osmv_query_res_t structure.
+*
+* SEE ALSO
+*      osmv_query_res_t, osm_madw_t
+*****/
+
+/****f* OpenSM Vendor SA Client/osmv_get_query_path_rec
+* NAME
+*      osmv_get_query_path_rec
+*
+* DESCRIPTION
+*      Retrieves a path record result from a MAD returned by a call to
+*      osmv_query_sa().
+*
+* SYNOPSIS
+*/
+static inline ib_path_rec_t*
+osmv_get_query_path_rec(
+       IN osm_madw_t           *p_result_madw,
+       IN uint32_t             result_index )
+{
+       ib_sa_mad_t             *p_sa_mad;
+
+       CL_ASSERT( p_result_madw );
+       p_sa_mad = (ib_sa_mad_t*)osm_madw_get_mad_ptr( p_result_madw );
+       CL_ASSERT( p_sa_mad && p_sa_mad->attr_id == IB_MAD_ATTR_PATH_RECORD );
+
+       return( (ib_path_rec_t*)osmv_get_query_result( p_result_madw, result_index ) );
+}
+/*
+* PARAMETERS
+*      p_result_madw
+*              [in] This is a reference to the MAD returned as a result of the
+*              query.
+*
+*      result_index
+*              [in] A zero-based index indicating which result to return.
+*
+* NOTES
+*      This call returns a pointer to the start of a path record result from
+*      a call to osmv_query_sa().
+*
+* SEE ALSO
+*      osmv_query_res_t, osm_madw_t, osmv_get_query_result, ib_path_rec_t
+*****/
+
+/****f* OpenSM Vendor SA Client/osmv_get_query_portinfo_rec
+* NAME
+*      osmv_get_query_portinfo_rec
+*
+* DESCRIPTION
+*      Retrieves a port info record result from a MAD returned by a call to
+*      osmv_query_sa().
+*
+* SYNOPSIS
+*/
+static inline ib_portinfo_record_t*
+osmv_get_query_portinfo_rec(
+       IN osm_madw_t           *p_result_madw,
+       IN uint32_t             result_index )
+{
+       ib_sa_mad_t             *p_sa_mad;
+
+       CL_ASSERT( p_result_madw );
+       p_sa_mad = (ib_sa_mad_t*)osm_madw_get_mad_ptr( p_result_madw );
+       CL_ASSERT( p_sa_mad && p_sa_mad->attr_id == IB_MAD_ATTR_PORTINFO_RECORD );
+
+       return( (ib_portinfo_record_t*)osmv_get_query_result( p_result_madw,
+               result_index ) );
+}
+/*
+* PARAMETERS
+*      p_result_madw
+*              [in] This is a reference to the MAD returned as a result of the
+*              query.
+*
+*      result_index
+*              [in] A zero-based index indicating which result to return.
+*
+* NOTES
+*      This call returns a pointer to the start of a port info record result
+*      from a call to osmv_query_sa().
+*
+* SEE ALSO
+*      osmv_query_res_t, osm_madw_t, osmv_get_query_result, ib_portinfo_record_t
+*****/
+
+/****f* OpenSM Vendor SA Client/osmv_get_query_node_rec
+* NAME
+*      osmv_get_query_node_rec
+*
+* DESCRIPTION
+*      Retrieves a node record result from a MAD returned by a call to
+*      osmv_query_sa().
+*
+* SYNOPSIS
+*/
+static inline ib_node_record_t*
+osmv_get_query_node_rec(
+       IN osm_madw_t           *p_result_madw,
+       IN uint32_t             result_index )
+{
+       ib_sa_mad_t             *p_sa_mad;
+
+       CL_ASSERT( p_result_madw );
+       p_sa_mad = (ib_sa_mad_t*)osm_madw_get_mad_ptr( p_result_madw );
+       CL_ASSERT( p_sa_mad && p_sa_mad->attr_id == IB_MAD_ATTR_NODE_RECORD );
+
+       return( (ib_node_record_t*)osmv_get_query_result( p_result_madw,
+               result_index ) );
+}
+/*
+* PARAMETERS
+*      p_result_madw
+*              [in] This is a reference to the MAD returned as a result of the
+*              query.
+*
+*      result_index
+*              [in] A zero-based index indicating which result to return.
+*
+* NOTES
+*      This call returns a pointer to the start of a node record result from
+*      a call to osmv_query_sa().
+*
+* SEE ALSO
+*      osmv_query_res_t, osm_madw_t, osmv_get_query_result, ib_node_record_t
+*****/
+
+/****f* OpenSM Vendor SA Client/osmv_get_query_svc_rec
+* NAME
+*      osmv_get_query_svc_rec
+*
+* DESCRIPTION
+*      Retrieves a service record result from a MAD returned by a call to
+*      osmv_query_sa().
+*
+* SYNOPSIS
+*/
+static inline ib_service_record_t*
+osmv_get_query_svc_rec(
+       IN osm_madw_t           *p_result_madw,
+       IN uint32_t             result_index )
+{
+       ib_sa_mad_t             *p_sa_mad;
+
+       CL_ASSERT( p_result_madw );
+       p_sa_mad = (ib_sa_mad_t*)osm_madw_get_mad_ptr( p_result_madw );
+       CL_ASSERT( p_sa_mad && p_sa_mad->attr_id == IB_MAD_ATTR_SERVICE_RECORD );
+
+       return( (ib_service_record_t*)osmv_get_query_result( p_result_madw,
+               result_index ) );
+}
+/*
+* PARAMETERS
+*      p_result_madw
+*              [in] This is a reference to the MAD returned as a result of the
+*              query.
+*
+*      result_index
+*              [in] A zero-based index indicating which result to return.
+*
+* NOTES
+*      This call returns a pointer to the start of a service record result from
+*      a call to osmv_query_sa().
+*
+* SEE ALSO
+*      osmv_query_res_t, osm_madw_t, osmv_get_query_result, ib_service_record_t
+*****/
+
+/****f* OpenSM Vendor SA Client/osmv_get_query_mc_rec
+* NAME
+*      osmv_get_query_mc_rec
+*
+* DESCRIPTION
+*      Retrieves a multicast record result from a MAD returned by a call to
+*      osmv_query_sa().
+*
+* SYNOPSIS
+*/
+static inline ib_member_rec_t*
+osmv_get_query_mc_rec(
+       IN osm_madw_t           *p_result_madw,
+       IN uint32_t             result_index )
+{
+       ib_sa_mad_t             *p_sa_mad;
+
+       CL_ASSERT( p_result_madw );
+       p_sa_mad = (ib_sa_mad_t*)osm_madw_get_mad_ptr( p_result_madw );
+       CL_ASSERT( p_sa_mad && p_sa_mad->attr_id == IB_MAD_ATTR_MCMEMBER_RECORD );
+
+       return( (ib_member_rec_t*)osmv_get_query_result( p_result_madw,
+               result_index ) );
+}
+/*
+* PARAMETERS
+*      p_result_madw
+*              [in] This is a reference to the MAD returned as a result of the
+*              query.
+*
+*      result_index
+*              [in] A zero-based index indicating which result to return.
+*
+* NOTES
+*      This call returns a pointer to the start of a service record result from
+*      a call to osmv_query_sa().
+*
+* SEE ALSO
+*      osmv_query_res_t, osm_madw_t, osmv_get_query_result, ib_member_rec_t
+*****/
+
+/****f* OpenSM Vendor SA Client/osmv_get_query_inform_info_rec
+* NAME
+*      osmv_get_query_inform_info_rec
+*
+* DESCRIPTION
+*      Retrieves an InformInfo record result from a MAD returned by
+*      a call to osmv_query_sa().
+*
+* SYNOPSIS
+*/
+static inline ib_inform_info_record_t*
+osmv_get_query_inform_info_rec(
+       IN osm_madw_t           *p_result_madw,
+       IN uint32_t             result_index )
+{
+       ib_sa_mad_t             *p_sa_mad;
+
+       CL_ASSERT( p_result_madw );
+       p_sa_mad = (ib_sa_mad_t*)osm_madw_get_mad_ptr( p_result_madw );
+       CL_ASSERT( p_sa_mad && p_sa_mad->attr_id == IB_MAD_ATTR_INFORM_INFO_RECORD );
+
+        return( (ib_inform_info_record_t*)osmv_get_query_result( p_result_madw,
+                result_index ) );
+}
+/*
+* PARAMETERS
+*      p_result_madw
+*              [in] This is a reference to the MAD returned as a result of the
+*              query.
+*
+*      result_index
+*              [in] A zero-based index indicating which result to return.
+*
+* NOTES
+*      This call returns a pointer to the start of a service record result from
+*      a call to osmv_query_sa().
+*
+* SEE ALSO
+*      osmv_query_res_t, osm_madw_t, osmv_get_query_result, ib_inform_info_record_t
+*****/
+
+/****f* OpenSM Vendor SA Client/osmv_pfn_query_cb_t
+* NAME
+*      osmv_pfn_query_cb_t
+*
+* DESCRIPTION
+*      User-defined callback invoked on completion of subnet administration
+*      query.
+*
+* SYNOPSIS
+*/
+typedef void
+(*osmv_pfn_query_cb_t)(
+       IN osmv_query_res_t     *p_query_res );
+/*
+* PARAMETERS
+*      p_query_res
+*              [in] This is a reference to a structure containing the result of
+*              the query.
+*
+* NOTES
+*      This routine is invoked to notify a client of the result of a subnet
+*      administration query.  The p_query_rec parameter references the result
+*      of the query and, in the case of a successful query, any information
+*      returned by subnet administration.
+*
+*      In the kernel, this callback is usually invoked using a tasklet,
+*      dependent on the implementation of the underlying verbs provider driver.
+*
+* SEE ALSO
+*      osmv_query_res_t
+*****/
+
+/****s* OpenSM Vendor SA Client/osmv_query_req_t
+* NAME
+*      osmv_query_req_t
+*
+* DESCRIPTION
+*      Information used to request an access layer provided query of subnet
+*      administration.
+*
+* SYNOPSIS
+*/
+typedef struct _osmv_query_req
+{
+       osmv_query_type_t                       query_type;
+       const void                              *p_query_input;
+       ib_net64_t                              sm_key;
+
+       uint32_t                                timeout_ms;
+       uint32_t                                retry_cnt;
+       osmv_flags_t                            flags;
+
+       const void                              *query_context;
+       osmv_pfn_query_cb_t                     pfn_query_cb;
+}      osmv_query_req_t;
+/*
+* FIELDS
+*      query_type
+*              Indicates the type of query that the access layer should
+*              perform.
+*
+*      p_query_input
+*              A pointer to the input for the query.  The data referenced by
+*              this structure is dependent on the type of query being requested
+*              and is determined by the specified query_type.
+*
+*      sm_key
+*              The M_Key to be provided with the SA MAD for authentication.
+*              Normally 0 is used.
+*
+*      timeout_ms
+*              Specifies the number of milliseconds to wait for a response for
+*              this query until retrying or timing out the request.
+*
+*      retry_cnt
+*              Specifies the number of times that the query will be retried
+*              before failing the request.
+*
+*      flags
+*              Used to describe the mode of operation.  Set to IB_FLAGS_SYNC to
+*              process the called routine synchronously.
+*
+*      query_context
+*              User-defined context information associated with this query.
+*              The context data is returned to the user as a part of their
+*              query callback.
+*
+*      pfn_query_cb
+*              A user-defined callback that is invoked upon completion of the
+*              query.
+*
+* NOTES
+*      This structure is used when requesting an osm vendor provided query
+*      of subnet administration.  Clients specify the type of query through
+*      the query_type field.  Based on the type of query, the p_query_input
+*      field is set to reference the appropriate data structure.
+*
+*      The information referenced by the p_query_input field is one of the
+*      following:
+*
+*              -- a NULL terminated service name
+*              -- a service id
+*              -- a single GUID
+*              -- a pair of GUIDs specified through an osmv_guid_pair_t structure
+*              -- a pair of GIDs specified through an osmv_gid_pair_t structure
+*
+* SEE ALSO
+*      osmv_query_type_t, osmv_pfn_query_cb_t, osmv_guid_pair_t,
+*      osmv_gid_pair_t
+*****/
+
+/****f* OpenSM Vendor SA Client/osmv_bind_sa
+* NAME
+*   osmv_bind_sa
+*
+* DESCRIPTION
+*      Bind to the SA service and return a handle to be used for later
+*  queries.
+*      
+*
+* SYNOPSIS
+*/
+osm_bind_handle_t 
+osmv_bind_sa(
+  IN osm_vendor_t    * const p_vend,
+  IN osm_mad_pool_t  * const p_mad_pool,
+  IN ib_net64_t              port_guid
+  );
+/*
+* PARAMETERS
+*   p_vend
+*      [in] an osm_vendor object to work with
+*
+*   p_mad_pool
+*      [in] mad pool to obtain madw from
+*
+*   port_guid
+*      [in] the port guid to attach to.
+*   
+* RETURN VALUE
+*      Bind handle to be used for later SA queries or OSM_BIND_INVALID_HANDLE
+*
+* NOTES
+*
+* SEE ALSO
+* osmv_query_sa
+*********/
+
+/****f* OpenSM Vendor SA Client/osmv_query_sa
+* NAME
+*   osmv_query_sa
+*
+* DESCRIPTION
+*   Query the SA given an SA query request (similar to IBAL ib_query).
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osmv_query_sa( 
+  IN osm_bind_handle_t         h_bind,
+  IN const osmv_query_req_t * const p_query_req 
+  );
+/*
+* PARAMETERS
+*   h_bind
+*      [in] bind handle for this port. Should be previously 
+*       obtained by calling osmv_bind_sa
+*
+*   p_query_req
+*      [in] an SA query request structure.
+*   
+* RETURN VALUE
+*      IB_SUCCESS if completed successfuly (or in ASYNC mode 
+*      if the request was sent).
+*
+* NOTES
+*
+* SEE ALSO
+* osmv_bind_sa
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_VENDOR_SA_API_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_select.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/osm_vendor_select.h
new file mode 100644 (file)
index 0000000..3c6394a
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_vendor_select.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *     Include file that defines which vendor files to compile.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#ifndef _OSM_VENDOR_SELECT_H_
+#define _OSM_VENDOR_SELECT_H_
+
+/////////////////////////////////////////////////////
+//
+// MAD INTERFACE SELECTION
+//
+/////////////////////////////////////////////////////
+
+/*
+       TEST and UMADT must be specified in the 'make' command line,
+       with VENDOR=test or VENDOR=umadt.
+*/
+#ifndef OSM_VENDOR_INTF_OPENIB
+#ifndef OSM_VENDOR_INTF_TEST
+#ifndef OSM_VENDOR_INTF_UMADT
+#ifndef OSM_VENDOR_INTF_MTL
+#ifndef OSM_VENDOR_INTF_TS
+#ifndef OSM_VENDOR_INTF_SIM
+#ifndef OSM_VENDOR_INTF_AL
+#define OSM_VENDOR_INTF_AL
+#endif /* AL */
+#endif /* TS */
+#endif /* SIM */
+#endif /* MTL */
+#endif /* UMADT */
+#endif /* TEST */
+#endif /* OPENIB */
+
+#endif /* _OSM_VENDOR_SELECT_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/winosm_common.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/include/vendor/winosm_common.h
new file mode 100644 (file)
index 0000000..cb2a286
--- /dev/null
@@ -0,0 +1,251 @@
+#ifndef _OSM_COMMON_H_\r
+#define _OSM_COMMON_H_\r
+\r
+#include <winsock2.h>\r
+#include <windows.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <stdarg.h>\r
+#include <ctype.h>\r
+\r
+#pragma warning(disable : 4996)\r
+#pragma warning(disable : 4100)\r
+\r
+struct timezone {\r
+        int     tz_minuteswest; /* minutes west of Greenwich */\r
+        int     tz_dsttime;     /* type of dst correction */\r
+};\r
+\r
+\r
+\r
+#ifndef _GETOPT_H_ \r
+\r
+# define no_argument           0\r
+# define required_argument     1\r
+# define optional_argument     2\r
+\r
+/* Global variables for getopt_long */\r
+char *optarg;\r
+\r
+struct option\r
+{\r
+  const char *name;\r
+  int has_arg;\r
+  int *flag;\r
+  int val;\r
+};\r
+#endif\r
+\r
+\r
+/************************************************************************/\r
+static char* \r
+get_char_option(const char* optstring,\r
+                             char*const* argv,int argc, \r
+                             int iArg, int* opt_ind,char* opt_p);   \r
+int \r
+getopt_long_only(int argc, char *const*argv,\r
+                         const char *optstring,\r
+                         const struct option *longopts, int *longindex);\r
+/**************************************************************************/\r
+static __inline\r
+void FileTimeToTimeval(LPFILETIME pft, struct timeval * ptv)\r
+{ /* Note that LONGLONG is a 64-bit value */\r
+LONGLONG ll;\r
+\r
+if(!pft || !ptv)\r
+goto Exit;\r
+\r
+ll = ((LONGLONG) pft->dwHighDateTime << 32);\r
+ll += (LONGLONG) pft->dwLowDateTime;\r
+#ifdef __GNUC__\r
+ll -= 116444736000000000ll;\r
+#else\r
+ll -= 116444736000000000;\r
+#endif\r
+\r
+ptv->tv_sec = (long) (ll / 10000000);\r
+ptv->tv_usec = (long) (ll - ((LONGLONG)(ptv->tv_sec) * 10000000)) / 10;\r
+\r
+Exit:;\r
+}/* FileTimeToTimeval */\r
+\r
+/********************************************************************************/\r
+static __inline\r
+int gettimeofday(struct timeval *ptv, struct timezone *tzp)\r
+{\r
+static int QueryCounter = 2;\r
+FILETIME CurrentTime;\r
+/* TODO : We need to add it , since in DDK - compiler does not like vars that are not in use */\r
+UNREFERENCED_PARAMETER(tzp);     \r
+if(!ptv)\r
+goto Exit;\r
+\r
+if(QueryCounter)\r
+{\r
+static LARGE_INTEGER Frequency;\r
+static LARGE_INTEGER Offset; /* counter offset for right time*/\r
+static LARGE_INTEGER LastCounter;\r
+LARGE_INTEGER Time;\r
+LARGE_INTEGER Counter;\r
+/* HANDLE hThread = GetCurrentThread();\r
+int ThreadPrio = GetThreadPriority(hThread);\r
+\r
+SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL); */\r
+GetSystemTimeAsFileTime(&CurrentTime);\r
+QueryPerformanceCounter(&Counter);\r
+/* SetThreadPriority(hThread, ThreadPrio); */\r
+\r
+if(QueryCounter == 2)\r
+{\r
+QueryCounter = 1;\r
+if(!QueryPerformanceFrequency(&Frequency))\r
+{\r
+QueryCounter = 0;\r
+Frequency.QuadPart = 10000000; /* prevent division by 0 */\r
+}\r
+\r
+/* get time as a large integer */\r
+Counter.HighPart &= 0x7fl; /* Clear the highest bits to prevent overflows */\r
+Offset.LowPart = CurrentTime.dwLowDateTime;\r
+Offset.HighPart = (LONG) CurrentTime.dwHighDateTime;\r
+Offset.QuadPart -= Counter.QuadPart * 10000000 / Frequency.QuadPart;\r
+}\r
+\r
+/* Convert counter to a 100 nanoseconds resolution timer value. */\r
+\r
+Counter.HighPart &= 0x7fl; /* Clear the highest bits to prevent overflows */\r
+Counter.QuadPart *= 10000000; /* Because we need time stamp in units of 100 ns */\r
+Counter.QuadPart /= Frequency.QuadPart; /* counter of 0.1 microseconds */\r
+\r
+if(LastCounter.QuadPart > Counter.QuadPart)\r
+{ /* Counter value wrapped */\r
+#ifdef __GNUC__\r
+Offset.QuadPart += (0x7f00000000ll * 10000000ll) / Frequency.QuadPart;\r
+#else\r
+Offset.QuadPart += (0x7f00000000 * 10000000) / Frequency.QuadPart;\r
+#endif\r
+}\r
+LastCounter = Counter;\r
+\r
+/* Add the in previous call calculated offset */\r
+Counter.QuadPart += Offset.QuadPart;\r
+\r
+/* get time as a large integer */\r
+Time.LowPart = CurrentTime.dwLowDateTime;\r
+Time.HighPart = (LONG) CurrentTime.dwHighDateTime;\r
+\r
+/* keep time difference within an interval of +- 0.1 seconds\r
+relative to the time function by adjusting the counters offset */\r
+\r
+if(((Time.QuadPart + 1000000) < Counter.QuadPart) ||\r
+((Time.QuadPart - 1000000) > Counter.QuadPart))\r
+{ /* Adjust the offset */\r
+Offset.QuadPart += Time.QuadPart - Counter.QuadPart;\r
+Counter.QuadPart = Time.QuadPart;\r
+}\r
+\r
+/* Now let's use the adjusted performance counter time for the time stamp */\r
+CurrentTime.dwLowDateTime = Counter.LowPart;\r
+CurrentTime.dwHighDateTime = Counter.HighPart;\r
+}\r
+else\r
+{\r
+GetSystemTimeAsFileTime(&CurrentTime);\r
+}\r
+\r
+FileTimeToTimeval(&CurrentTime,ptv);\r
+\r
+Exit:;\r
+return(0);\r
+}/* int gettimeofday(struct timeval *ptv, void *tzp) */\r
+/*****************************************************************************/\r
+\r
+\r
+#ifndef getpid\r
+#define getpid() GetCurrentProcessId()\r
+#endif\r
+\r
+#define sleep(sec) SleepEx((sec)*1000,TRUE)\r
+#define usleep(usec) SleepEx(usec/1000,TRUE)\r
+//#define MT_ALIGN8    __declspec(align(8))\r
+/* Verify the correct ETIMEDOUT value is defined in all compiled files */\r
+#ifndef ETIMEDOUT\r
+#define ETIMEDOUT              (10060)\r
+#endif\r
+\r
+#ifndef strtoull \r
+#define strtoull _strtoui64\r
+#endif\r
+\r
+#define OSM_MAX_LOG_NAME_SIZE 2048\r
+#define unlink(str) _unlink(str)\r
+#define strnicmp _strnicmp\r
+\r
+/* The following defines replace syslog.h */\r
+#define openlog(a,b,c)\r
+\r
+#define closelog()\r
+\r
+static __inline void\r
+syslog(int priority, ...) {}\r
+\r
+#define LOG_INFO 0\r
+#define LOG_WARNING 1\r
+#define LOG_ERR 2\r
+/*****************************************/\r
+\r
+/****f* OpenSM: osm_common/GetOsmTempPath\r
+* NAME\r
+*      GetOsmTempPath\r
+*\r
+* DESCRIPTION\r
+*      The function retrieves the temp path defined in Windows using its API\r
+*\r
+* SYNOPSIS\r
+*/\r
+char*\r
+GetOsmTempPath(void);\r
+/*\r
+* PARAMETERS\r
+*      NONE\r
+*\r
+* RETURN VALUE\r
+*      This function returns string containing the default temp path in windows\r
+*\r
+* NOTES\r
+*/\r
+\r
+/****f* OpenSM: osm_common/GetOsmCachePath\r
+* NAME\r
+*      GetOsmCachePath\r
+*\r
+* DESCRIPTION\r
+*      The function retrieves the path the cache directory. This directory is \r
+*  the etc dir under the installation directory of the mellanox stack. \r
+*  The installation directory should be pointed out by the WinIB_HOME variable.\r
+*  If WinIB_HOME variable is missing, or there is not /etc/ dir under it - then\r
+*  the function will return the getOsmTempPath() value.\r
+*\r
+* SYNOPSIS\r
+*/\r
+char*\r
+GetOsmCachePath(void);\r
+/*\r
+* PARAMETERS\r
+*      NONE\r
+*\r
+* RETURN VALUE\r
+*      This function returns string containing the default cache path for osm use.\r
+*\r
+* NOTES\r
+*/\r
+\r
+/* Implementation of strtok_r for windows: since strtok in windows is safe,\r
+   just ignore the last variable, and call strtok. */\r
+static inline \r
+char *strtok_r(char *s1, const char *s2, char **lasts)\r
+{\r
+  return strtok(s1, s2);\r
+}\r
+#endif         /* _OSM_COMMON_H_ */\r
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/Makefile b/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/Makefile
new file mode 100644 (file)
index 0000000..5818975
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source
+# file to this component.  This file merely indirects to the real make file
+# that is shared by all the driver components of the Windows NT DDK
+#
+
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/SOURCES b/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/SOURCES
new file mode 100644 (file)
index 0000000..4735040
--- /dev/null
@@ -0,0 +1,62 @@
+!if $(FREEBUILD)\r
+TARGETNAME=opensm_ibal\r
+!else\r
+TARGETNAME=opensm_ibald\r
+!endif\r
+TARGETTYPE=LIBRARY\r
+\r
+!if !defined(WINIBHOME)\r
+WINIBHOME=..\..\..\..\r
+!endif\r
+\r
+LIBPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)\r
+\r
+!if defined(OSM_TARGET)\r
+TARGETPATH=$(OSM_TARGET)\bin\user\obj$(BUILD_ALT_DIR)\r
+!else\r
+TARGETPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)\r
+!endif\r
+\r
+USE_NTDLL=1\r
+OVR_DIR=..\addon\r
+\r
+\r
+SOURCES=\\r
+   osm_log.c \\r
+   osm_mad_pool.c \\r
+   osm_helper.c\r
+\r
+OSM_HOME=..\r
+\r
+TARGETLIBS=\\r
+!if $(FREEBUILD)\r
+                       $(LIBPATH)\*\ibal.lib \\r
+                       $(LIBPATH)\*\complib.lib \\r
+                       $(TARGETPATH)\*\osmv_ibal_3_0_0.lib\r
+\r
+!else\r
+                       $(LIBPATH)\*\ibald.lib \\r
+                       $(LIBPATH)\*\complibd.lib \\r
+                       $(TARGETPATH)\*\osmv_ibal_3_0_0d.lib\r
+!endif\r
+\r
+#DO NOT TOUCH the order of search path , until ib_types.h merging process will be done\r
+INCLUDES= \\r
+       $(OSM_HOME)\include; \\r
+       $(OSM_HOME); \\r
+       $(WINIBHOME)\inc; \\r
+       $(WINIBHOME)\inc\user;\r
+\r
+# Could be any special flag needed for this project \r
+USER_C_FLAGS=$(USER_C_FLAGS) /MD\r
+#Add preproccessor definitions\r
+C_DEFINES=$(C_DEFINES) -DWIN32 -D__WIN__ -D__i386__ -Dinline=__inline -DMT_LITTLE_ENDIAN -DOSM_VENDOR_INTF_AL\r
+C_DEFINES=$(C_DEFINES) -I.. -DHAVE_CONFIG_H\r
+!if !$(FREEBUILD)\r
+#C_DEFINES=$(C_DEFINES) -D_DEBUG -DDEBUG -DDBG\r
+C_DEFINES=$(C_DEFINES) \r
+!endif\r
+\r
+LINKER_FLAGS= $(LINKER_FLAGS)\r
+MSC_WARNING_LEVEL= /W3\r
+#MSC_OPTIMIZATION= /O0\r
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/osm_helper.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/osm_helper.c
new file mode 100644 (file)
index 0000000..11912fc
--- /dev/null
@@ -0,0 +1,2534 @@
+/*\r
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.\r
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.\r
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: osm_helper.c 1930 2009-02-04 15:26:22Z tzachid $\r
+ */\r
+\r
+\r
+\r
+/*\r
+ * Abstract:\r
+ *    Implementation of opensm helper functions.\r
+ *\r
+ * Environment:\r
+ *    Linux User Mode\r
+ *\r
+ * $Revision: 1.19 $\r
+ */\r
+\r
+#if HAVE_CONFIG_H\r
+#  include <config.h>\r
+#endif /* HAVE_CONFIG_H */\r
+\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <complib/cl_debug.h>\r
+#include <iba/ib_types.h>\r
+#include <opensm/osm_helper.h>\r
+#include <opensm/osm_log.h>\r
+\r
+#define LINE_LENGTH 256\r
+\r
+/* we use two tables - one for queries and one for responses */\r
+const char* const __ib_sa_method_str[] =\r
+{\r
+  "RESERVED",                 /* 0 */\r
+  "SubnAdmGet",             /* 1 */\r
+  "SubnAdmSet",             /* 2 */\r
+  "RESERVED",                  /* 3 */\r
+  "RESERVED",                  /* 4 */\r
+  "RESERVED",                  /* 5 */\r
+  "SubnAdmReport",          /* 6 */\r
+  "RESERVED",                  /* 7 */\r
+  "RESERVED",                  /* 8 */\r
+  "RESERVED",                  /* 9 */\r
+  "RESERVED",                  /* A */\r
+  "RESERVED",                  /* B */\r
+  "RESERVED",                  /* C */\r
+  "RESERVED",                  /* D */\r
+  "RESERVED",                  /* E */\r
+  "RESERVED",                  /* F */\r
+  "RESERVED",                  /* 10 */\r
+  "RESERVED",                  /* 11 */\r
+  "SubnAdmGetTable",           /* 12 */\r
+  "SubnAdmGetTraceTable",      /* 13 */\r
+  "SubnAdmGetMulti",           /* 14 */\r
+  "SubnAdmDelete",          /* 15 */\r
+  "UNKNOWN"                   /* 16 */\r
+};\r
+\r
+const char* const __ib_sa_resp_method_str[] =\r
+{\r
+  "RESERVED",                 /* 80 */\r
+  "SubnAdmGetResp",            /* 81 */\r
+  "RESERVED (SetResp?)",    /* 82 */\r
+  "RESERVED",                  /* 83 */\r
+  "RESERVED",                  /* 84 */\r
+  "RESERVED",                  /* 85 */\r
+  "SubnAdmReportResp",         /* 86 */\r
+  "RESERVED",                  /* 87 */\r
+  "RESERVED",                  /* 88 */\r
+  "RESERVED",                  /* 89 */\r
+  "RESERVED",                  /* 8A */\r
+  "RESERVED",                  /* 8B */\r
+  "RESERVED",                  /* 8C */\r
+  "RESERVED",                  /* 8D */\r
+  "RESERVED",                  /* 8E */\r
+  "RESERVED",                  /* 8F */\r
+  "RESERVED",                  /* 90 */\r
+  "RESERVED",                  /* 91 */\r
+  "SubnAdmGetTableResp",       /* 92 */\r
+  "RESERVED",                  /* 93 */\r
+  "SubnAdmGetMultiResp",    /* 94 */\r
+  "SubnAdmDeleteResp",         /* 95 */\r
+  "UNKNOWN"\r
+};\r
+\r
+#define OSM_SA_METHOD_STR_UNKNOWN_VAL 0x16\r
+\r
+const char* const __ib_sm_method_str[] =\r
+{\r
+  "RESERVED0",              /* 0 */\r
+  "SubnGet",              /* 1 */\r
+  "SubnSet",              /* 2 */\r
+  "RESERVED3",               /* 3 */\r
+  "RESERVED4",               /* 4 */\r
+  "SubnTrap",                /* 5 */\r
+  "RESERVED6",               /* 6 */\r
+  "SubnTrapRepress",         /* 7 */\r
+  "RESERVED8",               /* 8 */\r
+  "RESERVED9",               /* 9 */\r
+  "RESERVEDA",               /* A */\r
+  "RESERVEDB",               /* B */\r
+  "RESERVEDC",               /* C */\r
+  "RESERVEDD",               /* D */\r
+  "RESERVEDE",               /* E */\r
+  "RESERVEDF",               /* F */\r
+  "RESERVED10",              /* 10 */\r
+  "SubnGetResp",             /* 11 */\r
+  "RESERVED12",           /* 12 */\r
+  "RESERVED13",           /* 13 */\r
+  "RESERVED14",           /* 14 */\r
+  "RESERVED15",           /* 15 */\r
+  "RESERVED16",              /* 16 */\r
+  "RESERVED17",           /* 17 */\r
+  "RESERVED18",           /* 18 */\r
+  "RESERVED19",           /* 19 */\r
+  "RESERVED1A",           /* 1A */\r
+  "RESERVED1B",           /* 1B */\r
+  "RESERVED1C",           /* 1C */\r
+  "RESERVED1D",           /* 1D */\r
+  "RESERVED1E",             /* 1E */\r
+  "RESERVED1F",             /* 1F */\r
+  "UNKNOWN"                  /* 20 */\r
+};\r
+\r
+#define OSM_SM_METHOD_STR_UNKNOWN_VAL 0x21\r
+\r
+const char* const __ib_sm_attr_str[] =\r
+{\r
+  "RESERVED",                  /* 0 */\r
+  "ClassPortInfo",             /* 1 */\r
+  "Notice",                    /* 2 */\r
+  "InformInfo",                /* 3 */\r
+  "RESERVED",                  /* 4 */\r
+  "RESERVED",                  /* 5 */\r
+  "RESERVED",                  /* 6 */\r
+  "RESERVED",                  /* 7 */\r
+  "RESERVED",                  /* 8 */\r
+  "RESERVED",                  /* 9 */\r
+  "RESERVED",                  /* A */\r
+  "RESERVED",                  /* B */\r
+  "RESERVED",                  /* C */\r
+  "RESERVED",                  /* D */\r
+  "RESERVED",                  /* E */\r
+  "RESERVED",                  /* F */\r
+  "NodeDescription",           /* 10 */\r
+  "NodeInfo",                  /* 11 */\r
+  "SwitchInfo",                /* 12 */\r
+  "UNKNOWN",                   /* 13 */\r
+  "GUIDInfo",                  /* 14 */\r
+  "PortInfo",                  /* 15 */\r
+  "P_KeyTable",                /* 16 */\r
+  "SLtoVLMappingTable",        /* 17 */\r
+  "VLArbitrationTable",        /* 18 */\r
+  "LinearForwardingTable",     /* 19 */\r
+  "RandomForwardingTable",     /* 1A */\r
+  "MulticastForwardingTable",  /* 1B */\r
+  "UNKNOWN",                   /* 1C */\r
+  "UNKNOWN",                   /* 1D */\r
+  "UNKNOWN",                   /* 1E */\r
+  "UNKNOWN",                   /* 1F */\r
+  "SMInfo",                    /* 20 */\r
+  "UNKNOWN"                    /* 21 - always highest value */\r
+};\r
+\r
+#define OSM_SM_ATTR_STR_UNKNOWN_VAL 0x21\r
+\r
+const char* const __ib_sa_attr_str[] =\r
+{\r
+  "RESERVED",                  /* 0 */\r
+  "ClassPortInfo",             /* 1 */\r
+  "Notice",                    /* 2 */\r
+  "InformInfo",                /* 3 */\r
+  "RESERVED",                  /* 4 */\r
+  "RESERVED",                  /* 5 */\r
+  "RESERVED",                  /* 6 */\r
+  "RESERVED",                  /* 7 */\r
+  "RESERVED",                  /* 8 */\r
+  "RESERVED",                  /* 9 */\r
+  "RESERVED",                  /* A */\r
+  "RESERVED",                  /* B */\r
+  "RESERVED",                  /* C */\r
+  "RESERVED",                  /* D */\r
+  "RESERVED",                  /* E */\r
+  "RESERVED",                  /* F */\r
+  "RESERVED",                  /* 10 */\r
+  "NodeRecord",                /* 11 */\r
+  "PortInfoRecord",            /* 12 */\r
+  "SLtoVLMappingTableRecord",  /* 13 */\r
+  "SwitchInfoRecord",          /* 14 */\r
+  "LinearForwardingTableRecord", /* 15 */\r
+  "RandomForwardingTableRecord", /* 16 */\r
+  "MulticastForwardingTableRecord",  /* 17 */\r
+  "SMInfoRecord",              /* 18 */\r
+  "RESERVED",                  /* 19 */\r
+  "RandomForwardingTable",     /* 1A */\r
+  "MulticastForwardingTable",  /* 1B */\r
+  "UNKNOWN",                   /* 1C */\r
+  "UNKNOWN",                   /* 1D */\r
+  "UNKNOWN",                   /* 1E */\r
+  "UNKNOWN",                   /* 1F */\r
+  "LinkRecord",                /* 20 */\r
+  "UNKNOWN",                   /* 21 */\r
+  "UNKNOWN",                   /* 22 */\r
+  "UNKNOWN",                   /* 23 */\r
+  "UNKNOWN",                   /* 24 */\r
+  "UNKNOWN",                   /* 25 */\r
+  "UNKNOWN",                   /* 26 */\r
+  "UNKNOWN",                   /* 27 */\r
+  "UNKNOWN",                   /* 28 */\r
+  "UNKNOWN",                   /* 29 */\r
+  "UNKNOWN",                   /* 2A */\r
+  "UNKNOWN",                   /* 2B */\r
+  "UNKNOWN",                   /* 2C */\r
+  "UNKNOWN",                   /* 2D */\r
+  "UNKNOWN",                   /* 2E */\r
+  "UNKNOWN",                   /* 2F */\r
+  "GuidInfoRecord",            /* 30 */\r
+  "ServiceRecord",             /* 31 */\r
+  "UNKNOWN",                   /* 32 */\r
+  "P_KeyTableRecord",          /* 33 */\r
+  "UNKNOWN",                   /* 34 */\r
+  "PathRecord",                /* 35 */\r
+  "VLArbitrationTableRecord",  /* 36 */\r
+  "UNKNOWN",                   /* 37 */\r
+  "MCMemberRecord",            /* 38 */\r
+  "TraceRecord",               /* 39 */\r
+  "MultiPathRecord",           /* 3A */\r
+  "ServiceAssociationRecord",  /* 3B */\r
+  "UNKNOWN",                   /* 3C */\r
+  "UNKNOWN",                   /* 3D */\r
+  "UNKNOWN",                   /* 3E */\r
+  "UNKNOWN",                   /* 3F */\r
+  "UNKNOWN",                   /* 40 */\r
+  "UNKNOWN",                   /* 41 */\r
+  "UNKNOWN",                   /* 42 */\r
+  "UNKNOWN",                   /* 43 */\r
+  "UNKNOWN",                   /* 44 */\r
+  "UNKNOWN",                   /* 45 */\r
+  "UNKNOWN",                   /* 46 */\r
+  "UNKNOWN",                   /* 47 */\r
+  "UNKNOWN",                   /* 48 */\r
+  "UNKNOWN",                   /* 49 */\r
+  "UNKNOWN",                   /* 4A */\r
+  "UNKNOWN",                   /* 4B */\r
+  "UNKNOWN",                   /* 4C */\r
+  "UNKNOWN",                   /* 4D */\r
+  "UNKNOWN",                   /* 4E */\r
+  "UNKNOWN",                   /* 4F */\r
+  "UNKNOWN",                   /* 50 */\r
+  "UNKNOWN",                   /* 51 */\r
+  "UNKNOWN",                   /* 52 */\r
+  "UNKNOWN",                   /* 53 */\r
+  "UNKNOWN",                   /* 54 */\r
+  "UNKNOWN",                   /* 55 */\r
+  "UNKNOWN",                   /* 56 */\r
+  "UNKNOWN",                   /* 57 */\r
+  "UNKNOWN",                   /* 58 */\r
+  "UNKNOWN",                   /* 59 */\r
+  "UNKNOWN",                   /* 5A */\r
+  "UNKNOWN",                   /* 5B */\r
+  "UNKNOWN",                   /* 5C */\r
+  "UNKNOWN",                   /* 5D */\r
+  "UNKNOWN",                   /* 5E */\r
+  "UNKNOWN",                   /* 5F */\r
+  "UNKNOWN",                   /* 60 */\r
+  "UNKNOWN",                   /* 61 */\r
+  "UNKNOWN",                   /* 62 */\r
+  "UNKNOWN",                   /* 63 */\r
+  "UNKNOWN",                   /* 64 */\r
+  "UNKNOWN",                   /* 65 */\r
+  "UNKNOWN",                   /* 66 */\r
+  "UNKNOWN",                   /* 67 */\r
+  "UNKNOWN",                   /* 68 */\r
+  "UNKNOWN",                   /* 69 */\r
+  "UNKNOWN",                   /* 6A */\r
+  "UNKNOWN",                   /* 6B */\r
+  "UNKNOWN",                   /* 6C */\r
+  "UNKNOWN",                   /* 6D */\r
+  "UNKNOWN",                   /* 6E */\r
+  "UNKNOWN",                   /* 6F */\r
+  "UNKNOWN",                   /* 70 */\r
+  "UNKNOWN",                   /* 71 */\r
+  "UNKNOWN",                   /* 72 */\r
+  "UNKNOWN",                   /* 73 */\r
+  "UNKNOWN",                   /* 74 */\r
+  "UNKNOWN",                   /* 75 */\r
+  "UNKNOWN",                   /* 76 */\r
+  "UNKNOWN",                   /* 77 */\r
+  "UNKNOWN",                   /* 78 */\r
+  "UNKNOWN",                   /* 79 */\r
+  "UNKNOWN",                   /* 7A */\r
+  "UNKNOWN",                   /* 7B */\r
+  "UNKNOWN",                   /* 7C */\r
+  "UNKNOWN",                   /* 7D */\r
+  "UNKNOWN",                   /* 7E */\r
+  "UNKNOWN",                   /* 7F */\r
+  "UNKNOWN",                   /* 80 */\r
+  "UNKNOWN",                   /* 81 */\r
+  "UNKNOWN",                   /* 82 */\r
+  "UNKNOWN",                   /* 83 */\r
+  "UNKNOWN",                   /* 84 */\r
+  "UNKNOWN",                   /* 85 */\r
+  "UNKNOWN",                   /* 86 */\r
+  "UNKNOWN",                   /* 87 */\r
+  "UNKNOWN",                   /* 88 */\r
+  "UNKNOWN",                   /* 89 */\r
+  "UNKNOWN",                   /* 8A */\r
+  "UNKNOWN",                   /* 8B */\r
+  "UNKNOWN",                   /* 8C */\r
+  "UNKNOWN",                   /* 8D */\r
+  "UNKNOWN",                   /* 8E */\r
+  "UNKNOWN",                   /* 8F */\r
+  "UNKNOWN",                   /* 90 */\r
+  "UNKNOWN",                   /* 91 */\r
+  "UNKNOWN",                   /* 92 */\r
+  "UNKNOWN",                   /* 93 */\r
+  "UNKNOWN",                   /* 94 */\r
+  "UNKNOWN",                   /* 95 */\r
+  "UNKNOWN",                   /* 96 */\r
+  "UNKNOWN",                   /* 97 */\r
+  "UNKNOWN",                   /* 98 */\r
+  "UNKNOWN",                   /* 99 */\r
+  "UNKNOWN",                   /* 9A */\r
+  "UNKNOWN",                   /* 9B */\r
+  "UNKNOWN",                   /* 9C */\r
+  "UNKNOWN",                   /* 9D */\r
+  "UNKNOWN",                   /* 9E */\r
+  "UNKNOWN",                   /* 9F */\r
+  "UNKNOWN",                   /* A0 */\r
+  "UNKNOWN",                   /* A1 */\r
+  "UNKNOWN",                   /* A2 */\r
+  "UNKNOWN",                   /* A3 */\r
+  "UNKNOWN",                   /* A4 */\r
+  "UNKNOWN",                   /* A5 */\r
+  "UNKNOWN",                   /* A6 */\r
+  "UNKNOWN",                   /* A7 */\r
+  "UNKNOWN",                   /* A8 */\r
+  "UNKNOWN",                   /* A9 */\r
+  "UNKNOWN",                   /* AA */\r
+  "UNKNOWN",                   /* AB */\r
+  "UNKNOWN",                   /* AC */\r
+  "UNKNOWN",                   /* AD */\r
+  "UNKNOWN",                   /* AE */\r
+  "UNKNOWN",                   /* AF */\r
+  "UNKNOWN",                   /* B0 */\r
+  "UNKNOWN",                   /* B1 */\r
+  "UNKNOWN",                   /* B2 */\r
+  "UNKNOWN",                   /* B3 */\r
+  "UNKNOWN",                   /* B4 */\r
+  "UNKNOWN",                   /* B5 */\r
+  "UNKNOWN",                   /* B6 */\r
+  "UNKNOWN",                   /* B7 */\r
+  "UNKNOWN",                   /* B8 */\r
+  "UNKNOWN",                   /* B9 */\r
+  "UNKNOWN",                   /* BA */\r
+  "UNKNOWN",                   /* BB */\r
+  "UNKNOWN",                   /* BC */\r
+  "UNKNOWN",                   /* BD */\r
+  "UNKNOWN",                   /* BE */\r
+  "UNKNOWN",                   /* BF */\r
+  "UNKNOWN",                   /* C0 */\r
+  "UNKNOWN",                   /* C1 */\r
+  "UNKNOWN",                   /* C2 */\r
+  "UNKNOWN",                   /* C3 */\r
+  "UNKNOWN",                   /* C4 */\r
+  "UNKNOWN",                   /* C5 */\r
+  "UNKNOWN",                   /* C6 */\r
+  "UNKNOWN",                   /* C7 */\r
+  "UNKNOWN",                   /* C8 */\r
+  "UNKNOWN",                   /* C9 */\r
+  "UNKNOWN",                   /* CA */\r
+  "UNKNOWN",                   /* CB */\r
+  "UNKNOWN",                   /* CC */\r
+  "UNKNOWN",                   /* CD */\r
+  "UNKNOWN",                   /* CE */\r
+  "UNKNOWN",                   /* CF */\r
+  "UNKNOWN",                   /* D0 */\r
+  "UNKNOWN",                   /* D1 */\r
+  "UNKNOWN",                   /* D2 */\r
+  "UNKNOWN",                   /* D3 */\r
+  "UNKNOWN",                   /* D4 */\r
+  "UNKNOWN",                   /* D5 */\r
+  "UNKNOWN",                   /* D6 */\r
+  "UNKNOWN",                   /* D7 */\r
+  "UNKNOWN",                   /* D8 */\r
+  "UNKNOWN",                   /* D9 */\r
+  "UNKNOWN",                   /* DA */\r
+  "UNKNOWN",                   /* DB */\r
+  "UNKNOWN",                   /* DC */\r
+  "UNKNOWN",                   /* DD */\r
+  "UNKNOWN",                   /* DE */\r
+  "UNKNOWN",                   /* DF */\r
+  "UNKNOWN",                   /* E0 */\r
+  "UNKNOWN",                   /* E1 */\r
+  "UNKNOWN",                   /* E2 */\r
+  "UNKNOWN",                   /* E3 */\r
+  "UNKNOWN",                   /* E4 */\r
+  "UNKNOWN",                   /* E5 */\r
+  "UNKNOWN",                   /* E6 */\r
+  "UNKNOWN",                   /* E7 */\r
+  "UNKNOWN",                   /* E8 */\r
+  "UNKNOWN",                   /* E9 */\r
+  "UNKNOWN",                   /* EA */\r
+  "UNKNOWN",                   /* EB */\r
+  "UNKNOWN",                   /* EC */\r
+  "UNKNOWN",                   /* ED */\r
+  "UNKNOWN",                   /* EE */\r
+  "UNKNOWN",                   /* EF */\r
+  "UNKNOWN",                   /* F0 */\r
+  "UNKNOWN",                   /* F1 */\r
+  "UNKNOWN",                   /* F2 */\r
+  "InformInfoRecord",          /* F3 */\r
+  "UNKNOWN"                    /* F4 - always highest value */\r
+};\r
+\r
+#define OSM_SA_ATTR_STR_UNKNOWN_VAL 0xF4\r
+\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+ib_get_sa_method_str(\r
+  IN uint8_t method )\r
+{\r
+  if (method & 0x80)\r
+  {\r
+    method = method & 0x7f;\r
+    if( method >= OSM_SA_METHOD_STR_UNKNOWN_VAL  )\r
+      method = OSM_SA_METHOD_STR_UNKNOWN_VAL;\r
+    /* it is a response - use the response table */\r
+    return( __ib_sa_resp_method_str[method] );\r
+  }\r
+  else\r
+  {\r
+    if( method >= OSM_SA_METHOD_STR_UNKNOWN_VAL  )\r
+      method = OSM_SA_METHOD_STR_UNKNOWN_VAL;\r
+    return( __ib_sa_method_str[method] );\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+ib_get_sm_method_str(\r
+  IN uint8_t method )\r
+{\r
+  if (method & 0x80) method = (method & 0x0F) | 0x10;\r
+  if( method >= OSM_SM_METHOD_STR_UNKNOWN_VAL  )\r
+    method = OSM_SM_METHOD_STR_UNKNOWN_VAL;\r
+  return( __ib_sm_method_str[method] );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+ib_get_sm_attr_str(\r
+  IN ib_net16_t attr )\r
+{\r
+  uint16_t host_attr;\r
+  host_attr = cl_ntoh16( attr );\r
+\r
+  if( host_attr >= OSM_SM_ATTR_STR_UNKNOWN_VAL  )\r
+    host_attr = OSM_SM_ATTR_STR_UNKNOWN_VAL;\r
+\r
+  return( __ib_sm_attr_str[host_attr] );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+ib_get_sa_attr_str(\r
+  IN ib_net16_t attr )\r
+{\r
+  uint16_t host_attr;\r
+  host_attr = cl_ntoh16( attr );\r
+\r
+  if( host_attr >= OSM_SA_ATTR_STR_UNKNOWN_VAL  )\r
+    host_attr = OSM_SA_ATTR_STR_UNKNOWN_VAL;\r
+\r
+  return( __ib_sa_attr_str[host_attr] );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osm_dbg_do_line(\r
+  IN char** pp_local,\r
+  IN const uint32_t buf_size,\r
+  IN const char* const p_prefix_str,\r
+  IN const char* const p_new_str,\r
+  IN uint32_t* const p_total_len )\r
+{\r
+  char line[LINE_LENGTH];\r
+  uint32_t len;\r
+\r
+  sprintf( line, "%s%s", p_prefix_str, p_new_str );\r
+  len = (uint32_t) strlen( line );\r
+  *p_total_len += len;\r
+  if( *p_total_len + sizeof('\0') > buf_size )\r
+    return( IB_INSUFFICIENT_MEMORY );\r
+\r
+  strcpy( *pp_local, line );\r
+  *pp_local += len;\r
+  return( IB_SUCCESS );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dbg_get_capabilities_str(\r
+  IN char* p_buf,\r
+  IN const uint32_t buf_size,\r
+  IN const char* const p_prefix_str,\r
+  IN const ib_port_info_t* const p_pi )\r
+{\r
+  uint32_t total_len = 0;\r
+  char *p_local = p_buf;\r
+\r
+  strcpy( p_local, "Capability Mask:\n" );\r
+  p_local += strlen( p_local );\r
+\r
+  if( p_pi->capability_mask & IB_PORT_CAP_RESV0 )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_RESV0\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_IS_SM )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_IS_SM\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_NOTICE )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_HAS_NOTICE\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_TRAP )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_HAS_TRAP\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_IPD )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_HAS_IPD\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_AUTO_MIG )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_HAS_AUTO_MIG\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_SL_MAP )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_HAS_SL_MAP\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_NV_MKEY )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_HAS_NV_MKEY\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_NV_PKEY )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_HAS_NV_PKEY\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_LED_INFO )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_HAS_LED_INFO\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_SM_DISAB )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_SM_DISAB\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_SYS_IMG_GUID )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_HAS_SYS_IMG_GUID\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_PKEY_SW_EXT_PORT_TRAP )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_PKEY_SW_EXT_PORT_TRAP\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_RESV13 )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_RESV13\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_RESV14 )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_RESV14\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_RESV15 )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_RESV15\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_COM_MGT )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_HAS_COM_MGT\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_SNMP )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_HAS_SNMP\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_REINIT )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_REINIT\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_DEV_MGT )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_HAS_DEV_MGT\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_VEND_CLS )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_HAS_VEND_CLS\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_DR_NTC )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_HAS_DR_NTC\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_CAP_NTC )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_HAS_CAP_NTC\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_BM )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_HAS_BM\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_LINK_RT_LATENCY )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_HAS_LINK_RT_LATENCY\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_CLIENT_REREG )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_HAS_CLIENT_REREG\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_RESV26 )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_RESV26\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_RESV27 )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_RESV27\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_RESV28)\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_RESV28\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_RESV29 )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_RESV29\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_RESV30 )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_RESV30\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+  if( p_pi->capability_mask & IB_PORT_CAP_RESV31 )\r
+  {\r
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+                         "IB_PORT_CAP_RESV31\n", &total_len ) != IB_SUCCESS )\r
+      return;\r
+  }\r
+\r
+  return;\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_port_info(\r
+  IN osm_log_t* const p_log,\r
+  IN const ib_net64_t node_guid,\r
+  IN const ib_net64_t port_guid,\r
+  IN const uint8_t port_num,\r
+  IN const ib_port_info_t* const p_pi,\r
+  IN const osm_log_level_t log_level )\r
+{\r
+  char buf[BUF_SIZE];\r
+\r
+  if( osm_log_is_active( p_log, log_level ) )\r
+  {\r
+    osm_log( p_log, log_level,\r
+             "PortInfo dump:\n"\r
+             "\t\t\t\tport number.............0x%X\n"\r
+             "\t\t\t\tnode_guid...............0x%016" PRIx64 "\n"\r
+             "\t\t\t\tport_guid...............0x%016" PRIx64 "\n"\r
+             "\t\t\t\tm_key...................0x%016" PRIx64 "\n"\r
+             "\t\t\t\tsubnet_prefix...........0x%016" PRIx64 "\n"\r
+             "\t\t\t\tbase_lid................0x%X\n"\r
+             "\t\t\t\tmaster_sm_base_lid......0x%X\n"\r
+             "\t\t\t\tcapability_mask.........0x%X\n"\r
+             "\t\t\t\tdiag_code...............0x%X\n"\r
+             "\t\t\t\tm_key_lease_period......0x%X\n"\r
+             "\t\t\t\tlocal_port_num..........0x%X\n"\r
+             "\t\t\t\tlink_width_enabled......0x%X\n"\r
+             "\t\t\t\tlink_width_supported....0x%X\n"\r
+             "\t\t\t\tlink_width_active.......0x%X\n"\r
+             "\t\t\t\tlink_speed_supported....0x%X\n"\r
+             "\t\t\t\tport_state..............%s\n"\r
+             "\t\t\t\tstate_info2.............0x%X\n"\r
+             "\t\t\t\tm_key_protect_bits......0x%X\n"\r
+             "\t\t\t\tlmc.....................0x%X\n"\r
+             "\t\t\t\tlink_speed..............0x%X\n"\r
+             "\t\t\t\tmtu_smsl................0x%X\n"\r
+             "\t\t\t\tvl_cap_init_type........0x%X\n"\r
+             "\t\t\t\tvl_high_limit...........0x%X\n"\r
+             "\t\t\t\tvl_arb_high_cap.........0x%X\n"\r
+             "\t\t\t\tvl_arb_low_cap..........0x%X\n"\r
+             "\t\t\t\tinit_rep_mtu_cap........0x%X\n"\r
+             "\t\t\t\tvl_stall_life...........0x%X\n"\r
+             "\t\t\t\tvl_enforce..............0x%X\n"\r
+             "\t\t\t\tm_key_violations........0x%X\n"\r
+             "\t\t\t\tp_key_violations........0x%X\n"\r
+             "\t\t\t\tq_key_violations........0x%X\n"\r
+             "\t\t\t\tguid_cap................0x%X\n"\r
+             "\t\t\t\tclient_reregister.......0x%X\n"\r
+             "\t\t\t\tsubnet_timeout..........0x%X\n"\r
+             "\t\t\t\tresp_time_value.........0x%X\n"\r
+             "\t\t\t\terror_threshold.........0x%X\n"\r
+             "",\r
+             port_num,\r
+             cl_ntoh64( node_guid ),\r
+             cl_ntoh64( port_guid ),\r
+             cl_ntoh64( p_pi->m_key ),\r
+             cl_ntoh64( p_pi->subnet_prefix ),\r
+             cl_ntoh16( p_pi->base_lid ),\r
+             cl_ntoh16( p_pi->master_sm_base_lid ),\r
+             cl_ntoh32( p_pi->capability_mask ),\r
+             cl_ntoh16( p_pi->diag_code ),\r
+             cl_ntoh16( p_pi->m_key_lease_period ),\r
+             p_pi->local_port_num,\r
+             p_pi->link_width_enabled,\r
+             p_pi->link_width_supported,\r
+             p_pi->link_width_active,\r
+             ib_port_info_get_link_speed_sup( p_pi ),\r
+             ib_get_port_state_str( ib_port_info_get_port_state( p_pi ) ),\r
+             p_pi->state_info2,\r
+             ib_port_info_get_mpb( p_pi ),\r
+             ib_port_info_get_lmc( p_pi ),\r
+             p_pi->link_speed,\r
+             p_pi->mtu_smsl,\r
+             p_pi->vl_cap,\r
+             p_pi->vl_high_limit,\r
+             p_pi->vl_arb_high_cap,\r
+             p_pi->vl_arb_low_cap,\r
+             p_pi->mtu_cap,\r
+             p_pi->vl_stall_life,\r
+             p_pi->vl_enforce,\r
+             cl_ntoh16( p_pi->m_key_violations ),\r
+             cl_ntoh16( p_pi->p_key_violations ),\r
+             cl_ntoh16( p_pi->q_key_violations ),\r
+             p_pi->guid_cap,\r
+             ib_port_info_get_client_rereg( p_pi ),\r
+             ib_port_info_get_timeout( p_pi ),\r
+             p_pi->resp_time_value,\r
+             p_pi->error_threshold\r
+             );\r
+\r
+    /*  show the capabilities mask */\r
+    osm_dbg_get_capabilities_str( buf, BUF_SIZE, "\t\t\t\t", p_pi );\r
+\r
+    osm_log( p_log, log_level, "%s", buf );\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_portinfo_record(\r
+  IN osm_log_t* const p_log,\r
+  IN const ib_portinfo_record_t* const p_pir,\r
+  IN const osm_log_level_t log_level )\r
+{\r
+  char buf[BUF_SIZE];\r
+  const ib_port_info_t * const p_pi = &p_pir->port_info;\r
+\r
+  if( osm_log_is_active( p_log, log_level ) )\r
+  {\r
+    osm_log( p_log, log_level,\r
+             "PortInfo Record dump:\n"\r
+             "\t\t\t\tRID\n"\r
+             "\t\t\t\tEndPortLid..............0x%X\n"\r
+             "\t\t\t\tPortNum.................0x%X\n"\r
+             "\t\t\t\tReserved................0x%X\n"\r
+             "\t\t\t\tPortInfo dump:\n"\r
+             "\t\t\t\tm_key...................0x%016" PRIx64 "\n"\r
+             "\t\t\t\tsubnet_prefix...........0x%016" PRIx64 "\n"\r
+             "\t\t\t\tbase_lid................0x%X\n"\r
+             "\t\t\t\tmaster_sm_base_lid......0x%X\n"\r
+             "\t\t\t\tcapability_mask.........0x%X\n"\r
+             "\t\t\t\tdiag_code...............0x%X\n"\r
+             "\t\t\t\tm_key_lease_period......0x%X\n"\r
+             "\t\t\t\tlocal_port_num..........0x%X\n"\r
+             "\t\t\t\tlink_width_enabled......0x%X\n"\r
+             "\t\t\t\tlink_width_supported....0x%X\n"\r
+             "\t\t\t\tlink_width_active.......0x%X\n"\r
+             "\t\t\t\tlink_speed_supported....0x%X\n"\r
+             "\t\t\t\tport_state..............%s\n"\r
+             "\t\t\t\tstate_info2.............0x%X\n"\r
+             "\t\t\t\tm_key_protect_bits......0x%X\n"\r
+             "\t\t\t\tlmc.....................0x%X\n"\r
+             "\t\t\t\tlink_speed..............0x%X\n"\r
+             "\t\t\t\tmtu_smsl................0x%X\n"\r
+             "\t\t\t\tvl_cap_init_type........0x%X\n"\r
+             "\t\t\t\tvl_high_limit...........0x%X\n"\r
+             "\t\t\t\tvl_arb_high_cap.........0x%X\n"\r
+             "\t\t\t\tvl_arb_low_cap..........0x%X\n"\r
+             "\t\t\t\tinit_rep_mtu_cap........0x%X\n"\r
+             "\t\t\t\tvl_stall_life...........0x%X\n"\r
+             "\t\t\t\tvl_enforce..............0x%X\n"\r
+             "\t\t\t\tm_key_violations........0x%X\n"\r
+             "\t\t\t\tp_key_violations........0x%X\n"\r
+             "\t\t\t\tq_key_violations........0x%X\n"\r
+             "\t\t\t\tguid_cap................0x%X\n"\r
+             "\t\t\t\tsubnet_timeout..........0x%X\n"\r
+             "\t\t\t\tresp_time_value.........0x%X\n"\r
+             "\t\t\t\terror_threshold.........0x%X\n"\r
+             "",\r
+             cl_ntoh16(p_pir->lid),\r
+             p_pir->port_num,\r
+             p_pir->resv,\r
+             cl_ntoh64( p_pi->m_key ),\r
+             cl_ntoh64( p_pi->subnet_prefix ),\r
+             cl_ntoh16( p_pi->base_lid ),\r
+             cl_ntoh16( p_pi->master_sm_base_lid ),\r
+             cl_ntoh32( p_pi->capability_mask ),\r
+             cl_ntoh16( p_pi->diag_code ),\r
+             cl_ntoh16( p_pi->m_key_lease_period ),\r
+             p_pi->local_port_num,\r
+             p_pi->link_width_enabled,\r
+             p_pi->link_width_supported,\r
+             p_pi->link_width_active,\r
+             ib_port_info_get_link_speed_sup( p_pi ),\r
+             ib_get_port_state_str( ib_port_info_get_port_state( p_pi ) ),\r
+             p_pi->state_info2,\r
+             ib_port_info_get_mpb( p_pi ),\r
+             ib_port_info_get_lmc( p_pi ),\r
+             p_pi->link_speed,\r
+             p_pi->mtu_smsl,\r
+             p_pi->vl_cap,\r
+             p_pi->vl_high_limit,\r
+             p_pi->vl_arb_high_cap,\r
+             p_pi->vl_arb_low_cap,\r
+             p_pi->mtu_cap,\r
+             p_pi->vl_stall_life,\r
+             p_pi->vl_enforce,\r
+             cl_ntoh16( p_pi->m_key_violations ),\r
+             cl_ntoh16( p_pi->p_key_violations ),\r
+             cl_ntoh16( p_pi->q_key_violations ),\r
+             p_pi->guid_cap,\r
+             ib_port_info_get_timeout( p_pi ),\r
+             p_pi->resp_time_value,\r
+             p_pi->error_threshold\r
+             );\r
+\r
+    /*  show the capabilities mask */\r
+    osm_dbg_get_capabilities_str( buf, BUF_SIZE, "\t\t\t\t", p_pi );\r
+\r
+    osm_log( p_log, log_level, "%s", buf );\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_guidinfo_record(\r
+  IN osm_log_t* const p_log,\r
+  IN const ib_guidinfo_record_t* const p_gir,\r
+  IN const osm_log_level_t log_level )\r
+{\r
+  const ib_guid_info_t * const p_gi = &p_gir->guid_info;\r
+\r
+  if( osm_log_is_active( p_log, log_level ) )\r
+  {\r
+    osm_log( p_log, log_level,\r
+             "GUIDInfo Record dump:\n"\r
+             "\t\t\t\tRID\n"\r
+             "\t\t\t\tLid.....................0x%X\n"\r
+             "\t\t\t\tBlockNum................0x%X\n"\r
+             "\t\t\t\tReserved................0x%X\n"\r
+             "\t\t\t\tGUIDInfo dump:\n"\r
+             "\t\t\t\tReserved................0x%X\n"\r
+             "\t\t\t\tGUID 0..................0x%016" PRIx64 "\n"\r
+             "\t\t\t\tGUID 1..................0x%016" PRIx64 "\n"\r
+             "\t\t\t\tGUID 2..................0x%016" PRIx64 "\n"\r
+             "\t\t\t\tGUID 3..................0x%016" PRIx64 "\n"\r
+             "\t\t\t\tGUID 4..................0x%016" PRIx64 "\n"\r
+             "\t\t\t\tGUID 5..................0x%016" PRIx64 "\n"\r
+             "\t\t\t\tGUID 6..................0x%016" PRIx64 "\n"\r
+             "\t\t\t\tGUID 7..................0x%016" PRIx64 "\n",\r
+             cl_ntoh16(p_gir->lid),\r
+             p_gir->block_num,\r
+             p_gir->resv,\r
+             cl_ntoh32(p_gir->reserved),\r
+             cl_ntoh64(p_gi->guid[0]),\r
+             cl_ntoh64(p_gi->guid[1]),\r
+             cl_ntoh64(p_gi->guid[2]),\r
+             cl_ntoh64(p_gi->guid[3]),\r
+             cl_ntoh64(p_gi->guid[4]),\r
+             cl_ntoh64(p_gi->guid[5]),\r
+             cl_ntoh64(p_gi->guid[6]),\r
+             cl_ntoh64(p_gi->guid[7])\r
+           );\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_node_info(\r
+  IN osm_log_t* const p_log,\r
+  IN const ib_node_info_t* const p_ni,\r
+  IN const osm_log_level_t log_level )\r
+{\r
+  if( osm_log_is_active( p_log, log_level ) )\r
+  {\r
+    osm_log( p_log, log_level,\r
+             "NodeInfo dump:\n"\r
+             "\t\t\t\tbase_version............0x%X\n"\r
+             "\t\t\t\tclass_version...........0x%X\n"\r
+             "\t\t\t\tnode_type...............%s\n"\r
+             "\t\t\t\tnum_ports...............0x%X\n"\r
+             "\t\t\t\tsys_guid................0x%016" PRIx64 "\n"\r
+             "\t\t\t\tnode_guid...............0x%016" PRIx64 "\n"\r
+             "\t\t\t\tport_guid...............0x%016" PRIx64 "\n"\r
+             "\t\t\t\tpartition_cap...........0x%X\n"\r
+             "\t\t\t\tdevice_id...............0x%X\n"\r
+             "\t\t\t\trevision................0x%X\n"\r
+             "\t\t\t\tport_num................0x%X\n"\r
+             "\t\t\t\tvendor_id...............0x%X\n"\r
+             "",\r
+             p_ni->base_version,\r
+             p_ni->class_version,\r
+             ib_get_node_type_str( p_ni->node_type ),\r
+             p_ni->num_ports,\r
+             cl_ntoh64( p_ni->sys_guid ),\r
+             cl_ntoh64( p_ni->node_guid ),\r
+             cl_ntoh64( p_ni->port_guid ),\r
+             cl_ntoh16( p_ni->partition_cap ),\r
+             cl_ntoh16( p_ni->device_id ),\r
+             cl_ntoh32( p_ni->revision ),\r
+             ib_node_info_get_local_port_num( p_ni ),\r
+             cl_ntoh32( ib_node_info_get_vendor_id( p_ni ) )\r
+             );\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_node_record(\r
+  IN osm_log_t* const p_log,\r
+  IN const ib_node_record_t* const p_nr,\r
+  IN const osm_log_level_t log_level )\r
+{\r
+  const ib_node_info_t * const p_ni = &p_nr->node_info;\r
+\r
+  if( osm_log_is_active( p_log, log_level ) )\r
+  {\r
+    char desc[sizeof(p_nr->node_desc.description) + 1];\r
+\r
+    memcpy(desc, p_nr->node_desc.description,\r
+           sizeof(p_nr->node_desc.description));\r
+    desc[sizeof(desc) - 1] = '\0';\r
+    osm_log( p_log, log_level,\r
+             "Node Record dump:\n"\r
+             "\t\t\t\tRID\n"\r
+             "\t\t\t\tLid.....................0x%X\n"\r
+             "\t\t\t\tReserved................0x%X\n"\r
+             "\t\t\t\tNodeInfo dump:\n"\r
+             "\t\t\t\tbase_version............0x%X\n"\r
+             "\t\t\t\tclass_version...........0x%X\n"\r
+             "\t\t\t\tnode_type...............%s\n"\r
+             "\t\t\t\tnum_ports...............0x%X\n"\r
+             "\t\t\t\tsys_guid................0x%016" PRIx64 "\n"\r
+             "\t\t\t\tnode_guid...............0x%016" PRIx64 "\n"\r
+             "\t\t\t\tport_guid...............0x%016" PRIx64 "\n"\r
+             "\t\t\t\tpartition_cap...........0x%X\n"\r
+             "\t\t\t\tdevice_id...............0x%X\n"\r
+             "\t\t\t\trevision................0x%X\n"\r
+             "\t\t\t\tport_num................0x%X\n"\r
+             "\t\t\t\tvendor_id...............0x%X\n"\r
+             "\t\t\t\tNodeDescription\n"\r
+             "\t\t\t\t%s\n"\r
+             "",\r
+             cl_ntoh16(p_nr->lid),\r
+             cl_ntoh16(p_nr->resv),\r
+             p_ni->base_version,\r
+             p_ni->class_version,\r
+             ib_get_node_type_str( p_ni->node_type ),\r
+             p_ni->num_ports,\r
+             cl_ntoh64( p_ni->sys_guid ),\r
+             cl_ntoh64( p_ni->node_guid ),\r
+             cl_ntoh64( p_ni->port_guid ),\r
+             cl_ntoh16( p_ni->partition_cap ),\r
+             cl_ntoh16( p_ni->device_id ),\r
+             cl_ntoh32( p_ni->revision ),\r
+             ib_node_info_get_local_port_num( p_ni ),\r
+             cl_ntoh32( ib_node_info_get_vendor_id( p_ni )),\r
+             desc\r
+             );\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_path_record(\r
+  IN osm_log_t* const p_log,\r
+  IN const ib_path_rec_t* const p_pr,\r
+  IN const osm_log_level_t log_level )\r
+{\r
+  if( osm_log_is_active( p_log, log_level ) )\r
+  {\r
+    osm_log( p_log, log_level,\r
+             "PathRecord dump:\n"\r
+             "\t\t\t\tservice_id..............0x%016" PRIx64 "\n"\r
+             "\t\t\t\tdgid....................0x%016" PRIx64 " : "\r
+             "0x%016" PRIx64 "\n"\r
+             "\t\t\t\tsgid....................0x%016" PRIx64 " : "\r
+             "0x%016" PRIx64 "\n"\r
+             "\t\t\t\tdlid....................0x%X\n"\r
+             "\t\t\t\tslid....................0x%X\n"\r
+             "\t\t\t\thop_flow_raw............0x%X\n"\r
+             "\t\t\t\ttclass..................0x%X\n"\r
+             "\t\t\t\tnum_path_revers.........0x%X\n"\r
+             "\t\t\t\tpkey....................0x%X\n"\r
+             "\t\t\t\tsl......................0x%X\n"\r
+             "\t\t\t\tmtu.....................0x%X\n"\r
+             "\t\t\t\trate....................0x%X\n"\r
+             "\t\t\t\tpkt_life................0x%X\n"\r
+             "\t\t\t\tpreference..............0x%X\n"\r
+             "\t\t\t\tresv2...................0x%X\n"\r
+             "\t\t\t\tresv3...................0x%X\n"\r
+             "",\r
+             *(uint64_t*)p_pr->service_id,\r
+             cl_ntoh64( p_pr->dgid.unicast.prefix ),\r
+             cl_ntoh64( p_pr->dgid.unicast.interface_id ),\r
+             cl_ntoh64( p_pr->sgid.unicast.prefix ),\r
+             cl_ntoh64( p_pr->sgid.unicast.interface_id ),\r
+             cl_ntoh16( p_pr->dlid ),\r
+             cl_ntoh16( p_pr->slid ),\r
+             cl_ntoh32( p_pr->hop_flow_raw ),\r
+             p_pr->tclass,\r
+             p_pr->num_path,\r
+             cl_ntoh16( p_pr->pkey ),\r
+             cl_ntoh16( p_pr->qos_class_sl ),\r
+             p_pr->mtu,\r
+             p_pr->rate,\r
+             p_pr->pkt_life,\r
+             p_pr->preference,\r
+             *(uint32_t*)&p_pr->resv2,\r
+             *((uint16_t*)&p_pr->resv2 + 2)\r
+             );\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_multipath_record(\r
+  IN osm_log_t* const p_log,\r
+  IN const ib_multipath_rec_t* const p_mpr,\r
+  IN const osm_log_level_t log_level )\r
+{\r
+  int i;\r
+  char buf_line[1024];\r
+  ib_gid_t const *p_gid;\r
+\r
+  if( osm_log_is_active( p_log, log_level ) )\r
+  {\r
+    memset(buf_line, 0, sizeof(buf_line));\r
+    p_gid = p_mpr->gids;\r
+    if ( p_mpr->sgid_count )\r
+    {\r
+      for (i = 0; i < p_mpr->sgid_count; i++)\r
+      {\r
+        sprintf( buf_line, "%s\t\t\t\tsgid%02d.................."\r
+                 "0x%016" PRIx64 " : 0x%016" PRIx64 "\n",\r
+                 buf_line, i + 1, cl_ntoh64( p_gid->unicast.prefix ),\r
+                 cl_ntoh64( p_gid->unicast.interface_id ) );\r
+        p_gid++;\r
+      }\r
+    }\r
+    if ( p_mpr->dgid_count )\r
+    {\r
+      for (i = 0; i < p_mpr->dgid_count; i++)\r
+      {\r
+        sprintf( buf_line, "%s\t\t\t\tdgid%02d.................."\r
+                 "0x%016" PRIx64 " : 0x%016" PRIx64 "\n",\r
+                 buf_line, i + 1, cl_ntoh64( p_gid->unicast.prefix ),\r
+                 cl_ntoh64( p_gid->unicast.interface_id ) );\r
+        p_gid++;\r
+      }\r
+    }\r
+    osm_log( p_log, log_level,\r
+             "MultiPath Record dump:\n"\r
+             "\t\t\t\thop_flow_raw............0x%X\n"\r
+             "\t\t\t\ttclass..................0x%X\n"\r
+             "\t\t\t\tnum_path_revers.........0x%X\n"\r
+             "\t\t\t\tpkey....................0x%X\n"\r
+             "\t\t\t\tresv0...................0x%X\n"\r
+             "\t\t\t\tsl......................0x%X\n"\r
+             "\t\t\t\tmtu.....................0x%X\n"\r
+             "\t\t\t\trate....................0x%X\n"\r
+             "\t\t\t\tpkt_life................0x%X\n"\r
+             "\t\t\t\tresv1...................0x%X\n"\r
+             "\t\t\t\tindependence............0x%X\n"\r
+             "\t\t\t\tsgid_count..............0x%X\n"\r
+             "\t\t\t\tdgid_count..............0x%X\n"\r
+             "%s\n"\r
+             "",\r
+             cl_ntoh32( p_mpr->hop_flow_raw ),\r
+             p_mpr->tclass,\r
+             p_mpr->num_path,\r
+             cl_ntoh16( p_mpr->pkey ),\r
+             p_mpr->resv0,\r
+             cl_ntoh16( p_mpr->sl ),\r
+             p_mpr->mtu,\r
+             p_mpr->rate,\r
+             p_mpr->pkt_life,\r
+             p_mpr->resv1,\r
+             p_mpr->independence,\r
+             p_mpr->sgid_count,\r
+             p_mpr->dgid_count,\r
+             buf_line\r
+             );\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_mc_record(\r
+  IN osm_log_t* const p_log,\r
+  IN const ib_member_rec_t* const p_mcmr,\r
+  IN const osm_log_level_t log_level )\r
+{\r
+\r
+  if( osm_log_is_active( p_log, log_level ) )\r
+  {\r
+    osm_log( p_log, log_level,\r
+             "MCMember Record dump:\n"\r
+             "\t\t\t\tMGID....................0x%016" PRIx64 " : "\r
+             "0x%016" PRIx64 "\n"\r
+             "\t\t\t\tPortGid.................0x%016" PRIx64 " : "\r
+             "0x%016" PRIx64 "\n"\r
+             "\t\t\t\tqkey....................0x%X\n"\r
+             "\t\t\t\tmlid....................0x%X\n"\r
+             "\t\t\t\tmtu.....................0x%X\n"\r
+             "\t\t\t\tTClass..................0x%X\n"\r
+             "\t\t\t\tpkey....................0x%X\n"\r
+             "\t\t\t\trate....................0x%X\n"\r
+             "\t\t\t\tpkt_life................0x%X\n"\r
+             "\t\t\t\tSLFlowLabelHopLimit.....0x%X\n"\r
+             "\t\t\t\tScopeState..............0x%X\n"\r
+             "\t\t\t\tProxyJoin...............0x%X\n"\r
+             "",\r
+             cl_ntoh64( p_mcmr->mgid.unicast.prefix ),\r
+             cl_ntoh64( p_mcmr->mgid.unicast.interface_id ),\r
+             cl_ntoh64( p_mcmr->port_gid.unicast.prefix ),\r
+             cl_ntoh64( p_mcmr->port_gid.unicast.interface_id ),\r
+             cl_ntoh32( p_mcmr->qkey ),\r
+             cl_ntoh16( p_mcmr->mlid ),\r
+             p_mcmr->mtu,\r
+             p_mcmr->tclass,\r
+             cl_ntoh16( p_mcmr->pkey ),\r
+             p_mcmr->rate,\r
+             p_mcmr->pkt_life,\r
+             cl_ntoh32( p_mcmr->sl_flow_hop ),\r
+             p_mcmr->scope_state,\r
+             p_mcmr->proxy_join\r
+             );\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_service_record(\r
+  IN osm_log_t* const p_log,\r
+  IN const ib_service_record_t* const p_sr,\r
+  IN const osm_log_level_t log_level )\r
+{\r
+  char buf_service_key[35];\r
+  char buf_service_name[65];\r
+\r
+  if( osm_log_is_active( p_log, log_level ) )\r
+  {\r
+    sprintf(buf_service_key,\r
+            "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",\r
+            p_sr->service_key[0],\r
+            p_sr->service_key[1],\r
+            p_sr->service_key[2],\r
+            p_sr->service_key[3],\r
+            p_sr->service_key[4],\r
+            p_sr->service_key[5],\r
+            p_sr->service_key[6],\r
+            p_sr->service_key[7],\r
+            p_sr->service_key[8],\r
+            p_sr->service_key[9],\r
+            p_sr->service_key[10],\r
+            p_sr->service_key[11],\r
+            p_sr->service_key[12],\r
+            p_sr->service_key[13],\r
+            p_sr->service_key[14],\r
+            p_sr->service_key[15]);\r
+    strncpy(buf_service_name, (char *)p_sr->service_name, 64);\r
+    buf_service_name[64] = '\0';\r
+\r
+    osm_log( p_log, log_level,\r
+             "Service Record dump:\n"\r
+             "\t\t\t\tServiceID...............0x%016" PRIx64 "\n"\r
+             "\t\t\t\tServiceGID..............0x%016" PRIx64 " : "\r
+             "0x%016" PRIx64 "\n"\r
+             "\t\t\t\tServiceP_Key............0x%X\n"\r
+             "\t\t\t\tServiceLease............0x%X\n"\r
+             "\t\t\t\tServiceKey..............%s\n"\r
+             "\t\t\t\tServiceName.............%s\n"\r
+             "\t\t\t\tServiceData8.1..........0x%X\n"\r
+             "\t\t\t\tServiceData8.2..........0x%X\n"\r
+             "\t\t\t\tServiceData8.3..........0x%X\n"\r
+             "\t\t\t\tServiceData8.4..........0x%X\n"\r
+             "\t\t\t\tServiceData8.5..........0x%X\n"\r
+             "\t\t\t\tServiceData8.6..........0x%X\n"\r
+             "\t\t\t\tServiceData8.7..........0x%X\n"\r
+             "\t\t\t\tServiceData8.8..........0x%X\n"\r
+             "\t\t\t\tServiceData8.9..........0x%X\n"\r
+             "\t\t\t\tServiceData8.10.........0x%X\n"\r
+             "\t\t\t\tServiceData8.11.........0x%X\n"\r
+             "\t\t\t\tServiceData8.12.........0x%X\n"\r
+             "\t\t\t\tServiceData8.13.........0x%X\n"\r
+             "\t\t\t\tServiceData8.14.........0x%X\n"\r
+             "\t\t\t\tServiceData8.15.........0x%X\n"\r
+             "\t\t\t\tServiceData8.16.........0x%X\n"\r
+             "\t\t\t\tServiceData16.1.........0x%X\n"\r
+             "\t\t\t\tServiceData16.2.........0x%X\n"\r
+             "\t\t\t\tServiceData16.3.........0x%X\n"\r
+             "\t\t\t\tServiceData16.4.........0x%X\n"\r
+             "\t\t\t\tServiceData16.5.........0x%X\n"\r
+             "\t\t\t\tServiceData16.6.........0x%X\n"\r
+             "\t\t\t\tServiceData16.7.........0x%X\n"\r
+             "\t\t\t\tServiceData16.8.........0x%X\n"\r
+             "\t\t\t\tServiceData32.1.........0x%X\n"\r
+             "\t\t\t\tServiceData32.2.........0x%X\n"\r
+             "\t\t\t\tServiceData32.3.........0x%X\n"\r
+             "\t\t\t\tServiceData32.4.........0x%X\n"\r
+             "\t\t\t\tServiceData64.1.........0x%016" PRIx64 "\n"\r
+             "\t\t\t\tServiceData64.2.........0x%016" PRIx64 "\n"\r
+             "",\r
+             cl_ntoh64( p_sr->service_id ),\r
+             cl_ntoh64( p_sr->service_gid.unicast.prefix ),\r
+             cl_ntoh64( p_sr->service_gid.unicast.interface_id ),\r
+             cl_ntoh16( p_sr->service_pkey ),\r
+             cl_ntoh32( p_sr->service_lease ),\r
+             buf_service_key,\r
+             buf_service_name,\r
+             p_sr->service_data8[0], p_sr->service_data8[1],\r
+             p_sr->service_data8[2], p_sr->service_data8[3],\r
+             p_sr->service_data8[4], p_sr->service_data8[5],\r
+             p_sr->service_data8[6], p_sr->service_data8[7],\r
+             p_sr->service_data8[8], p_sr->service_data8[9],\r
+             p_sr->service_data8[10], p_sr->service_data8[11],\r
+             p_sr->service_data8[12], p_sr->service_data8[13],\r
+             p_sr->service_data8[14], p_sr->service_data8[15],\r
+             cl_ntoh16(p_sr->service_data16[0]),\r
+             cl_ntoh16(p_sr->service_data16[1]),\r
+             cl_ntoh16(p_sr->service_data16[2]),\r
+             cl_ntoh16(p_sr->service_data16[3]),\r
+             cl_ntoh16(p_sr->service_data16[4]),\r
+             cl_ntoh16(p_sr->service_data16[5]),\r
+             cl_ntoh16(p_sr->service_data16[6]),\r
+             cl_ntoh16(p_sr->service_data16[7]),\r
+             cl_ntoh32(p_sr->service_data32[0]),\r
+             cl_ntoh32(p_sr->service_data32[1]),\r
+             cl_ntoh32(p_sr->service_data32[2]),\r
+             cl_ntoh32(p_sr->service_data32[3]),\r
+             cl_ntoh64(p_sr->service_data64[0]),\r
+             cl_ntoh64(p_sr->service_data64[1])\r
+             );\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_inform_info(\r
+  IN osm_log_t* const p_log,\r
+  IN const ib_inform_info_t* const p_ii,\r
+  IN const osm_log_level_t log_level )\r
+{\r
+  uint32_t qpn;\r
+  uint8_t  resp_time_val;\r
+\r
+  if( osm_log_is_active( p_log, log_level ) )\r
+  {\r
+\r
+   ib_inform_info_get_qpn_resp_time(p_ii->g_or_v.generic.qpn_resp_time_val,\r
+                                    &qpn, &resp_time_val);\r
+\r
+   if (p_ii->is_generic)\r
+    {\r
+      osm_log( p_log, log_level,\r
+               "InformInfo dump:\n"\r
+               "\t\t\t\tgid.....................0x%016" PRIx64 " : 0x%016" PRIx64 "\n"\r
+               "\t\t\t\tlid_range_begin.........0x%X\n"\r
+               "\t\t\t\tlid_range_end...........0x%X\n"\r
+               "\t\t\t\tis_generic..............0x%X\n"\r
+               "\t\t\t\tsubscribe...............0x%X\n"\r
+               "\t\t\t\ttrap_type...............0x%X\n"\r
+               "\t\t\t\ttrap_num................%u\n"\r
+               "\t\t\t\tqpn.....................0x%06X\n"\r
+               "\t\t\t\tresp_time_val...........0x%X\n"\r
+               "\t\t\t\tnode_type...............0x%06X\n"\r
+               "",\r
+               cl_ntoh64( p_ii->gid.unicast.prefix ),\r
+               cl_ntoh64( p_ii->gid.unicast.interface_id ),\r
+               cl_ntoh16( p_ii->lid_range_begin ),\r
+               cl_ntoh16( p_ii->lid_range_end ),\r
+               p_ii->is_generic,\r
+               p_ii->subscribe,\r
+               cl_ntoh16( p_ii->trap_type ),\r
+               cl_ntoh16( p_ii->g_or_v.generic.trap_num ),\r
+               cl_ntoh32(qpn),\r
+               resp_time_val,\r
+               cl_ntoh32(ib_inform_info_get_node_type( p_ii ))\r
+               );\r
+    }\r
+    else\r
+    {\r
+      osm_log( p_log, log_level,\r
+               "InformInfo dump:\n"\r
+               "\t\t\t\tgid.....................0x%016" PRIx64 " : 0x%016" PRIx64 "\n"\r
+               "\t\t\t\tlid_range_begin.........0x%X\n"\r
+               "\t\t\t\tlid_range_end...........0x%X\n"\r
+               "\t\t\t\tis_generic..............0x%X\n"\r
+               "\t\t\t\tsubscribe...............0x%X\n"\r
+               "\t\t\t\ttrap_type...............0x%X\n"\r
+               "\t\t\t\tdev_id..................0x%X\n"\r
+               "\t\t\t\tqpn.....................0x%06X\n"\r
+               "\t\t\t\tresp_time_val...........0x%X\n"\r
+               "\t\t\t\tvendor_id...............0x%06X\n"\r
+               "",\r
+               cl_ntoh64( p_ii->gid.unicast.prefix ),\r
+               cl_ntoh64( p_ii->gid.unicast.interface_id ),\r
+               cl_ntoh16( p_ii->lid_range_begin ),\r
+               cl_ntoh16( p_ii->lid_range_end ),\r
+               p_ii->is_generic,\r
+               p_ii->subscribe,\r
+               cl_ntoh16( p_ii->trap_type ),\r
+               cl_ntoh16( p_ii->g_or_v.vend.dev_id ),\r
+               cl_ntoh32(qpn),\r
+               resp_time_val,\r
+               cl_ntoh32(ib_inform_info_get_node_type( p_ii ))\r
+               );\r
+    }\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_inform_info_record(\r
+  IN osm_log_t* const p_log,\r
+  IN const ib_inform_info_record_t* const p_iir,\r
+  IN const osm_log_level_t log_level )\r
+{\r
+  uint32_t qpn;\r
+  uint8_t  resp_time_val;\r
+\r
+  ib_inform_info_get_qpn_resp_time(p_iir->inform_info.g_or_v.generic.qpn_resp_time_val,\r
+                                   &qpn, &resp_time_val);\r
+\r
+  if( osm_log_is_active( p_log, log_level ) )\r
+  {\r
+\r
+    ib_inform_info_get_qpn_resp_time(p_iir->inform_info.g_or_v.generic.qpn_resp_time_val,\r
+                                     &qpn, &resp_time_val);\r
+\r
+    if (p_iir->inform_info.is_generic)\r
+    {\r
+      osm_log( p_log, log_level,\r
+               "InformInfo Record dump:\n"\r
+               "\t\t\t\tRID\n"\r
+               "\t\t\t\tSubscriberGID...........0x%016" PRIx64 " : "\r
+               "0x%016" PRIx64 "\n"\r
+               "\t\t\t\tSubscriberEnum..........0x%X\n"\r
+               "\t\t\t\tInformInfo dump:\n"\r
+               "\t\t\t\tgid.....................0x%016" PRIx64 " : 0x%016" PRIx64 "\n"\r
+               "\t\t\t\tlid_range_begin.........0x%X\n"\r
+               "\t\t\t\tlid_range_end...........0x%X\n"\r
+               "\t\t\t\tis_generic..............0x%X\n"\r
+               "\t\t\t\tsubscribe...............0x%X\n"\r
+               "\t\t\t\ttrap_type...............0x%X\n"\r
+               "\t\t\t\ttrap_num................%u\n"\r
+               "\t\t\t\tqpn.....................0x%06X\n"\r
+               "\t\t\t\tresp_time_val...........0x%X\n"\r
+               "\t\t\t\tnode_type...............0x%06X\n"\r
+               "",\r
+               cl_ntoh64( p_iir->subscriber_gid.unicast.prefix ),\r
+               cl_ntoh64( p_iir->subscriber_gid.unicast.interface_id ),\r
+               cl_ntoh16( p_iir->subscriber_enum ),\r
+               cl_ntoh64( p_iir->inform_info.gid.unicast.prefix ),\r
+               cl_ntoh64( p_iir->inform_info.gid.unicast.interface_id ),\r
+               cl_ntoh16( p_iir->inform_info.lid_range_begin ),\r
+               cl_ntoh16( p_iir->inform_info.lid_range_end ),\r
+               p_iir->inform_info.is_generic,\r
+               p_iir->inform_info.subscribe,\r
+               cl_ntoh16( p_iir->inform_info.trap_type ),\r
+               cl_ntoh16( p_iir->inform_info.g_or_v.generic.trap_num ),\r
+               cl_ntoh32(qpn),\r
+               resp_time_val,\r
+               cl_ntoh32(ib_inform_info_get_node_type( &p_iir->inform_info ))\r
+               );\r
+    }\r
+    else\r
+    {\r
+      osm_log( p_log, log_level,\r
+               "InformInfo Record dump:\n"\r
+               "\t\t\t\tRID\n"\r
+               "\t\t\t\tSubscriberGID...........0x%016" PRIx64 " : "\r
+               "0x%016" PRIx64 "\n"\r
+               "\t\t\t\tSubscriberEnum..........0x%X\n"\r
+               "\t\t\t\tInformInfo dump:\n"\r
+               "\t\t\t\tgid.....................0x%016" PRIx64 " : 0x%016" PRIx64 "\n"\r
+               "\t\t\t\tlid_range_begin.........0x%X\n"\r
+               "\t\t\t\tlid_range_end...........0x%X\n"\r
+               "\t\t\t\tis_generic..............0x%X\n"\r
+               "\t\t\t\tsubscribe...............0x%X\n"\r
+               "\t\t\t\ttrap_type...............0x%X\n"\r
+               "\t\t\t\tdev_id..................0x%X\n"\r
+               "\t\t\t\tqpn.....................0x%06X\n"\r
+               "\t\t\t\tresp_time_val...........0x%X\n"\r
+               "\t\t\t\tvendor_id...............0x%06X\n"\r
+               "",\r
+               cl_ntoh64( p_iir->subscriber_gid.unicast.prefix ),\r
+               cl_ntoh64( p_iir->subscriber_gid.unicast.interface_id ),\r
+               cl_ntoh16( p_iir->subscriber_enum ),\r
+               cl_ntoh64( p_iir->inform_info.gid.unicast.prefix ),\r
+               cl_ntoh64( p_iir->inform_info.gid.unicast.interface_id ),\r
+               cl_ntoh16( p_iir->inform_info.lid_range_begin ),\r
+               cl_ntoh16( p_iir->inform_info.lid_range_end ),\r
+               p_iir->inform_info.is_generic,\r
+               p_iir->inform_info.subscribe,\r
+               cl_ntoh16( p_iir->inform_info.trap_type ),\r
+               cl_ntoh16( p_iir->inform_info.g_or_v.vend.dev_id ),\r
+               cl_ntoh32(qpn),\r
+               resp_time_val,\r
+               cl_ntoh32(ib_inform_info_get_node_type( &p_iir->inform_info ))\r
+               );\r
+    }\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_link_record(\r
+  IN osm_log_t*            const p_log,\r
+  IN const ib_link_record_t*  const p_lr,\r
+  IN const osm_log_level_t log_level )\r
+{\r
+  if( osm_log_is_active( p_log, log_level ) )\r
+  {\r
+    osm_log( p_log, log_level,\r
+             "Link Record dump:\n"\r
+             "\t\t\t\tfrom_lid................0x%X\n"\r
+             "\t\t\t\tfrom_port_num...........0x%X\n"\r
+             "\t\t\t\tto_port_num.............0x%X\n"\r
+             "\t\t\t\tto_lid..................0x%X\n"\r
+             "",\r
+             cl_ntoh16( p_lr->from_lid ),\r
+             p_lr->from_port_num,\r
+             p_lr->to_port_num,\r
+             cl_ntoh16( p_lr->to_lid )\r
+             );\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_switch_info(\r
+  IN osm_log_t* const p_log,\r
+  IN const ib_switch_info_t* const p_si,\r
+  IN const osm_log_level_t log_level )\r
+{\r
+  if( osm_log_is_active( p_log, log_level ) )\r
+  {\r
+    osm_log( p_log, OSM_LOG_VERBOSE,\r
+             "SwitchInfo dump:\n"\r
+             "\t\t\t\tlin_cap.................0x%X\n"\r
+             "\t\t\t\trand_cap................0x%X\n"\r
+             "\t\t\t\tmcast_cap...............0x%X\n"\r
+             "\t\t\t\tlin_top.................0x%X\n"\r
+             "\t\t\t\tdef_port................0x%X\n"\r
+             "\t\t\t\tdef_mcast_pri_port......0x%X\n"\r
+             "\t\t\t\tdef_mcast_not_port......0x%X\n"\r
+             "\t\t\t\tlife_state..............0x%X\n"\r
+             "\t\t\t\tlids_per_port...........0x%X\n"\r
+             "\t\t\t\tpartition_enf_cap.......0x%X\n"\r
+             "\t\t\t\tflags...................0x%X\n"\r
+             "",\r
+             cl_ntoh16( p_si->lin_cap ),\r
+             cl_ntoh16( p_si->rand_cap ),\r
+             cl_ntoh16( p_si->mcast_cap ),\r
+             cl_ntoh16( p_si->lin_top ),\r
+             p_si->def_port,\r
+             p_si->def_mcast_pri_port,\r
+             p_si->def_mcast_not_port,\r
+             p_si->life_state,\r
+             cl_ntoh16( p_si->lids_per_port ),\r
+             cl_ntoh16( p_si->enforce_cap ),\r
+             p_si->flags\r
+             );\r
+  }\r
+}\r
+\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_switch_info_record(\r
+  IN osm_log_t* const p_log,\r
+  IN const ib_switch_info_record_t* const p_sir,\r
+  IN const osm_log_level_t log_level )\r
+{\r
+  if( osm_log_is_active( p_log, log_level ) )\r
+  {\r
+    osm_log( p_log, log_level,\r
+             "SwitchInfo Record dump:\n"\r
+             "\t\t\t\tRID\n"\r
+             "\t\t\t\tlid.....................0x%X\n"\r
+             "\t\t\t\tSwitchInfo dump:\n"\r
+             "\t\t\t\tlin_cap.................0x%X\n"\r
+             "\t\t\t\trand_cap................0x%X\n"\r
+             "\t\t\t\tmcast_cap...............0x%X\n"\r
+             "\t\t\t\tlin_top.................0x%X\n"\r
+             "\t\t\t\tdef_port................0x%X\n"\r
+             "\t\t\t\tdef_mcast_pri_port......0x%X\n"\r
+             "\t\t\t\tdef_mcast_not_port......0x%X\n"\r
+             "\t\t\t\tlife_state..............0x%X\n"\r
+             "\t\t\t\tlids_per_port...........0x%X\n"\r
+             "\t\t\t\tpartition_enf_cap.......0x%X\n"\r
+             "\t\t\t\tflags...................0x%X\n"\r
+             "",\r
+             cl_ntoh16( p_sir->lid ),\r
+             cl_ntoh16( p_sir->switch_info.lin_cap ),\r
+             cl_ntoh16( p_sir->switch_info.rand_cap ),\r
+             cl_ntoh16( p_sir->switch_info.mcast_cap ),\r
+             cl_ntoh16( p_sir->switch_info.lin_top ),\r
+             p_sir->switch_info.def_port,\r
+             p_sir->switch_info.def_mcast_pri_port,\r
+             p_sir->switch_info.def_mcast_not_port,\r
+             p_sir->switch_info.life_state,\r
+             cl_ntoh16( p_sir->switch_info.lids_per_port ),\r
+             cl_ntoh16( p_sir->switch_info.enforce_cap ),\r
+             p_sir->switch_info.flags\r
+           );\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_pkey_block(\r
+  IN osm_log_t* const p_log,\r
+  IN uint64_t port_guid,\r
+  IN uint16_t block_num,\r
+  IN uint8_t port_num,\r
+  IN const ib_pkey_table_t* const p_pkey_tbl,\r
+  IN const osm_log_level_t log_level )\r
+{\r
+  int i;\r
+  char buf_line[1024];\r
+\r
+  if( osm_log_is_active( p_log, log_level ) )\r
+  {\r
+    buf_line[0] = '\0';\r
+    for (i = 0; i < 32; i++)\r
+      sprintf( buf_line,"%s 0x%04x |",\r
+               buf_line, cl_ntoh16(p_pkey_tbl->pkey_entry[i]));\r
+\r
+    osm_log( p_log, log_level,\r
+             "P_Key table dump:\n"\r
+             "\t\t\tport_guid...........0x%016" PRIx64 "\n"\r
+             "\t\t\tblock_num...........0x%X\n"\r
+             "\t\t\tport_num............0x%X\n\tP_Key Table: %s\n",\r
+             cl_ntoh64( port_guid ),\r
+             block_num,\r
+             port_num,\r
+             buf_line\r
+             );\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_slvl_map_table(\r
+  IN osm_log_t* const p_log,\r
+  IN uint64_t port_guid,\r
+  IN uint8_t in_port_num,\r
+  IN uint8_t out_port_num,\r
+  IN const ib_slvl_table_t* const p_slvl_tbl,\r
+  IN const osm_log_level_t log_level )\r
+{\r
+  uint8_t i;\r
+  char buf_line1[1024];\r
+  char buf_line2[1024];\r
+\r
+  if( osm_log_is_active( p_log, log_level ) )\r
+  {\r
+    buf_line1[0] = '\0';\r
+    buf_line2[0] = '\0';\r
+    for (i = 0; i < 16; i++)\r
+      sprintf( buf_line1,"%s %-2u |", buf_line1, i);\r
+    for (i = 0; i < 16; i++)\r
+      sprintf( buf_line2,"%s0x%01X |",\r
+               buf_line2, ib_slvl_table_get(p_slvl_tbl, i));\r
+    osm_log( p_log, log_level,\r
+             "SLtoVL dump:\n"\r
+             "\t\t\tport_guid............0x%016" PRIx64 "\n"\r
+             "\t\t\tin_port_num..........0x%X\n"\r
+             "\t\t\tout_port_num.........0x%X\n\tSL: | %s\n\tVL: | %s\n",\r
+             cl_ntoh64( port_guid ),\r
+             in_port_num,\r
+             out_port_num,\r
+             buf_line1, buf_line2\r
+             );\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_vl_arb_table(\r
+  IN osm_log_t* const p_log,\r
+  IN uint64_t port_guid,\r
+  IN uint8_t block_num,\r
+  IN uint8_t port_num,\r
+  IN const ib_vl_arb_table_t* const p_vla_tbl,\r
+  IN const osm_log_level_t log_level )\r
+{\r
+  int i;\r
+  char buf_line1[1024];\r
+  char buf_line2[1024];\r
+\r
+  if( osm_log_is_active( p_log, log_level ) )\r
+  {\r
+    buf_line1[0] = '\0';\r
+    buf_line2[0] = '\0';\r
+    for (i = 0; i < 32; i++)\r
+      sprintf( buf_line1,"%s 0x%01X |",\r
+               buf_line1, p_vla_tbl->vl_entry[i].vl);\r
+    for (i = 0; i < 32; i++)\r
+      sprintf( buf_line2,"%s 0x%01X |",\r
+               buf_line2, p_vla_tbl->vl_entry[i].weight);\r
+    osm_log( p_log, log_level,\r
+             "VlArb dump:\n"\r
+             "\t\t\tport_guid...........0x%016" PRIx64 "\n"\r
+             "\t\t\tblock_num...........0x%X\n"\r
+             "\t\t\tport_num............0x%X\n\tVL    : | %s\n\tWEIGHT:| %s\n",\r
+             cl_ntoh64( port_guid ),\r
+             block_num,\r
+             port_num,\r
+             buf_line1, buf_line2\r
+             );\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_sm_info(\r
+  IN osm_log_t* const p_log,\r
+  IN const ib_sm_info_t* const p_smi,\r
+  IN const osm_log_level_t log_level )\r
+{\r
+  if( osm_log_is_active( p_log, log_level ) )\r
+  {\r
+    osm_log( p_log, OSM_LOG_DEBUG,\r
+             "SMInfo dump:\n"\r
+             "\t\t\t\tguid....................0x%016" PRIx64 "\n"\r
+             "\t\t\t\tsm_key..................0x%016" PRIx64 "\n"\r
+             "\t\t\t\tact_count...............%u\n"\r
+             "\t\t\t\tpriority................%u\n"\r
+             "\t\t\t\tsm_state................%u\n"\r
+             "",\r
+             cl_ntoh64( p_smi->guid ),\r
+             cl_ntoh64( p_smi->sm_key ),\r
+             cl_ntoh32( p_smi->act_count ),\r
+             ib_sminfo_get_priority( p_smi ),\r
+             ib_sminfo_get_state( p_smi )\r
+             );\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_sm_info_record(\r
+  IN osm_log_t* const p_log,\r
+  IN const ib_sminfo_record_t* const p_smir,\r
+  IN const osm_log_level_t log_level )\r
+{\r
+  if( osm_log_is_active( p_log, log_level ) )\r
+  {\r
+    osm_log( p_log, OSM_LOG_DEBUG,\r
+             "SMInfo Record dump:\n"\r
+             "\t\t\t\tRID\n"\r
+             "\t\t\t\tLid.....................0x%X\n"\r
+             "\t\t\t\tReserved................0x%X\n"\r
+             "\t\t\t\tSMInfo dump:\n"\r
+             "\t\t\t\tguid....................0x%016" PRIx64 "\n"\r
+             "\t\t\t\tsm_key..................0x%016" PRIx64 "\n"\r
+             "\t\t\t\tact_count...............%u\n"\r
+             "\t\t\t\tpriority................%u\n"\r
+             "\t\t\t\tsm_state................%u\n"\r
+             "",\r
+             cl_ntoh16( p_smir->lid ),\r
+             cl_ntoh16( p_smir->resv0 ),\r
+             cl_ntoh64( p_smir->sm_info.guid ),\r
+             cl_ntoh64( p_smir->sm_info.sm_key ),\r
+             cl_ntoh32( p_smir->sm_info.act_count ),\r
+             ib_sminfo_get_priority( &p_smir->sm_info ),\r
+             ib_sminfo_get_state( &p_smir->sm_info )\r
+             );\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_notice(\r
+  IN osm_log_t* const p_log,\r
+  IN const ib_mad_notice_attr_t *p_ntci,\r
+  IN const osm_log_level_t log_level )\r
+{\r
+  char buff[1024];\r
+  buff[0] = '\0';\r
+\r
+  if( osm_log_is_active( p_log, log_level ) )\r
+  {\r
+    if (ib_notice_is_generic(p_ntci))\r
+    {\r
+      /* immediate data based on the trap */\r
+      switch (cl_ntoh16(p_ntci->g_or_v.generic.trap_num)) {\r
+      case 64:\r
+      case 65:\r
+      case 66:\r
+      case 67:\r
+        sprintf(buff,\r
+                "\t\t\t\tsrc_gid..................0x%016" PRIx64\r
+                ":0x%016" PRIx64 "\n",\r
+                cl_ntoh64(p_ntci->data_details.ntc_64_67.gid.unicast.prefix),\r
+                cl_ntoh64(p_ntci->data_details.ntc_64_67.gid.unicast.interface_id));\r
+        break;\r
+      case 128:\r
+        sprintf(buff,\r
+                "\t\t\t\tsw_lid...................0x%04X\n",\r
+                cl_ntoh16(p_ntci->data_details.ntc_128.sw_lid));\r
+        break;\r
+      case 129:\r
+      case 130:\r
+      case 131:\r
+        sprintf(buff,\r
+                "\t\t\t\tlid......................0x%04X\n"\r
+                "\t\t\t\tport_num.................%u\n",\r
+                cl_ntoh16(p_ntci->data_details.ntc_129_131.lid),\r
+                p_ntci->data_details.ntc_129_131.port_num);\r
+        break;\r
+      case 144:\r
+        sprintf(buff,\r
+                "\t\t\t\tlid......................0x%04x\n"\r
+                "\t\t\t\tnew_cap_mask.............0x%08x\n",\r
+                cl_ntoh16(p_ntci->data_details.ntc_144.lid),\r
+                cl_ntoh32(p_ntci->data_details.ntc_144.new_cap_mask));\r
+        break;\r
+      case 145:\r
+        sprintf(buff,\r
+                "\t\t\t\tlid......................0x%04X\n"\r
+                "\t\t\t\tnew_sys_guid.............0x%016" PRIx64 "\n",\r
+                cl_ntoh16(p_ntci->data_details.ntc_145.lid),\r
+                cl_ntoh64(p_ntci->data_details.ntc_145.new_sys_guid));\r
+        break;\r
+      }\r
+\r
+      osm_log( p_log, log_level,\r
+               "Generic Notice dump:\n"\r
+               "\t\t\t\ttype.....................0x%02X\n"\r
+               "\t\t\t\tprod_type................%u\n"\r
+               "\t\t\t\ttrap_num.................%u\n%s"\r
+               "",\r
+               ib_notice_get_type(p_ntci),\r
+               cl_ntoh32(ib_notice_get_prod_type(p_ntci)),\r
+               cl_ntoh16(p_ntci->g_or_v.generic.trap_num),\r
+               buff\r
+               );\r
+    }\r
+    else\r
+    {\r
+      osm_log( p_log, log_level,\r
+               "Vendor Notice dump:\n"\r
+               "\t\t\t\ttype.....................0x%04x\n"\r
+               "\t\t\t\tvendor...................%u\n"\r
+               "\t\t\t\tdevice_id................%u\n"\r
+               "",\r
+               cl_ntoh16(ib_notice_get_type(p_ntci)),\r
+               cl_ntoh32(ib_notice_get_vend_id(p_ntci)),\r
+               cl_ntoh16(p_ntci->g_or_v.vend.dev_id)\r
+               );\r
+    }\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_dr_smp(\r
+  IN osm_log_t* const p_log,\r
+  IN const ib_smp_t* const p_smp,\r
+  IN const osm_log_level_t log_level )\r
+{\r
+  uint32_t i;\r
+  char buf[BUF_SIZE];\r
+  char line[BUF_SIZE];\r
+\r
+  if( osm_log_is_active( p_log, log_level ) )\r
+  {\r
+    sprintf( buf,\r
+             "SMP dump:\n"\r
+             "\t\t\t\tbase_ver................0x%X\n"\r
+             "\t\t\t\tmgmt_class..............0x%X\n"\r
+             "\t\t\t\tclass_ver...............0x%X\n"\r
+             "\t\t\t\tmethod..................0x%X (%s)\n",\r
+             p_smp->base_ver,\r
+             p_smp->mgmt_class,\r
+             p_smp->class_ver,\r
+             p_smp->method, ib_get_sm_method_str(p_smp->method));\r
+\r
+    if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR)\r
+    {\r
+      sprintf( line,\r
+               "\t\t\t\tD bit...................0x%X\n"\r
+               "\t\t\t\tstatus..................0x%X\n",\r
+               ib_smp_is_d(p_smp),\r
+               ib_smp_get_status(p_smp));\r
+    }\r
+    else\r
+    {\r
+      sprintf( line,\r
+               "\t\t\t\tstatus..................0x%X\n",\r
+               cl_ntoh16(p_smp->status));\r
+    }\r
+    strcat( buf, line );\r
+\r
+    sprintf( line,\r
+             "\t\t\t\thop_ptr.................0x%X\n"\r
+             "\t\t\t\thop_count...............0x%X\n"\r
+             "\t\t\t\ttrans_id................0x%" PRIx64 "\n"\r
+             "\t\t\t\tattr_id.................0x%X (%s)\n"\r
+             "\t\t\t\tresv....................0x%X\n"\r
+             "\t\t\t\tattr_mod................0x%X\n"\r
+             "\t\t\t\tm_key...................0x%016" PRIx64 "\n",\r
+             p_smp->hop_ptr,\r
+             p_smp->hop_count,\r
+             cl_ntoh64(p_smp->trans_id),\r
+             cl_ntoh16(p_smp->attr_id),\r
+             ib_get_sm_attr_str( p_smp->attr_id ),\r
+             cl_ntoh16(p_smp->resv),\r
+             cl_ntoh32(p_smp->attr_mod),\r
+             cl_ntoh64(p_smp->m_key)\r
+             );\r
+    strcat( buf, line );\r
+\r
+    if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR)\r
+    {\r
+      sprintf( line,\r
+               "\t\t\t\tdr_slid.................0x%X\n"\r
+               "\t\t\t\tdr_dlid.................0x%X\n",\r
+               cl_ntoh16(p_smp->dr_slid),\r
+               cl_ntoh16(p_smp->dr_dlid)\r
+               );\r
+      strcat( buf, line );\r
+\r
+      strcat( buf, "\n\t\t\t\tInitial path: " );\r
+\r
+      for( i = 0; i <= p_smp->hop_count; i++ )\r
+      {\r
+        sprintf( line, "[%X]", p_smp->initial_path[i] );\r
+        strcat( buf, line );\r
+      }\r
+\r
+      strcat( buf, "\n\t\t\t\tReturn path:  " );\r
+\r
+      for( i = 0; i <= p_smp->hop_count; i++ )\r
+      {\r
+        sprintf( line, "[%X]", p_smp->return_path[i] );\r
+        strcat( buf, line );\r
+      }\r
+\r
+      strcat( buf, "\n\t\t\t\tReserved:     " );\r
+\r
+      for( i = 0; i < 7; i++ )\r
+      {\r
+        sprintf( line, "[%0X]", p_smp->resv1[i] );\r
+        strcat( buf, line );\r
+      }\r
+\r
+      strcat( buf, "\n" );\r
+\r
+      for( i = 0; i < 64; i += 16 )\r
+      {\r
+        sprintf( line, "\n\t\t\t\t%02X %02X %02X %02X "\r
+                 "%02X %02X %02X %02X"\r
+                 "   %02X %02X %02X %02X %02X %02X %02X %02X\n",\r
+                 p_smp->data[i],\r
+                 p_smp->data[i+1],\r
+                 p_smp->data[i+2],\r
+                 p_smp->data[i+3],\r
+                 p_smp->data[i+4],\r
+                 p_smp->data[i+5],\r
+                 p_smp->data[i+6],\r
+                 p_smp->data[i+7],\r
+                 p_smp->data[i+8],\r
+                 p_smp->data[i+9],\r
+                 p_smp->data[i+10],\r
+                 p_smp->data[i+11],\r
+                 p_smp->data[i+12],\r
+                 p_smp->data[i+13],\r
+                 p_smp->data[i+14],\r
+                 p_smp->data[i+15] );\r
+\r
+        strcat( buf, line );\r
+      }\r
+    }\r
+    else\r
+    {\r
+      /* not a Direct Route so provide source and destination lids */\r
+      strcat(buf, "\t\t\t\tMAD IS LID ROUTED\n");\r
+    }\r
+\r
+    osm_log( p_log, log_level,\r
+             "%s\n", buf );\r
+\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_sa_mad(\r
+  IN osm_log_t* const p_log,\r
+  IN const ib_sa_mad_t* const p_mad,\r
+  IN const osm_log_level_t log_level )\r
+{\r
+  char buf[BUF_SIZE];\r
+\r
+  /* make sure the mad is valid */\r
+  if (p_mad == NULL)\r
+  {\r
+    osm_log( p_log, log_level,\r
+             "NULL MAD POINTER\n");\r
+    return;\r
+  }\r
+\r
+  if( osm_log_is_active( p_log, log_level ) )\r
+  {\r
+    sprintf( buf,\r
+             "SA MAD dump:\n"\r
+             "\t\t\t\tbase_ver................0x%X\n"\r
+             "\t\t\t\tmgmt_class..............0x%X\n"\r
+             "\t\t\t\tclass_ver...............0x%X\n"\r
+             "\t\t\t\tmethod..................0x%X (%s)\n"\r
+             "\t\t\t\tstatus..................0x%X\n"\r
+             "\t\t\t\tresv....................0x%X\n"\r
+             "\t\t\t\ttrans_id................0x%" PRIx64 "\n"\r
+             "\t\t\t\tattr_id.................0x%X (%s)\n"\r
+             "\t\t\t\tresv1...................0x%X\n"\r
+             "\t\t\t\tattr_mod................0x%X\n"\r
+             "\t\t\t\trmpp_version............0x%X\n"\r
+             "\t\t\t\trmpp_type...............0x%X\n"\r
+             "\t\t\t\trmpp_flags..............0x%X\n"\r
+             "\t\t\t\trmpp_status.............0x%X\n"\r
+             "\t\t\t\tseg_num.................0x%X\n"\r
+             "\t\t\t\tpayload_len/new_win.....0x%X\n"\r
+             "\t\t\t\tsm_key..................0x%016" PRIx64 "\n"\r
+             "\t\t\t\tattr_offset.............0x%X\n"\r
+             "\t\t\t\tresv2...................0x%X\n"\r
+             "\t\t\t\tcomp_mask...............0x%016" PRIx64 "\n",\r
+             p_mad->base_ver,\r
+             p_mad->mgmt_class,\r
+             p_mad->class_ver,\r
+             p_mad->method, ib_get_sa_method_str(p_mad->method),\r
+             cl_ntoh16(p_mad->status),\r
+             cl_ntoh16(p_mad->resv),\r
+             cl_ntoh64(p_mad->trans_id),\r
+             cl_ntoh16(p_mad->attr_id),\r
+             ib_get_sa_attr_str( p_mad->attr_id ),\r
+             cl_ntoh16(p_mad->resv1),\r
+             cl_ntoh32(p_mad->attr_mod),\r
+             p_mad->rmpp_version,\r
+             p_mad->rmpp_type,\r
+             p_mad->rmpp_flags,\r
+             p_mad->rmpp_status,\r
+             cl_ntoh32(p_mad->seg_num),\r
+             cl_ntoh32(p_mad->paylen_newwin),\r
+             cl_ntoh64(p_mad->sm_key),\r
+             cl_ntoh16(p_mad->attr_offset),\r
+             cl_ntoh16(p_mad->resv3),\r
+             cl_ntoh64(p_mad->comp_mask)\r
+             );\r
+\r
+    strcat( buf, "\n" );\r
+\r
+    osm_log( p_log, log_level,\r
+             "%s\n", buf );\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_dr_path(\r
+  IN osm_log_t* const p_log,\r
+  IN const osm_dr_path_t* const p_path,\r
+  IN const osm_log_level_t log_level)\r
+{\r
+  uint32_t i;\r
+  char buf[BUF_SIZE];\r
+  char line[BUF_SIZE];\r
+\r
+  if( osm_log_is_active( p_log, log_level) )\r
+  {\r
+    sprintf( buf, "Directed Path Dump of %u hop path:"\r
+             "\n\t\t\t\tPath = ", p_path->hop_count );\r
+\r
+    for( i = 0; i <= p_path->hop_count; i++ )\r
+    {\r
+      sprintf( line, "[%X]", p_path->path[i] );\r
+      strcat( buf, line );\r
+    }\r
+    osm_log( p_log, log_level,\r
+             "%s\n", buf );\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_smp_dr_path(\r
+  IN osm_log_t* const p_log,\r
+  IN const ib_smp_t* const p_smp,\r
+  IN const osm_log_level_t log_level\r
+  )\r
+{\r
+  uint32_t i;\r
+  char buf[BUF_SIZE];\r
+  char line[BUF_SIZE];\r
+\r
+  if( osm_log_is_active( p_log, log_level) )\r
+  {\r
+    sprintf( buf, "Received SMP on a %u hop path:"\r
+             "\n\t\t\t\tInitial path = ", p_smp->hop_count );\r
+\r
+    for( i = 0; i <= p_smp->hop_count; i++ )\r
+    {\r
+      sprintf( line, "[%X]", p_smp->initial_path[i] );\r
+      strcat( buf, line );\r
+    }\r
+\r
+    strcat( buf, "\n\t\t\t\tReturn path  = " );\r
+\r
+    for( i = 0; i <= p_smp->hop_count; i++ )\r
+    {\r
+      sprintf( line, "[%X]", p_smp->return_path[i] );\r
+      strcat( buf, line );\r
+    }\r
+\r
+    osm_log( p_log, log_level,\r
+             "%s\n", buf );\r
+  }\r
+}\r
+\r
+const char* const __osm_sm_state_str[] =\r
+{\r
+  "OSM_SM_STATE_NO_STATE",                 /* 0 */\r
+  "OSM_SM_STATE_INIT",                     /* 1 */\r
+  "OSM_SM_STATE_IDLE",                     /* 2 */\r
+  "OSM_SM_STATE_SWEEP_LIGHT",                 /* 3 */\r
+  "OSM_SM_STATE_SWEEP_LIGHT_WAIT",            /* 4 */\r
+  "OSM_SM_STATE_SWEEP_HEAVY_SELF",            /* 5 */\r
+  "OSM_SM_STATE_SWEEP_HEAVY_SUBNET",          /* 6 */\r
+  "OSM_SM_STATE_SET_SM_UCAST_LID",            /* 7 */\r
+  "OSM_SM_STATE_SET_SM_UCAST_LID_WAIT",       /* 8 */\r
+  "OSM_SM_STATE_SET_SM_UCAST_LID_DONE",       /* 9 */\r
+  "OSM_SM_STATE_SET_SUBNET_UCAST_LIDS",       /* 10 */\r
+  "OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_WAIT",     /* 11 */\r
+  "OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_DONE",     /* 12 */\r
+  "OSM_SM_STATE_SET_UCAST_TABLES",            /* 13 */\r
+  "OSM_SM_STATE_SET_UCAST_TABLES_WAIT",       /* 14 */\r
+  "OSM_SM_STATE_SET_UCAST_TABLES_DONE",       /* 15 */\r
+  "OSM_SM_STATE_SET_MCAST_TABLES",            /* 16 */\r
+  "OSM_SM_STATE_SET_MCAST_TABLES_WAIT",       /* 17 */\r
+  "OSM_SM_STATE_SET_MCAST_TABLES_DONE",       /* 18 */\r
+  "OSM_SM_STATE_SET_LINK_PORTS",                 /* 19 */\r
+  "OSM_SM_STATE_SET_LINK_PORTS_WAIT",               /* 20 */\r
+  "OSM_SM_STATE_SET_LINK_PORTS_DONE",               /* 21 */\r
+  "OSM_SM_STATE_SET_ARMED",                   /* 22 */\r
+  "OSM_SM_STATE_SET_ARMED_WAIT",              /* 23 */\r
+  "OSM_SM_STATE_SET_ARMED_DONE",              /* 24 */\r
+  "OSM_SM_STATE_SET_ACTIVE",                  /* 25 */\r
+  "OSM_SM_STATE_SET_ACTIVE_WAIT",             /* 26 */\r
+  "OSM_SM_STATE_LOST_NEGOTIATION",            /* 27 */\r
+  "OSM_SM_STATE_STANDBY",                     /* 28 */\r
+  "OSM_SM_STATE_SUBNET_UP",                   /* 29 */\r
+  "OSM_SM_STATE_PROCESS_REQUEST",             /* 30 */\r
+  "OSM_SM_STATE_PROCESS_REQUEST_WAIT",        /* 31 */\r
+  "OSM_SM_STATE_PROCESS_REQUEST_DONE",        /* 32 */\r
+  "OSM_SM_STATE_MASTER_OR_HIGHER_SM_DETECTED",/* 33 */\r
+  "OSM_SM_STATE_SET_PKEY",                    /* 34 */\r
+  "OSM_SM_STATE_SET_PKEY_WAIT",               /* 35 */\r
+  "OSM_SM_STATE_SET_PKEY_DONE",               /* 36 */\r
+  "UNKNOWN STATE!!"                           /* 37 */\r
+};\r
+\r
+const char* const __osm_sm_signal_str[] =\r
+{\r
+  "OSM_SIGNAL_NONE",                       /* 0 */\r
+  "OSM_SIGNAL_SWEEP",                      /* 1 */\r
+  "OSM_SIGNAL_CHANGE_DETECTED",               /* 2 */\r
+  "OSM_SIGNAL_NO_PENDING_TRANSACTIONS",       /* 3 */\r
+  "OSM_SIGNAL_DONE",                       /* 4 */\r
+  "OSM_SIGNAL_DONE_PENDING",                  /* 5 */\r
+  "OSM_SIGNAL_LOST_SM_NEGOTIATION",           /* 6 */\r
+  "OSM_SIGNAL_LIGHT_SWEEP_FAIL",              /* 7 */\r
+  "OSM_SIGNAL_IDLE_TIME_PROCESS",             /* 8 */\r
+  "OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST",        /* 9 */\r
+  "OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED",  /* 10 */\r
+  "OSM_SIGNAL_EXIT_STBY",                /* 11 */\r
+  "UNKNOWN SIGNAL!!"                       /* 12 */\r
+};\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+osm_get_sm_state_str(\r
+  IN osm_sm_state_t state )\r
+{\r
+  if( state > OSM_SM_STATE_MAX )\r
+    state = OSM_SM_STATE_MAX;\r
+  return( __osm_sm_state_str[state] );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+osm_get_sm_signal_str(\r
+  IN osm_signal_t signal )\r
+{\r
+  if( signal > OSM_SIGNAL_MAX )\r
+    signal = OSM_SIGNAL_MAX;\r
+  return( __osm_sm_signal_str[signal] );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+\r
+static const char* const __osm_disp_msg_str[] =\r
+{\r
+  "OSM_MSG_REQ",\r
+  "OSM_MSG_MAD_NODE_INFO",\r
+  "OSM_MSG_MAD_PORT_INFO,",\r
+  "OSM_MSG_MAD_SWITCH_INFO",\r
+  "OSM_MSG_MAD_NODE_DESC",\r
+  "OSM_MSG_NO_SMPS_OUTSTANDING",\r
+  "OSM_MSG_MAD_NODE_RECORD",\r
+  "OSM_MSG_MAD_PORTINFO_RECORD",\r
+  "OSM_MSG_MAD_SERVICE_RECORD",\r
+  "OSM_MSG_MAD_PATH_RECORD",\r
+  "OSM_MSG_MAD_MCMEMBER_RECORD",\r
+  "OSM_MSG_MAD_LINK_RECORD",\r
+  "OSM_MSG_MAD_SMINFO_RECORD",\r
+  "OSM_MSG_MAD_CLASS_PORT_INFO",\r
+  "OSM_MSG_MAD_INFORM_INFO",\r
+  "OSM_MSG_MAD_LFT_RECORD",\r
+  "OSM_MSG_MAD_LFT",\r
+  "OSM_MSG_MAD_SM_INFO",\r
+  "OSM_MSG_MAD_NOTICE",\r
+  "OSM_MSG_LIGHT_SWEEP_FAIL",\r
+  "OSM_MSG_MAD_MFT",\r
+  "OSM_MSG_MAD_PKEY_TBL_RECORD",\r
+  "OSM_MSG_MAD_VL_ARB_RECORD",\r
+  "OSM_MSG_MAD_SLVL_TBL_RECORD",\r
+  "OSM_MSG_MAD_PKEY",\r
+  "OSM_MSG_MAD_VL_ARB",\r
+  "OSM_MSG_MAD_SLVL",\r
+  "OSM_MSG_MAD_GUIDINFO_RECORD",\r
+  "OSM_MSG_MAD_INFORM_INFO_RECORD",\r
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)\r
+  "OSM_MSG_MAD_MULTIPATH_RECORD",\r
+#endif\r
+  "UNKNOWN!!"\r
+};\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+osm_get_disp_msg_str(\r
+  IN cl_disp_msgid_t msg )\r
+{\r
+  if( msg > OSM_MSG_MAX )\r
+    msg = OSM_MSG_MAX;\r
+  return( __osm_disp_msg_str[msg] );\r
+}\r
+\r
+static const char* const __osm_port_state_str_fixed_width[] =\r
+{\r
+  "NOC",\r
+  "DWN",\r
+  "INI",\r
+  "ARM",\r
+  "ACT",\r
+  "???"\r
+};\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+osm_get_port_state_str_fixed_width(\r
+  IN uint8_t port_state )\r
+{\r
+  if( port_state > IB_LINK_ACTIVE )\r
+    port_state = IB_LINK_ACTIVE + 1;\r
+  return( __osm_port_state_str_fixed_width[port_state] );\r
+}\r
+\r
+static const char* const __osm_node_type_str_fixed_width[] =\r
+{\r
+  "??",\r
+  "CA",\r
+  "SW",\r
+  "RT",\r
+};\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+osm_get_node_type_str_fixed_width(\r
+  IN uint32_t node_type )\r
+{\r
+  if( node_type >= IB_NOTICE_NODE_TYPE_ROUTER )\r
+    node_type = 0;\r
+  return( __osm_node_type_str_fixed_width[node_type] );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+osm_get_manufacturer_str(\r
+  IN uint64_t              const guid_ho )\r
+{\r
+  static const char* intel_str         = "Intel      ";\r
+  static const char* mellanox_str      = "Mellanox   ";\r
+  static const char* redswitch_str     = "Redswitch  ";\r
+  static const char* silverstorm_str   = "SilverStorm";\r
+  static const char* topspin_str       = "Topspin    ";\r
+  static const char* fujitsu_str       = "Fujitsu    ";\r
+  static const char* voltaire_str      = "Voltaire   ";\r
+  static const char* yotta_str         = "YottaYotta ";\r
+  static const char* pathscale_str     = "PathScale  ";\r
+  static const char* ibm_str           = "IBM        ";\r
+  static const char* divergenet_str    = "DivergeNet ";\r
+  static const char* flextronics_str   = "Flextronics";\r
+  static const char* agilent_str       = "Agilent    ";\r
+  static const char* obsidian_str      = "Obsidian   ";\r
+  static const char* baymicro_str      = "BayMicro   ";\r
+  static const char* lsilogic_str      = "LSILogic   ";\r
+  static const char* ddn_str           = "DataDirect ";\r
+  static const char* panta_str         = "Panta      ";\r
+  static const char* hp_str            = "HP         ";\r
+  static const char* rioworks_str      = "Rioworks   ";\r
+  static const char* unknown_str       = "Unknown    ";\r
+\r
+  switch( (uint32_t)(guid_ho >> (5 * 8)) )\r
+  {\r
+  case OSM_VENDOR_ID_INTEL:\r
+    return( intel_str );\r
+  case OSM_VENDOR_ID_MELLANOX:\r
+    return( mellanox_str );\r
+  case OSM_VENDOR_ID_REDSWITCH:\r
+    return( redswitch_str );\r
+  case OSM_VENDOR_ID_SILVERSTORM:\r
+    return( silverstorm_str );\r
+  case OSM_VENDOR_ID_TOPSPIN:\r
+    return( topspin_str );\r
+  case OSM_VENDOR_ID_FUJITSU:\r
+  case OSM_VENDOR_ID_FUJITSU2:\r
+    return( fujitsu_str );\r
+  case OSM_VENDOR_ID_VOLTAIRE:\r
+    return( voltaire_str );\r
+  case OSM_VENDOR_ID_YOTTAYOTTA:\r
+    return( yotta_str );\r
+  case OSM_VENDOR_ID_PATHSCALE:\r
+    return( pathscale_str );\r
+  case OSM_VENDOR_ID_IBM:\r
+    return( ibm_str );\r
+  case OSM_VENDOR_ID_DIVERGENET:\r
+    return( divergenet_str );\r
+  case OSM_VENDOR_ID_FLEXTRONICS:\r
+    return( flextronics_str );\r
+  case OSM_VENDOR_ID_AGILENT:\r
+    return( agilent_str );\r
+  case OSM_VENDOR_ID_OBSIDIAN:\r
+    return( obsidian_str );\r
+  case OSM_VENDOR_ID_BAYMICRO:\r
+    return( baymicro_str );\r
+  case OSM_VENDOR_ID_LSILOGIC:\r
+    return( lsilogic_str );\r
+  case OSM_VENDOR_ID_DDN:\r
+    return( ddn_str );\r
+  case OSM_VENDOR_ID_PANTA:\r
+    return( panta_str );\r
+  case OSM_VENDOR_ID_HP:\r
+    return( hp_str );\r
+  case OSM_VENDOR_ID_RIOWORKS:\r
+    return( rioworks_str );\r
+  default:\r
+    return( unknown_str );\r
+  }\r
+}\r
+\r
+static const char* const __osm_mtu_str_fixed_width[] =\r
+{\r
+  "??? ",\r
+  "256 ",\r
+  "512 ",\r
+  "1024",\r
+  "2048",\r
+  "4096"\r
+};\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+osm_get_mtu_str(\r
+  IN uint8_t               const mtu )\r
+{\r
+  if( mtu > IB_MTU_LEN_4096 )\r
+    return( __osm_mtu_str_fixed_width[0] );\r
+  else\r
+    return( __osm_mtu_str_fixed_width[mtu] );\r
+}\r
+\r
+static const char* const __osm_lwa_str_fixed_width[] =\r
+{\r
+  "???",\r
+  "1x ",\r
+  "4x ",\r
+  "???",\r
+  "???",\r
+  "???",\r
+  "???",\r
+  "???",\r
+  "12x"\r
+};\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+osm_get_lwa_str(\r
+  IN uint8_t               const lwa )\r
+{\r
+  if( lwa > 8 )\r
+    return( __osm_lwa_str_fixed_width[0] );\r
+  else\r
+    return( __osm_lwa_str_fixed_width[lwa] );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static const char* const __osm_lsa_str_fixed_width[] =\r
+{\r
+  "???",\r
+  "2.5",\r
+  "5  ",\r
+  "???",\r
+  "10 "\r
+};\r
+\r
+const char*\r
+osm_get_lsa_str(\r
+  IN uint8_t               const lsa )\r
+{\r
+  if( lsa > 4 )\r
+    return( __osm_lsa_str_fixed_width[0] );\r
+  else\r
+    return( __osm_lsa_str_fixed_width[lsa] );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+\r
+const char* const __osm_sm_mgr_signal_str[] =\r
+{\r
+  "OSM_SM_SIGNAL_INIT",                 /* 0 */\r
+  "OSM_SM_SIGNAL_DISCOVERY_COMPLETED",   /* 2 */\r
+  "OSM_SM_SIGNAL_POLLING_TIMEOUT",       /* 3 */\r
+  "OSM_SM_SIGNAL_DISCOVER",              /* 4 */\r
+  "OSM_SM_SIGNAL_DISABLE",               /* 5 */\r
+  "OSM_SM_SIGNAL_HANDOVER",              /* 6 */\r
+  "OSM_SM_SIGNAL_HANDOVER_SENT",         /* 7 */\r
+  "OSM_SM_SIGNAL_ACKNOWLEDGE",           /* 8 */\r
+  "OSM_SM_SIGNAL_STANDBY",               /* 9 */\r
+  "OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED",        /* 10 */\r
+  "OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED_DONE",    /* 11 */\r
+  "OSM_SM_SIGNAL_WAIT_FOR_HANDOVER",     /* 12 */\r
+  "UNKNOWN STATE!!"                      /* 13 */\r
+\r
+};\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+osm_get_sm_mgr_signal_str(\r
+  IN osm_sm_signal_t signal )\r
+{\r
+  if( signal > OSM_SM_SIGNAL_MAX )\r
+    signal = OSM_SM_SIGNAL_MAX;\r
+  return( __osm_sm_mgr_signal_str[signal] );\r
+}\r
+\r
+const char* const __osm_sm_mgr_state_str[] =\r
+{\r
+  "IB_SMINFO_STATE_NOTACTIVE",                /* 0 */\r
+  "IB_SMINFO_STATE_DISCOVERING",              /* 1 */\r
+  "IB_SMINFO_STATE_STANDBY",                     /* 2 */\r
+  "IB_SMINFO_STATE_MASTER",                   /* 3 */\r
+  "IB_SMINFO_STATE_INIT",                     /* 4 */\r
+  "UNKNOWN STATE!!"                              /* 5 */\r
+\r
+};\r
+\r
+const char*\r
+osm_get_sm_mgr_state_str(\r
+  IN uint16_t state )\r
+{\r
+  if( state > IB_SMINFO_STATE_INIT )\r
+    state = IB_SMINFO_STATE_INIT + 1;\r
+  return( __osm_sm_mgr_state_str[state] );\r
+}\r
+\r
+\r
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/osm_log.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/osm_log.c
new file mode 100644 (file)
index 0000000..c62f926
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_log.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementaion of osm_log_t.
+ * This object represents the log file.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.8 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <opensm/osm_log.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+static int log_exit_count = 0;
+
+#ifndef WIN32
+#include <sys/time.h>
+#include <unistd.h>
+#include <complib/cl_timer.h>
+
+static char *month_str[] = {
+  "Jan",
+  "Feb",
+  "Mar",
+  "Apr",
+  "May",
+  "Jun",
+  "Jul",
+  "Aug",
+  "Sep",
+  "Oct",
+  "Nov",
+  "Dec"
+};
+#else
+void 
+OsmReportState(
+    IN const char *p_str);
+#endif /* ndef WIN32 */
+
+#ifndef WIN32
+
+static void truncate_log_file(osm_log_t* const p_log)
+{
+       int fd = fileno(p_log->out_port);
+       if (ftruncate(fd, 0) < 0)
+               fprintf(stderr, "truncate_log_file: cannot truncate: %s\n",
+                       strerror(errno));
+       if (lseek(fd, 0, SEEK_SET) < 0)
+               fprintf(stderr, "truncate_log_file: cannot rewind: %s\n",
+                       strerror(errno));
+       p_log->count = 0;
+}
+
+#else /* Windows */
+
+static void truncate_log_file(osm_log_t* const p_log)
+{
+       fprintf(stderr, "truncate_log_file: cannot truncate on windows system (yet)\n");
+}
+#endif /* ndef WIN32 */
+
+int osm_log_printf(osm_log_t *p_log, osm_log_level_t level,
+                  const char *fmt, ...)
+{
+       va_list args;
+       int ret;
+
+       if (!(p_log->level&level))
+               return 0;
+
+       va_start(args, fmt);
+       ret = vfprintf(stdout, fmt, args);
+       va_end(args);
+
+       if (p_log->flush || level&OSM_LOG_ERROR)
+               fflush( stdout );
+
+       return ret;
+}
+
+void
+osm_log(
+  IN osm_log_t* const p_log,
+  IN const osm_log_level_t verbosity,
+  IN const char *p_str, ... )
+{
+  char      buffer[LOG_ENTRY_SIZE_MAX];
+  va_list   args;
+  int       ret;
+
+#ifdef WIN32
+  SYSTEMTIME st;
+  uint32_t pid = GetCurrentThreadId();
+#else
+  pid_t pid = 0;
+  time_t tim;
+  struct tm result;
+  uint64_t time_usecs;
+  uint32_t usecs;
+
+  time_usecs = cl_get_time_stamp();
+  tim = time_usecs/1000000;
+  usecs = time_usecs % 1000000;
+  localtime_r(&tim, &result);
+#endif /* WIN32 */
+
+  /* If this is a call to syslog - always print it */
+  if ( verbosity & (OSM_LOG_SYS | p_log->level) )
+  {
+    va_start( args, p_str );
+    vsprintf( buffer, p_str, args );
+    va_end(args);
+
+    /* this is a call to the syslog */
+    if (verbosity & OSM_LOG_SYS)
+    {
+      cl_log_event("OpenSM", LOG_INFO, buffer , NULL, 0);
+
+      /* SYSLOG should go to stdout too */
+      if (p_log->out_port != stdout)
+      {
+        printf("%s\n", buffer);
+        fflush( stdout );
+      }
+#ifdef WIN32
+      OsmReportState(buffer);
+#endif /* WIN32 */
+    }
+
+    /* regular log to default out_port */
+    cl_spinlock_acquire( &p_log->lock );
+
+    if (p_log->max_size && p_log->count > p_log->max_size)
+    {
+      /* truncate here */
+      fprintf(stderr, "osm_log: log file exceeds the limit %lu. Truncating.\n",
+              p_log->max_size);
+      truncate_log_file(p_log);
+    }
+
+#ifdef WIN32
+    GetLocalTime(&st);
+ _retry:
+    ret = fprintf( p_log->out_port, "[%02d:%02d:%02d:%03d][%04X] -> %s",
+                   st.wHour, st.wMinute, st.wSecond, st.wMilliseconds,
+                   pid, buffer );
+#else
+    pid = pthread_self();
+ _retry:
+    ret = fprintf( p_log->out_port, "%s %02d %02d:%02d:%02d %06d [%04X] -> %s",
+                   (result.tm_mon < 12 ? month_str[result.tm_mon] : "???"),
+                   result.tm_mday, result.tm_hour,
+                   result.tm_min, result.tm_sec,
+                   usecs, pid, buffer );
+#endif
+    /*  flush log */
+    if (ret > 0 && (p_log->flush || (verbosity & OSM_LOG_ERROR)) &&
+        fflush( p_log->out_port ) < 0)
+      ret = -1;
+
+    if (ret >= 0)
+    {
+      log_exit_count = 0;
+      p_log->count += ret;
+    }
+    else if (log_exit_count < 3)
+    {
+      log_exit_count++;
+      if (errno == ENOSPC && p_log->max_size) {
+        fprintf(stderr, "osm_log: write failed: %s. Truncating log file.\n",
+                strerror(errno));
+        truncate_log_file(p_log);
+        goto _retry;
+      }
+      fprintf(stderr, "osm_log: write failed: %s\n", strerror(errno));
+    }
+
+    cl_spinlock_release( &p_log->lock );
+  }
+}
+
+void
+osm_log_raw(
+  IN osm_log_t* const p_log,
+  IN const osm_log_level_t verbosity,
+  IN const char *p_buf )
+{
+  if( p_log->level & verbosity )
+  {
+    cl_spinlock_acquire( &p_log->lock );
+    printf( "%s", p_buf );
+    cl_spinlock_release( &p_log->lock );
+
+    /*
+      Flush log on errors too.
+    */
+    if( p_log->flush || (verbosity & OSM_LOG_ERROR) )
+      fflush( stdout );
+  }
+}
+
+boolean_t
+osm_is_debug(void)
+{
+#if defined( _DEBUG_ )
+  return TRUE;
+#else
+  return FALSE;
+#endif /* defined( _DEBUG_ ) */
+}
+
+ib_api_status_t
+osm_log_init_v2(
+  IN osm_log_t* const p_log,
+  IN const boolean_t flush,
+  IN const uint8_t log_flags,
+  IN const char *log_file,
+  IN const unsigned long max_size,
+  IN const boolean_t accum_log_file )
+{
+  struct stat st;
+
+  p_log->level = log_flags;
+  p_log->flush = flush;
+  p_log->count = 0;
+  p_log->max_size = 0;
+
+  if (log_file == NULL || !strcmp(log_file, "-") ||
+      !strcmp(log_file, "stdout"))
+  {
+    p_log->out_port = stdout;
+  }
+  else if (!strcmp(log_file, "stderr"))
+  {
+    p_log->out_port = stderr;
+  }
+  else
+  {
+    if (accum_log_file)
+      p_log->out_port = fopen(log_file, "a+");
+    else
+      p_log->out_port = fopen(log_file, "w+");
+
+    if (!p_log->out_port)
+    {
+      if (accum_log_file)
+        printf("Cannot open %s for appending. Permission denied\n", log_file);
+      else
+        printf("Cannot open %s for writing. Permission denied\n", log_file);
+
+      return(IB_UNKNOWN_ERROR);
+    }
+
+    if (fstat(fileno(p_log->out_port), &st) == 0)
+      p_log->count = st.st_size;
+
+    p_log->max_size = max_size;
+  }
+
+  openlog("OpenSM", LOG_CONS | LOG_PID, LOG_USER);
+
+  if (cl_spinlock_init( &p_log->lock ) == CL_SUCCESS) 
+    return IB_SUCCESS;
+  else
+    return IB_ERROR;
+}
+
+ib_api_status_t
+osm_log_init(
+  IN osm_log_t* const p_log,
+  IN const boolean_t flush,
+  IN const uint8_t log_flags,
+  IN const char *log_file,
+  IN const boolean_t accum_log_file )
+{
+  return osm_log_init_v2( p_log, flush, log_flags, log_file, 0, accum_log_file );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/osm_mad_pool.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/libopensm/osm_mad_pool.c
new file mode 100644 (file)
index 0000000..d648cfe
--- /dev/null
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_mad_pool.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_mad_pool_t.
+ * This object represents a pool of management datagram (MAD) objects.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <vendor/osm_vendor_api.h>
+
+#define OSM_MAD_POOL_MIN_SIZE 256
+#define OSM_MAD_POOL_GROW_SIZE 256
+
+
+/**********************************************************************
+ **********************************************************************/
+cl_status_t
+__osm_mad_pool_ctor(
+  IN void* const p_object,
+  IN void* context,
+  OUT cl_pool_item_t** const pp_pool_item )
+{
+  osm_madw_t *p_madw = p_object;
+
+  UNUSED_PARAM( context );
+  osm_madw_construct( p_madw );
+  /* CHECK THIS.  DOCS DON'T DESCRIBE THIS OUT PARAM. */
+  *pp_pool_item = &p_madw->pool_item;
+  return( CL_SUCCESS );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mad_pool_construct(
+  IN osm_mad_pool_t* const p_pool )
+{
+  CL_ASSERT( p_pool );
+
+  memset( p_pool, 0, sizeof(*p_pool) );
+  cl_qlock_pool_construct( &p_pool->madw_pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mad_pool_destroy(
+  IN osm_mad_pool_t* const p_pool )
+{
+  CL_ASSERT( p_pool );
+
+  /* HACK: we still rarely see some mads leaking - so ignore this */
+  /* cl_qlock_pool_destroy( &p_pool->madw_pool ); */
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mad_pool_init(
+  IN osm_mad_pool_t* const p_pool,
+  IN osm_log_t* const p_log )
+{
+  ib_api_status_t status;
+
+  OSM_LOG_ENTER( p_log, osm_mad_pool_init );
+
+  p_pool->p_log = p_log;
+
+  status = cl_qlock_pool_init(
+    &p_pool->madw_pool,
+    OSM_MAD_POOL_MIN_SIZE,
+    0,
+    OSM_MAD_POOL_GROW_SIZE,
+    sizeof( osm_madw_t ),
+    __osm_mad_pool_ctor,
+    NULL,
+    p_pool );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_mad_pool_init: ERR 0702: "
+             "Grow pool initialization failed (%s)\n",
+             ib_get_err_str(status) );
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_madw_t*
+osm_mad_pool_get(
+  IN osm_mad_pool_t* const p_pool,
+  IN osm_bind_handle_t h_bind,
+  IN const uint32_t total_size,
+  IN const osm_mad_addr_t* const p_mad_addr )
+{
+  osm_madw_t *p_madw;
+  ib_mad_t *p_mad;
+
+  OSM_LOG_ENTER( p_pool->p_log, osm_mad_pool_get );
+
+  CL_ASSERT( h_bind != OSM_BIND_INVALID_HANDLE );
+  CL_ASSERT( total_size );
+
+  /*
+    First, acquire a mad wrapper from the mad wrapper pool.
+  */
+  p_madw = (osm_madw_t*)cl_qlock_pool_get( &p_pool->madw_pool );
+  if( p_madw == NULL )
+  {
+    osm_log( p_pool->p_log, OSM_LOG_ERROR,
+             "osm_mad_pool_get: ERR 0703: "
+             "Unable to acquire MAD wrapper object\n" );
+    goto Exit;
+  }
+
+  osm_madw_init( p_madw, h_bind, total_size, p_mad_addr );
+
+  /*
+    Next, acquire a wire mad of the specified size.
+  */
+  p_mad = osm_vendor_get( h_bind, total_size, &p_madw->vend_wrap );
+  if( p_mad == NULL )
+  {
+    osm_log( p_pool->p_log, OSM_LOG_ERROR,
+             "osm_mad_pool_get: ERR 0704: "
+             "Unable to acquire wire MAD\n" );
+
+    /* Don't leak wrappers! */
+    cl_qlock_pool_put( &p_pool->madw_pool, (cl_pool_item_t*)p_madw );
+    p_madw = NULL;
+    goto Exit;
+  }
+
+  cl_atomic_inc( &p_pool->mads_out );
+  /*
+    Finally, attach the wire MAD to this wrapper.
+  */
+  osm_madw_set_mad( p_madw, p_mad );
+
+  osm_log( p_pool->p_log, OSM_LOG_DEBUG,
+           "osm_mad_pool_get: Acquired p_madw = %p, p_mad = %p, "
+           "size = %u\n", p_madw, p_madw->p_mad, total_size );
+
+ Exit:
+  OSM_LOG_EXIT( p_pool->p_log );
+  return( p_madw );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_madw_t*
+osm_mad_pool_get_wrapper(
+  IN osm_mad_pool_t* const p_pool,
+  IN osm_bind_handle_t h_bind,
+  IN const uint32_t total_size,
+  IN const ib_mad_t* const p_mad,
+  IN const osm_mad_addr_t* const p_mad_addr )
+{
+  osm_madw_t *p_madw;
+
+  OSM_LOG_ENTER( p_pool->p_log, osm_mad_pool_get_wrapper );
+
+  CL_ASSERT( h_bind != OSM_BIND_INVALID_HANDLE );
+  CL_ASSERT( total_size );
+  CL_ASSERT( p_mad );
+
+  /*
+    First, acquire a mad wrapper from the mad wrapper pool.
+  */
+  p_madw = (osm_madw_t*)cl_qlock_pool_get( &p_pool->madw_pool );
+  if( p_madw == NULL )
+  {
+    osm_log( p_pool->p_log, OSM_LOG_ERROR,
+             "osm_mad_pool_get_wrapper: ERR 0705: "
+             "Unable to acquire MAD wrapper object\n" );
+    goto Exit;
+  }
+
+  /*
+    Finally, initialize the wrapper object.
+  */
+  cl_atomic_inc( &p_pool->mads_out );
+  osm_madw_init( p_madw, h_bind, total_size, p_mad_addr );
+  osm_madw_set_mad( p_madw, p_mad );
+
+  osm_log( p_pool->p_log, OSM_LOG_DEBUG,
+           "osm_mad_pool_get_wrapper: Acquired p_madw = %p, p_mad = %p "
+           "size = %u\n", p_madw, p_madw->p_mad, total_size );
+
+ Exit:
+  OSM_LOG_EXIT( p_pool->p_log );
+  return( p_madw );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_madw_t*
+osm_mad_pool_get_wrapper_raw(
+  IN osm_mad_pool_t* const p_pool )
+{
+  osm_madw_t *p_madw;
+
+  OSM_LOG_ENTER( p_pool->p_log, osm_mad_pool_get_wrapper_raw );
+
+  p_madw = (osm_madw_t*)cl_qlock_pool_get( &p_pool->madw_pool );
+
+  osm_log( p_pool->p_log, OSM_LOG_DEBUG,
+           "osm_mad_pool_get_wrapper_raw: "
+           "Getting p_madw = %p\n", p_madw );
+
+  osm_madw_init( p_madw, 0, 0, 0 );
+  osm_madw_set_mad( p_madw, 0 );
+  cl_atomic_inc( &p_pool->mads_out );
+
+  OSM_LOG_EXIT( p_pool->p_log );
+  return( p_madw );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mad_pool_put(
+  IN osm_mad_pool_t* const p_pool,
+  IN osm_madw_t* const p_madw )
+{
+  OSM_LOG_ENTER( p_pool->p_log, osm_mad_pool_put );
+
+  CL_ASSERT( p_madw );
+
+  osm_log( p_pool->p_log, OSM_LOG_DEBUG,
+           "osm_mad_pool_put: Releasing p_madw = %p, p_mad = %p\n",
+           p_madw, p_madw->p_mad );
+
+  /*
+    First, return the wire mad to the pool
+  */
+  if( p_madw->p_mad )
+    osm_vendor_put( p_madw->h_bind, &p_madw->vend_wrap );
+
+  /*
+    Return the mad wrapper to the wrapper pool
+  */
+  cl_qlock_pool_put( &p_pool->madw_pool, (cl_pool_item_t*)p_madw );
+  cl_atomic_dec( &p_pool->mads_out );
+
+  OSM_LOG_EXIT( p_pool->p_log );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/Makefile b/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/Makefile
new file mode 100644 (file)
index 0000000..5818975
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source
+# file to this component.  This file merely indirects to the real make file
+# that is shared by all the driver components of the Windows NT DDK
+#
+
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/SOURCES b/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/SOURCES
new file mode 100644 (file)
index 0000000..6c23c9d
--- /dev/null
@@ -0,0 +1,60 @@
+!if $(FREEBUILD)\r
+TARGETNAME=osmv_ibal_3_0_0\r
+!else\r
+TARGETNAME=osmv_ibal_3_0_0d\r
+!endif\r
+TARGETTYPE=LIBRARY\r
+\r
+!if !defined(WINIBHOME)\r
+WINIBHOME=..\..\..\..\r
+!endif\r
+\r
+LIBPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)\r
+\r
+!if defined(OSM_TARGET)\r
+TARGETPATH=$(OSM_TARGET)\bin\user\obj$(BUILD_ALT_DIR)\r
+!else\r
+TARGETPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)\r
+!endif\r
+\r
+USE_NTDLL=1\r
+USE_NATIVE_EH=1\r
+OVR_DIR=..\addon\r
+\r
+\r
+SOURCES=\\r
+       osm_vendor_al.c \\r
+       osm_vendor_mlx_sa.c \\r
+       winosm_common.c\r
+\r
+OSM_HOME=..\r
+\r
+TARGETLIBS=\\r
+!if $(FREEBUILD)\r
+                       $(LIBPATH)\*\ibal.lib \\r
+                       $(LIBPATH)\*\complib.lib \r
+!else\r
+                       $(LIBPATH)\*\ibald.lib \\r
+                       $(LIBPATH)\*\complibd.lib\r
+!endif\r
+\r
+#DO NOT TOUCH the order of search path , until ib_types.h merging process will be done\r
+INCLUDES= \\r
+       $(OSM_HOME)\include; \\r
+       $(OSM_HOME); \\r
+       $(WINIBHOME)\inc; \\r
+       $(WINIBHOME)\inc\user;\r
+\r
+# Could be any special flag needed for this project \r
+USER_C_FLAGS=$(USER_C_FLAGS) \r
+#Add preproccessor definitions\r
+C_DEFINES=$(C_DEFINES) -DWIN32 -D__WIN__ -D__i386__ -Dinline=__inline -DMT_LITTLE_ENDIAN -DOSM_VENDOR_INTF_AL\r
+C_DEFINES=$(C_DEFINES) -I.. -DHAVE_CONFIG_H\r
+!if !$(FREEBUILD)\r
+#C_DEFINES=$(C_DEFINES) -D_DEBUG -DDEBUG -DDBG\r
+C_DEFINES=$(C_DEFINES)\r
+!endif\r
+\r
+LINKER_FLAGS= $(LINKER_FLAGS)\r
+MSC_WARNING_LEVEL= /W3\r
+#MSC_OPTIMIZATION= /O0\r
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/osm_vendor_al.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/osm_vendor_al.c
new file mode 100644 (file)
index 0000000..e683b05
--- /dev/null
@@ -0,0 +1,1533 @@
+/*\r
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.\r
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.\r
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.\r
+ * Portions Copyright (c) 2008 Microsoft Corporation.  All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: osm_vendor_al.c 1375 2008-07-13 08:55:53Z leonidk $\r
+ */\r
+\r
+\r
+/*\r
+ * Abstract:\r
+ *    Implementation of osm_req_t.\r
+ * This object represents the generic attribute requester.\r
+ * This object is part of the opensm family of objects.\r
+ *\r
+ * Environment:\r
+ *    Linux User Mode\r
+ *\r
+ * $Revision: 1.8 $\r
+ */\r
+\r
+/*\r
+  Next available error code: 0x300\r
+*/\r
+#ifdef __WIN__\r
+/* Suppress all warning regarding casting void* to specific pointer object */\r
+#pragma warning(disable : 4305)\r
+#endif\r
+\r
+#include <vendor/osm_vendor_select.h>\r
+\r
+#ifdef OSM_VENDOR_INTF_AL\r
+\r
+#include <complib/cl_memory.h>\r
+#include <complib/cl_qlist.h>\r
+#include <complib/cl_thread.h>\r
+#include <complib/cl_math.h>\r
+#include <complib/cl_debug.h>\r
+#include <iba/ib_types.h>\r
+#include <opensm/osm_madw.h>\r
+#include <opensm/osm_log.h>\r
+#include <opensm/osm_mad_pool.h>\r
+#include <vendor/osm_vendor_api.h>\r
+\r
+/****s* OpenSM: Vendor AL/osm_al_bind_info_t\r
+ * NAME\r
+ *   osm_al_bind_info_t\r
+ *\r
+ * DESCRIPTION\r
+ *    Structure containing bind information.\r
+ *\r
+ * SYNOPSIS\r
+ */\r
+typedef struct _osm_al_bind_info\r
+{\r
+  osm_vendor_t                *p_vend;\r
+  void                        *client_context;\r
+  ib_qp_handle_t                 h_qp;\r
+  ib_mad_svc_handle_t               h_svc;\r
+  uint8_t                        port_num;\r
+  ib_pool_key_t                  pool_key;\r
+  osm_vend_mad_recv_callback_t      rcv_callback;\r
+  osm_vend_mad_send_err_callback_t  send_err_callback;\r
+  osm_mad_pool_t                 *p_osm_pool;\r
+  ib_av_handle_t                 h_dr_av;\r
+\r
+} osm_al_bind_info_t;\r
+/*\r
+ * FIELDS\r
+ * p_vend\r
+ *    Pointer to the vendor object.\r
+ *\r
+ * client_context\r
+ *    User's context passed during osm_bind\r
+ *\r
+ * h_qp\r
+ *    Handle the QP for this bind.\r
+ *\r
+ * h_qp_svc\r
+ *    Handle the QP mad service for this bind.\r
+ *\r
+ * port_num\r
+ *    Port number (within the HCA) of the bound port.\r
+ *\r
+ * pool_key\r
+ *    Pool key returned by all for this QP.\r
+ *\r
+ * h_dr_av\r
+ *    Address vector handle used for all directed route SMPs.\r
+ *\r
+ * SEE ALSO\r
+ *********/\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+inline static ib_api_status_t\r
+__osm_al_convert_wcs(\r
+  IN ib_wc_status_t        const wc_status )\r
+{\r
+  switch( wc_status )\r
+  {\r
+  case IB_WCS_SUCCESS:\r
+    return( IB_SUCCESS );\r
+\r
+  case IB_WCS_TIMEOUT_RETRY_ERR:\r
+    return( IB_TIMEOUT );\r
+\r
+  default:\r
+    return( IB_ERROR );\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void AL_API\r
+__osm_set_vend_wrap( IN  osm_al_bind_info_t* const p_bind,\r
+                     IN  ib_mad_element_t* const   p_elem,\r
+                     OUT osm_vend_wrap_t* p_vw)\r
+{\r
+    p_vw->h_bind = p_bind;\r
+    p_vw->size = p_elem->size;\r
+    p_vw->p_elem = p_elem;\r
+    p_vw->h_av = 0;\r
+    p_vw->p_resp_madw = NULL;\r
+\r
+}\r
+            \r
+\r
+static void AL_API\r
+__osm_al_ca_err_callback(\r
+  IN ib_async_event_rec_t *p_async_rec )\r
+{\r
+  osm_vendor_t *p_vend = (osm_vendor_t*)p_async_rec->context;\r
+  OSM_LOG_ENTER( p_vend->p_log, __osm_al_ca_err_callback );\r
+\r
+  osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+           "__osm_al_ca_err_callback: ERR 3B01: "\r
+           "Event on channel adapter (%s).\n",\r
+           ib_get_async_event_str( p_async_rec->code ) );\r
+\r
+  OSM_LOG_EXIT( p_vend->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static void AL_API\r
+__osm_al_ca_destroy_callback(\r
+  IN void *context )\r
+{\r
+  osm_al_bind_info_t *p_bind = (osm_al_bind_info_t*)context;\r
+  osm_vendor_t *p_vend = p_bind->p_vend;\r
+  OSM_LOG_ENTER( p_vend->p_log, __osm_al_ca_destroy_callback );\r
+\r
+  osm_log( p_vend->p_log, OSM_LOG_INFO,\r
+           "__osm_al_ca_destroy_callback: "\r
+           "Closing local channel adapter.\n" );\r
+\r
+  OSM_LOG_EXIT( p_vend->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+\r
+static void AL_API\r
+__osm_al_err_callback(\r
+  IN ib_async_event_rec_t *p_async_rec )\r
+{\r
+  osm_al_bind_info_t *p_bind = (osm_al_bind_info_t*)p_async_rec->context;\r
+  osm_vendor_t *p_vend = p_bind->p_vend;\r
+  OSM_LOG_ENTER( p_vend->p_log, __osm_al_err_callback );\r
+\r
+  osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+           "__osm_al_err_callback: ERR 3B02: "\r
+           "Error on QP (%s).\n",\r
+           ib_get_async_event_str( p_async_rec->code ) );\r
+\r
+  OSM_LOG_EXIT( p_vend->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+/* \r
+    Send_cb will handle  the following cases :\r
+    Element Status  |  Send Response (no reponse expected)      | Send Request (response expeceted)  \r
+    ================|===========================================|==========================================\r
+        ERROR       |   Free : AV , madw(send_err_cb)           | Free : AV , madw , resp_madw \r
+        SUCCESS     |   Free : AV , madw                        | Free : AV , madw\r
+\r
+    Element Status  |  Receive Response (no reponse expected)    \r
+    ================|===========================================\r
+        ERROR       |   Free : AV , madw(send_err_cb) \r
+        SUCCESS     |   Free : AV , madw, resp_madw (both through rcv_callback)                        \r
+   \r
+*/    \r
+static void AL_API\r
+__osm_al_send_callback(\r
+  IN const ib_mad_svc_handle_t h_mad_svc,\r
+  IN void *mad_svc_context,\r
+  IN ib_mad_element_t *p_elem )\r
+{\r
+  osm_al_bind_info_t* const p_bind = (osm_al_bind_info_t*)mad_svc_context;\r
+  osm_vendor_t* const p_vend = p_bind->p_vend;\r
+  osm_madw_t* const p_madw = (osm_madw_t*)p_elem->context1;\r
+  osm_vend_wrap_t* p_vw = osm_madw_get_vend_ptr( p_madw );\r
+  ib_mad_t *p_mad = ib_get_mad_buf( p_elem );\r
+  ib_av_attr_t         av_attr;\r
+  ib_pd_handle_t               h_pd;\r
+  ib_api_status_t status_elem,status;\r
+  osm_madw_t *p_new_madw;\r
+\r
+  OSM_LOG_ENTER( p_vend->p_log, __osm_al_send_callback );\r
+  UNUSED_PARAM(h_mad_svc);\r
+  CL_ASSERT( p_vw );\r
+  CL_ASSERT( p_vw->h_av );\r
+  /* since we use context1 , safely , and its the only place that remove the clean \r
+    p_elem,p_madw , h_av no checks are required */\r
+  status_elem = __osm_al_convert_wcs(p_elem->status);\r
+  osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+           "__osm_al_send_callback: "\r
+           "Destroying av handle %p.\n", p_elem->h_av );\r
+  /* Check first if its a direct route handle , in this case skip */\r
+  if (p_elem->h_av != p_bind->h_dr_av) \r
+  {\r
+      ib_destroy_av( p_elem->h_av );\r
+  }\r
+  /* Since the free order is first resp_madw then madw (PARENT) we should check\r
+   this case first */\r
+  if (p_elem->resp_expected)\r
+  {\r
+      p_madw->status = status_elem;\r
+      if ( status_elem != IB_SUCCESS )\r
+      {\r
+          /*\r
+              Return any wrappers to the pool that may have been\r
+              pre-emptively allocated to handle a receive.\r
+          */\r
+          osm_log(p_vend->p_log, OSM_LOG_ERROR,\r
+                  "__osm_al_send_callback: ERR 3333 "\r
+                  " Mad Completed with WQE Error : %s.\n",ib_get_wc_status_str(p_elem->status));\r
+          if( p_vw->p_resp_madw )\r
+          {\r
+              osm_mad_pool_put( p_bind->p_osm_pool, p_vw->p_resp_madw );\r
+              p_vw->p_resp_madw = NULL;\r
+          }\r
+\r
+          p_bind->send_err_callback( p_bind->client_context, p_madw );\r
+      }\r
+      else\r
+      {\r
+          /* We are in response flow of receive , need to apply the rcv_callback \r
+                The rcv_callback will free the resp_madw , req_madw , p_elem of receive\r
+                and request */\r
+          osm_log(p_vend->p_log, OSM_LOG_DEBUG,\r
+                  "__osm_al_send_callback: "\r
+                  "The Mad is a response , thus handeled in __osm_al_send_callback\n");\r
+          p_new_madw = p_vw->p_resp_madw;\r
+          p_bind->rcv_callback( p_new_madw, p_bind->client_context,\r
+                                p_madw );\r
+\r
+      }\r
+  }\r
+  else\r
+  {\r
+      osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+           "__osm_al_send_callback: "\r
+           "Returning MAD to pool, TID = 0x%" PRIx64 ".\n",\r
+           cl_ntoh64( p_mad->trans_id ) );\r
+      osm_mad_pool_put( p_bind->p_osm_pool, p_madw );\r
+      if ( status_elem != IB_SUCCESS )\r
+          osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+           "__osm_al_send_callback: ERR 3b0b "\r
+           "request mad had failed.\n");\r
+      goto Exit;\r
+  }\r
+\r
+\r
+\r
+\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( p_vend->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+/*\r
+    Receive_cb will be applied in the following cases :\r
+    Element Status  |  Receive Response (no reponse expected)      | Receive Request (response expeceted)  \r
+    ================|==============================================|=======================================\r
+        ERROR       |  NOT APPLIED                                 | NOT_APPLIED\r
+        SUCCESS     |  Free :  Resp_madw , copy_req_madw           | Allocate new_madw (for response then in send_cb free)\r
+ */\r
+ static void AL_API\r
+__osm_al_rcv_callback(\r
+  IN const ib_mad_svc_handle_t h_mad_svc,\r
+  IN void *mad_svc_context,\r
+  IN ib_mad_element_t *p_elem )\r
+{\r
+  osm_al_bind_info_t* const p_bind = (osm_al_bind_info_t*)mad_svc_context;\r
+  osm_vendor_t* const p_vend = p_bind->p_vend;\r
+  osm_madw_t *p_old_madw,*p_copy_old_madw;\r
+  osm_madw_t *p_new_madw;\r
+  osm_vend_wrap_t* p_old_vw;\r
+  osm_vend_wrap_t* p_new_vw;\r
+  ib_mad_t *p_new_mad;\r
+  osm_mad_addr_t mad_addr;\r
+\r
+  OSM_LOG_ENTER( p_vend->p_log, __osm_al_rcv_callback );\r
+  UNUSED_PARAM(h_mad_svc);\r
+  CL_ASSERT( p_elem->context1 == NULL );\r
+  CL_ASSERT( p_elem->context2 == NULL );\r
+    /*\r
+  osm_log( p_vend->p_log, OSM_LOG_VERBOSE,\r
+             "__osm_al_rcv_callback:  "\r
+             "Handling Transaction : 0x%" PRIx64 " .\n",\r
+           cl_ntoh64(p_elem->p_mad_buf->trans_id));\r
+           */\r
+  p_new_mad = ib_get_mad_buf( p_elem );\r
+  osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+           "__osm_al_rcv_callback: "\r
+           "Acquired implicitly MAD %p.\n", p_new_mad );\r
+\r
+  /*\r
+    In preperation for initializing the new mad wrapper,\r
+    Initialize the mad_addr structure for the received wire MAD.\r
+  */\r
+  mad_addr.dest_lid = p_elem->remote_lid;\r
+  mad_addr.path_bits = p_elem->path_bits;\r
+\r
+  /* TO DO - figure out which #define to use for the 2.5 Gb rate... */\r
+  mad_addr.static_rate = 0;\r
+\r
+  if( p_new_mad->mgmt_class == IB_MCLASS_SUBN_LID ||\r
+      p_new_mad->mgmt_class == IB_MCLASS_SUBN_DIR )\r
+  {\r
+    mad_addr.addr_type.smi.source_lid = p_elem->remote_lid;\r
+  }\r
+  else\r
+  {\r
+    mad_addr.addr_type.gsi.remote_qp = p_elem->remote_qp;\r
+    mad_addr.addr_type.gsi.remote_qkey = p_elem->remote_qkey;\r
+    mad_addr.addr_type.gsi.pkey = p_elem->pkey_index;\r
+    mad_addr.addr_type.gsi.service_level = p_elem->remote_sl;\r
+    mad_addr.addr_type.gsi.global_route = FALSE;\r
+  }\r
+\r
+  /*\r
+    If this MAD is a response to a previous request,\r
+    then grab our pre-allocated MAD wrapper.\r
+    Otherwise, allocate a new MAD wrapper.\r
+    context1 - contains the request madw\r
+  */\r
+  if( ib_mad_is_response( p_new_mad ) )\r
+  {\r
+    /*\r
+      The acquiring was done in the ib_get_mad_buf function. \r
+      If this is a request - then we impllicitly allocate the MAD.\r
+      In this case - it was allocated in the lower layer. The message\r
+      is for tracking down messages - locate how/where this mad was\r
+      allocated.\r
+    */\r
+    osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+               "__osm_al_rcv_callback: "\r
+               "The Mad is a response , thus handeled in __osm_al_send_callback\n");\r
+    CL_ASSERT( p_elem->send_context1 != NULL );\r
+    CL_ASSERT( p_elem->send_context2 == NULL );\r
+\r
+    p_old_madw = (osm_madw_t*)p_elem->send_context1;\r
+    p_old_vw = osm_madw_get_vend_ptr( p_old_madw );\r
+    p_new_madw = p_old_vw->p_resp_madw;\r
+\r
+    CL_ASSERT( p_new_madw );\r
+    osm_madw_init( p_new_madw, p_bind, p_elem->size,\r
+                   &mad_addr );\r
+    osm_madw_set_mad( p_new_madw, p_new_mad );\r
+    p_new_vw = osm_madw_get_vend_ptr( p_new_madw );\r
+    __osm_set_vend_wrap(p_bind,p_elem,p_new_vw);\r
+    goto Exit;\r
+  }\r
+  else\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+                 "__osm_al_rcv_callback: "\r
+                 "The Mad is a request , thus handeled in __osm_al_rcv_callback\n");\r
+    CL_ASSERT( p_elem->send_context1 == NULL );\r
+    CL_ASSERT( p_elem->send_context2 == NULL );\r
+\r
+    p_new_madw = osm_mad_pool_get_wrapper( p_bind->p_osm_pool,\r
+                                           p_bind, p_elem->size, p_new_mad, &mad_addr );\r
+    CL_ASSERT(p_new_madw);\r
+    p_new_vw = osm_madw_get_vend_ptr( p_new_madw );\r
+\r
+    __osm_set_vend_wrap(p_bind,p_elem,p_new_vw);\r
+    osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+             "__osm_al_rcv_callback: "\r
+             "Calling receive callback function %p.\n",\r
+             p_bind->rcv_callback );\r
+\r
+\r
+    p_bind->rcv_callback( p_new_madw, p_bind->client_context,\r
+                          ((osm_madw_t*)p_elem->send_context1) );\r
+  }\r
+\r
+\r
+  Exit:\r
+  OSM_LOG_EXIT( p_vend->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osm_vendor_init(\r
+  IN osm_vendor_t* const p_vend,\r
+  IN osm_log_t* const p_log,\r
+  IN const uint32_t timeout )\r
+{\r
+  ib_api_status_t status;\r
+  OSM_LOG_ENTER( p_log, osm_vendor_init );\r
+\r
+  p_vend->p_log = p_log;\r
+\r
+  /*\r
+    Open our instance of AL.\r
+  */\r
+  status = ib_open_al( &p_vend->h_al );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+             "osm_vendor_init: ERR 3B03: "\r
+             "Error opening AL (%s).\n",\r
+             ib_get_err_str( status ) );\r
+\r
+    goto Exit;\r
+  }\r
+\r
+  p_vend->timeout = timeout;\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( p_log );\r
+  return( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+osm_vendor_t*\r
+osm_vendor_new(\r
+  IN osm_log_t* const p_log,\r
+  IN const uint32_t timeout )\r
+{\r
+  ib_api_status_t    status;\r
+  osm_vendor_t    *p_vend;\r
+\r
+  OSM_LOG_ENTER( p_log, osm_vendor_new );\r
+\r
+  p_vend = cl_zalloc( sizeof(*p_vend) );\r
+  if( p_vend == NULL )\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+             "osm_vendor_new: ERR 3B04: "\r
+             "Unable to allocate vendor object.\n" );\r
+    goto Exit;\r
+  }\r
+\r
+  status = osm_vendor_init( p_vend, p_log, timeout );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    cl_free( p_vend );\r
+    p_vend = NULL;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( p_log );\r
+  return( p_vend );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_vendor_delete(\r
+  IN osm_vendor_t** const pp_vend )\r
+{\r
+  /* TO DO - fill this in */\r
+  ib_close_al( (*pp_vend)->h_al );\r
+  cl_free( *pp_vend );\r
+  *pp_vend = NULL;\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+__osm_ca_info_init(\r
+  IN osm_vendor_t*        const p_vend,\r
+  IN osm_ca_info_t*  const   p_ca_info,\r
+  IN const ib_net64_t      ca_guid )\r
+{\r
+  ib_api_status_t status;\r
+\r
+  OSM_LOG_ENTER( p_vend->p_log, __osm_ca_info_init );\r
+\r
+  p_ca_info->guid = ca_guid;\r
+\r
+  if( osm_log_is_active( p_vend->p_log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_VERBOSE,\r
+             "__osm_ca_info_init: "\r
+             "Querying CA 0x%" PRIx64 ".\n",\r
+             cl_ntoh64( ca_guid ) );\r
+  }\r
+/* attr size by verbs definition is required to be (uint32_t *) under opensm is only being set as 1 */\r
+  status = ib_query_ca_by_guid( p_vend->h_al, ca_guid, NULL,\r
+                                (uint32_t*)&p_ca_info->attr_size );\r
+  if( (status != IB_INSUFFICIENT_MEMORY ) && (status != IB_SUCCESS ) )\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+             "__osm_ca_info_init: ERR 3B05: "\r
+             "Unexpected status getting CA attributes (%s).\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  CL_ASSERT( p_ca_info->attr_size );\r
+\r
+  p_ca_info->p_attr = cl_malloc( p_ca_info->attr_size );\r
+  if( p_ca_info->p_attr == NULL )\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+             "__osm_ca_info_init: ERR 3B06: "\r
+             "Unable to allocate attribute storage.\n" );\r
+    goto Exit;\r
+  }\r
+\r
+  status = ib_query_ca_by_guid( p_vend->h_al, ca_guid, p_ca_info->p_attr,\r
+                                (uint32_t*)&p_ca_info->attr_size );\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+             "__osm_ca_info_init: ERR 3B07: "\r
+             "Unexpected status getting CA attributes (%s).\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( p_vend->p_log );\r
+  return( status );\r
+}\r
+\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_ca_info_destroy(\r
+  IN osm_vendor_t*        const p_vend,\r
+  IN osm_ca_info_t*     const p_ca_info )\r
+{\r
+  OSM_LOG_ENTER( p_vend->p_log, osm_ca_info_destroy );\r
+\r
+  if( p_ca_info->p_attr )\r
+    cl_free( p_ca_info->p_attr );\r
+\r
+  cl_free( p_ca_info );\r
+\r
+  OSM_LOG_EXIT( p_vend->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+osm_ca_info_t*\r
+osm_ca_info_new(\r
+  IN osm_vendor_t*        const p_vend,\r
+  IN const ib_net64_t      ca_guid )\r
+{\r
+  ib_api_status_t status;\r
+  osm_ca_info_t *p_ca_info;\r
+\r
+  OSM_LOG_ENTER( p_vend->p_log, osm_ca_info_new );\r
+\r
+  CL_ASSERT( ca_guid );\r
+\r
+  p_ca_info = cl_zalloc( sizeof(*p_ca_info) );\r
+  if( p_ca_info == NULL )\r
+    goto Exit;\r
+\r
+  status = __osm_ca_info_init( p_vend, p_ca_info, ca_guid );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_ca_info_destroy( p_vend, p_ca_info );\r
+    p_ca_info = NULL;\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( p_vend->p_log );\r
+  return( p_ca_info );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+__osm_vendor_get_ca_guids(\r
+  IN osm_vendor_t*        const p_vend,\r
+  IN ib_net64_t**       const p_guids,\r
+  IN size_t*           const p_num_guids )\r
+{\r
+  ib_api_status_t status;\r
+\r
+  OSM_LOG_ENTER( p_vend->p_log, __osm_vendor_get_ca_guids );\r
+\r
+  CL_ASSERT( p_guids );\r
+  CL_ASSERT( p_num_guids );\r
+\r
+  status = ib_get_ca_guids( p_vend->h_al, NULL, p_num_guids );\r
+  if( (status != IB_INSUFFICIENT_MEMORY ) && (status != IB_SUCCESS ) )\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+             "__osm_vendor_get_ca_guids: ERR 3B08: "\r
+             "Unexpected status getting CA GUID array (%s).\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  if( *p_num_guids == 0 )\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+             "__osm_vendor_get_ca_guids: ERR 3B09: "\r
+             "No available channel adapters.\n" );\r
+    status = IB_INSUFFICIENT_RESOURCES;\r
+    goto Exit;\r
+  }\r
+\r
+  *p_guids = cl_malloc( *p_num_guids * sizeof(**p_guids) );\r
+  if( *p_guids == NULL )\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+             "__osm_vendor_get_ca_guids: ERR 3B10: "\r
+             "Unable to allocate CA GUID array.\n" );\r
+    goto Exit;\r
+  }\r
+\r
+  status = ib_get_ca_guids( p_vend->h_al, *p_guids, p_num_guids );\r
+  CL_ASSERT( *p_num_guids );\r
+\r
+  if( osm_log_is_active( p_vend->p_log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_VERBOSE,\r
+             "__osm_vendor_get_ca_guids: "\r
+             "Detected %u local channel adapters.\n", *p_num_guids );\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( p_vend->p_log );\r
+  return( status );\r
+}\r
+\r
+/****f* OpenSM: CA Info/osm_ca_info_get_pi_ptr\r
+ * NAME\r
+ * osm_ca_info_get_pi_ptr\r
+ *\r
+ * DESCRIPTION\r
+ * Returns a pointer to the port attribute of the specified port\r
+ * owned by this CA.\r
+ *\r
+ * SYNOPSIS\r
+ */\r
+static ib_port_attr_t*\r
+__osm_ca_info_get_port_attr_ptr(\r
+  IN const osm_ca_info_t* const p_ca_info,\r
+  IN const uint8_t index )\r
+{\r
+  return( &p_ca_info->p_attr->p_port_attr[index] );\r
+}\r
+/*\r
+ * PARAMETERS\r
+ * p_ca_info\r
+ *    [in] Pointer to a CA Info object.\r
+ *\r
+ * index\r
+ *    [in] Port "index" for which to retrieve the port attribute.\r
+ *    The index is the offset into the ca's internal array\r
+ *    of port attributes.\r
+ *\r
+ * RETURN VALUE\r
+ * Returns a pointer to the port attribute of the specified port\r
+ * owned by this CA.\r
+ * Also allocate p_vend->p_ca_info if not allocated and init it .\r
+ *\r
+ * NOTES\r
+ *\r
+ * SEE ALSO\r
+ *********/\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osm_vendor_get_all_port_attr(\r
+  IN osm_vendor_t*        const p_vend,\r
+  IN ib_port_attr_t*    const p_attr_array,\r
+  IN uint32_t*       const p_num_ports )\r
+{\r
+  ib_api_status_t status;\r
+\r
+  uint32_t ca;\r
+  size_t ca_count;\r
+  uint32_t port_count = 0;\r
+  uint8_t port_num;\r
+  uint32_t total_ports = 0;\r
+  ib_net64_t *p_ca_guid = NULL;\r
+  osm_ca_info_t *p_ca_info;\r
+\r
+  OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get_all_port_attr );\r
+\r
+  CL_ASSERT( p_vend );\r
\r
+  /*\r
+    1) Determine the number of CA's\r
+    2) If not allready allocated - allocate an array big enough to hold the\r
+         ca info object , the ca info will be overwrite to contain the new ca info\r
+    3) Call again to retrieve the guids.\r
+  */\r
+  status = __osm_vendor_get_ca_guids( p_vend, &p_ca_guid, &ca_count );\r
+\r
+  if (p_vend->p_ca_info == NULL) \r
+  {\r
+      p_vend->p_ca_info = cl_zalloc( ca_count * sizeof(*(p_vend->p_ca_info)) );\r
+      \r
+      if( p_vend->p_ca_info == NULL )\r
+      {\r
+        osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+                 "osm_vendor_get_all_port_attr: ERR 3B11: "\r
+                 "Unable to allocate CA information array.\n" );\r
+        goto Exit;\r
+      }\r
+  }\r
+\r
+  p_vend->ca_count = ca_count;\r
+\r
+  /*\r
+    For each CA, retrieve the port info attributes\r
+  */\r
+  for( ca = 0; ca < ca_count; ca++ )\r
+  {\r
+    p_ca_info = &p_vend->p_ca_info[ca];\r
+\r
+    status = __osm_ca_info_init(\r
+      p_vend,\r
+      p_ca_info,\r
+      p_ca_guid[ca] );\r
+\r
+    if( status != IB_SUCCESS )\r
+    {\r
+      osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+               "osm_vendor_get_all_port_attr: ERR 3B12: "\r
+               "Unable to initialize CA Info object (%s).\n",\r
+               ib_get_err_str( status ) );\r
+    }\r
+\r
+    total_ports += osm_ca_info_get_num_ports( p_ca_info );\r
+  }\r
+\r
+  /*\r
+    If the user supplied enough storage, return the port guids,\r
+    otherwise, return the appropriate error.\r
+  */\r
+  if( *p_num_ports >= total_ports )\r
+  {\r
+    for( ca = 0; ca < ca_count; ca++ )\r
+    {\r
+      uint32_t num_ports;\r
+\r
+      p_ca_info = &p_vend->p_ca_info[ca];\r
+\r
+      num_ports = osm_ca_info_get_num_ports( p_ca_info );\r
+\r
+      for( port_num = 0; port_num < num_ports; port_num++ )\r
+      {\r
+        p_attr_array[port_count] = \r
+          *__osm_ca_info_get_port_attr_ptr( p_ca_info, port_num );\r
+        /* convert lid to host order */\r
+        p_attr_array[port_count].lid = cl_ntoh16(p_attr_array[port_count].lid);\r
+        port_count++;\r
+      }\r
+    }\r
+  }\r
+  else\r
+  {\r
+    status = IB_INSUFFICIENT_MEMORY;\r
+  }\r
+\r
+\r
+  *p_num_ports = total_ports;\r
+\r
+\r
+ Exit:\r
+  if( p_ca_guid )\r
+    cl_free( p_ca_guid );\r
+\r
+  OSM_LOG_EXIT( p_vend->p_log );\r
+  return( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_net64_t\r
+osm_vendor_get_ca_guid(\r
+  IN osm_vendor_t* const p_vend,\r
+  IN const ib_net64_t port_guid )\r
+{\r
+  uint8_t index;\r
+  uint8_t num_ports;\r
+  uint32_t num_guids = 0;\r
+  osm_ca_info_t *p_ca_info;\r
+  uint32_t ca;\r
+\r
+  OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get_ca_guid );\r
+\r
+  CL_ASSERT( port_guid );\r
+  /*\r
+    First, locate the HCA that owns this port.\r
+  */\r
+  if( p_vend->p_ca_info == NULL )\r
+  {\r
+    /*\r
+      Initialize the osm_ca_info_t array which allows\r
+      us to match port GUID to CA.\r
+    */\r
+    osm_vendor_get_all_port_attr( p_vend, NULL, &num_guids );\r
+  }\r
+\r
+  CL_ASSERT( p_vend->p_ca_info );\r
+  CL_ASSERT( p_vend->ca_count );\r
+\r
+  for( ca = 0; ca < p_vend->ca_count; ca++ )\r
+  {\r
+    p_ca_info = &p_vend->p_ca_info[ca];\r
+\r
+    num_ports = osm_ca_info_get_num_ports( p_ca_info );\r
+    CL_ASSERT( num_ports );\r
+\r
+    for( index = 0; index < num_ports; index++ )\r
+    {\r
+      if( port_guid ==\r
+          osm_ca_info_get_port_guid( p_ca_info, index ) )\r
+      {\r
+        OSM_LOG_EXIT( p_vend->p_log );\r
+        return( osm_ca_info_get_ca_guid( p_ca_info ) );\r
+      }\r
+    }\r
+  }\r
+\r
+  /*\r
+    No local CA owns this guid!\r
+  */\r
+  osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+           "osm_vendor_get_ca_guid: ERR 3B13: "\r
+           "Unable to determine CA guid.\n" );\r
+\r
+  OSM_LOG_EXIT( p_vend->p_log );\r
+  return( 0 );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+uint8_t\r
+osm_vendor_get_port_num(\r
+  IN osm_vendor_t* const p_vend,\r
+  IN const ib_net64_t port_guid )\r
+{\r
+  uint8_t index;\r
+  uint8_t num_ports;\r
+  uint32_t num_guids = 0;\r
+  osm_ca_info_t *p_ca_info;\r
+  uint32_t ca;\r
+\r
+  OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get_port_num );\r
+\r
+  CL_ASSERT( port_guid );\r
+  /*\r
+    First, locate the HCA that owns this port.\r
+  */\r
+  if( p_vend->p_ca_info == NULL )\r
+  {\r
+    /*\r
+      Initialize the osm_ca_info_t array which allows\r
+      us to match port GUID to CA.\r
+    */\r
+    osm_vendor_get_all_port_attr( p_vend, NULL, &num_guids );\r
+  }\r
+\r
+  CL_ASSERT( p_vend->p_ca_info );\r
+  CL_ASSERT( p_vend->ca_count );\r
+\r
+  for( ca = 0; ca < p_vend->ca_count; ca++ )\r
+  {\r
+    p_ca_info = &p_vend->p_ca_info[ca];\r
+\r
+    num_ports = osm_ca_info_get_num_ports( p_ca_info );\r
+    CL_ASSERT( num_ports );\r
+\r
+    for( index = 0; index < num_ports; index++ )\r
+    {\r
+      if( port_guid ==\r
+          osm_ca_info_get_port_guid( p_ca_info, index ) )\r
+      {\r
+        OSM_LOG_EXIT( p_vend->p_log );\r
+        return( osm_ca_info_get_port_num( p_ca_info, index ) );\r
+      }\r
+    }\r
+  }\r
\r
+  /*\r
+    No local CA owns this guid!\r
+  */\r
+  osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+           "osm_vendor_get_port_num: ERR 3B30: "\r
+           "Unable to determine CA guid.\n" );\r
+\r
+  OSM_LOG_EXIT( p_vend->p_log );\r
+  return( 0 );\r
+}\r
+\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+__osm_vendor_open_ca(\r
+  IN osm_vendor_t* const p_vend,\r
+  IN const ib_net64_t port_guid )\r
+{\r
+  ib_net64_t ca_guid;\r
+  ib_api_status_t status;\r
+\r
+  OSM_LOG_ENTER( p_vend->p_log, __osm_vendor_open_ca );\r
+\r
+  ca_guid = osm_vendor_get_ca_guid( p_vend, port_guid );\r
+  if( ca_guid == 0 )\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+             "__osm_vendor_open_ca: ERR 3B31: "\r
+             "Bad port GUID value 0x%" PRIx64 ".\n",\r
+             cl_ntoh64( port_guid ) );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  osm_log( p_vend->p_log, OSM_LOG_VERBOSE,\r
+           "__osm_vendor_open_ca: "\r
+           "Opening HCA 0x%" PRIx64 ".\n",   cl_ntoh64( ca_guid ) );\r
+\r
+  status = ib_open_ca( p_vend->h_al,\r
+                       ca_guid,\r
+                       __osm_al_ca_err_callback,\r
+                       p_vend,\r
+                       &p_vend->h_ca );\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+             "__osm_vendor_open_ca: ERR 3B15: "\r
+             "Unable to open CA (%s).\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  CL_ASSERT( p_vend->h_ca );\r
+\r
+  status = ib_alloc_pd(\r
+    p_vend->h_ca,\r
+    IB_PDT_ALIAS,\r
+    p_vend,\r
+    &p_vend->h_pd );\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    ib_close_ca( p_vend->h_ca,__osm_al_ca_destroy_callback  );\r
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+             "__osm_vendor_open_ca: ERR 3B16: "\r
+             "Unable to allocate protection domain (%s).\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  CL_ASSERT( p_vend->h_pd );\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( p_vend->p_log );\r
+  return( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static void\r
+__osm_vendor_init_av(\r
+  IN const osm_al_bind_info_t* p_bind,\r
+  IN ib_av_attr_t* p_av )\r
+{\r
+  cl_memclr( p_av, sizeof(*p_av) );\r
+  p_av->port_num = p_bind->port_num;\r
+  p_av->dlid = IB_LID_PERMISSIVE;\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+osm_bind_handle_t\r
+osm_vendor_bind(\r
+  IN osm_vendor_t* const p_vend,\r
+  IN osm_bind_info_t* const p_user_bind,\r
+  IN osm_mad_pool_t* const p_mad_pool,\r
+  IN osm_vend_mad_recv_callback_t mad_recv_callback,\r
+  IN osm_vend_mad_send_err_callback_t send_err_callback,\r
+  IN void* context )\r
+{\r
+  ib_net64_t port_guid;\r
+  osm_al_bind_info_t *p_bind = 0;\r
+  ib_api_status_t status;\r
+  ib_qp_create_t qp_create;\r
+  ib_mad_svc_t mad_svc;\r
+  ib_av_attr_t av;\r
+\r
+  OSM_LOG_ENTER( p_vend->p_log, osm_vendor_bind );\r
+\r
+  CL_ASSERT( p_user_bind );\r
+  CL_ASSERT( p_mad_pool );\r
+  CL_ASSERT( mad_recv_callback );\r
+  CL_ASSERT( send_err_callback );\r
+\r
+  port_guid = p_user_bind->port_guid;\r
+  osm_log( p_vend->p_log, OSM_LOG_INFO,\r
+           "osm_vendor_bind: "\r
+           "Binding to port 0x%" PRIx64 ".\n",\r
+           cl_ntoh64( port_guid ) );\r
+\r
+  if( p_vend->h_ca == 0 )\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+             "osm_vendor_bind: "\r
+             "Opening CA that owns port 0x%" PRIx64 ".\n", cl_ntoh64( port_guid ));\r
+\r
+    status = __osm_vendor_open_ca( p_vend, port_guid );\r
+    if( status != IB_SUCCESS )\r
+    {\r
+      osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+               "osm_vendor_bind: ERR 3B17: "\r
+               "Unable to Open CA (%s).\n",\r
+               ib_get_err_str( status ) );\r
+      goto Exit;\r
+    }\r
+  }\r
+\r
+  p_bind = cl_zalloc( sizeof(*p_bind) );\r
+  if( p_bind == NULL )\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+             "osm_vendor_bind: ERR 3B18: "\r
+             "Unable to allocate internal bind object.\n" );\r
+    goto Exit;\r
+  }\r
+\r
+  p_bind->p_vend = p_vend;\r
+  p_bind->client_context = context;\r
+  p_bind->port_num = osm_vendor_get_port_num( p_vend, port_guid );\r
+  p_bind->rcv_callback = mad_recv_callback;\r
+  p_bind->send_err_callback = send_err_callback;\r
+  p_bind->p_osm_pool = p_mad_pool;\r
+\r
+  CL_ASSERT( p_bind->port_num );\r
+\r
+  /*\r
+    Get the proper QP.\r
+  */\r
+  cl_memclr( &qp_create, sizeof(qp_create) );\r
+\r
+  switch( p_user_bind->mad_class )\r
+  {\r
+  case IB_MCLASS_SUBN_LID:\r
+  case IB_MCLASS_SUBN_DIR:\r
+    qp_create.qp_type = IB_QPT_QP0_ALIAS;\r
+    break;\r
+\r
+  case IB_MCLASS_SUBN_ADM:\r
+  default:\r
+    qp_create.qp_type = IB_QPT_QP1_ALIAS;\r
+    break;\r
+  }\r
+\r
+  qp_create.sq_depth = p_user_bind->send_q_size;\r
+  qp_create.rq_depth = p_user_bind->recv_q_size;\r
+  qp_create.sq_sge = OSM_AL_SQ_SGE;\r
+  qp_create.rq_sge = OSM_AL_RQ_SGE;\r
+  status = ib_get_spl_qp(\r
+    p_vend->h_pd,\r
+    port_guid,\r
+    &qp_create,\r
+    p_bind,\r
+    __osm_al_err_callback,\r
+    &p_bind->pool_key,\r
+    &p_bind->h_qp );\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+             "osm_vendor_bind: ERR 3B19: "\r
+             "Unable to get QP handle (%s).\n",\r
+             ib_get_err_str( status ) );\r
+    cl_free( p_bind );\r
+    p_bind = 0;\r
+    goto Exit;\r
+  }\r
+\r
+  CL_ASSERT( p_bind->h_qp );\r
+  CL_ASSERT( p_bind->pool_key );\r
+\r
+  cl_memclr( &mad_svc, sizeof(mad_svc) );\r
+\r
+  mad_svc.mad_svc_context = p_bind;\r
+  mad_svc.pfn_mad_send_cb = __osm_al_send_callback; \r
+  mad_svc.pfn_mad_recv_cb = __osm_al_rcv_callback;\r
+  mad_svc.mgmt_class = p_user_bind->mad_class;\r
+  mad_svc.mgmt_version = p_user_bind->class_version;\r
+  mad_svc.support_unsol = p_user_bind->is_responder;\r
+  mad_svc.method_array[IB_MAD_METHOD_GET] = TRUE;\r
+  mad_svc.method_array[IB_MAD_METHOD_SET] = TRUE;\r
+  mad_svc.method_array[IB_MAD_METHOD_DELETE] = TRUE;\r
+  mad_svc.method_array[IB_MAD_METHOD_TRAP] = TRUE;\r
+  mad_svc.method_array[IB_MAD_METHOD_GETTABLE] = TRUE;\r
+\r
+\r
+  status = ib_reg_mad_svc(\r
+    p_bind->h_qp,\r
+    &mad_svc,\r
+    &p_bind->h_svc );\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+             "osm_vendor_bind: ERR 3B21: "\r
+             "Unable to register QP0 MAD service (%s).\n",\r
+             ib_get_err_str( status ) );\r
+    cl_free( p_bind );\r
+    p_bind = 0;\r
+    goto Exit;\r
+  }\r
+\r
+  __osm_vendor_init_av( p_bind, &av );\r
+\r
+  status = ib_create_av( p_vend->h_pd, &av, &(p_bind->h_dr_av) );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+             "osm_vendor_bind: ERR 3B22: "\r
+             "Unable to create address vector (%s).\n",\r
+             ib_get_err_str( status ) );\r
+\r
+    cl_free( p_bind );\r
+    p_bind = 0;\r
+    goto Exit;\r
+  }\r
+\r
+  if( osm_log_is_active( p_vend->p_log, OSM_LOG_DEBUG ) )\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+             "osm_vendor_bind: "\r
+             "Allocating av handle %p.\n", p_bind->h_dr_av );\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( p_vend->p_log );\r
+  return( (osm_bind_handle_t)p_bind );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+/* osm_vendor_unbind is added due to OSM-1.8.0 gen2 merging\r
+    The functionality will be added when the Gen2 osm_vendor_unbind\r
+    will be implemented.\r
+*/    \r
+void\r
+osm_vendor_unbind(\r
+  IN osm_bind_handle_t h_bind)\r
+{\r
+       osm_al_bind_info_t *p_bind = ( osm_al_bind_info_t * ) h_bind;\r
+       osm_vendor_t *p_vend = p_bind->p_vend;\r
+\r
+\r
+       OSM_LOG_ENTER( p_vend->p_log, osm_vendor_unbind );\r
+\r
+       OSM_LOG_EXIT( p_vend->p_log);\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_mad_t*\r
+osm_vendor_get(\r
+  IN osm_bind_handle_t  h_bind,\r
+  IN const uint32_t     mad_size,\r
+  IN osm_vend_wrap_t*      const p_vw )\r
+{\r
+  ib_mad_t *p_mad;\r
+  osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;\r
+  osm_vendor_t *p_vend = p_bind->p_vend;\r
+  ib_api_status_t status;\r
+\r
+  OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get );\r
+\r
+  CL_ASSERT( p_vw );\r
+\r
+  p_vw->size = mad_size;\r
+  p_vw->h_bind = h_bind;\r
+\r
+  /*\r
+    Retrieve a MAD element from the pool and give the user direct\r
+    access to its buffer.\r
+  */\r
+  status = ib_get_mad( p_bind->pool_key, mad_size, &p_vw->p_elem );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+             "osm_vendor_get: ERR 3B25: "\r
+             "Unable to acquire MAD (%s).\n",\r
+             ib_get_err_str( status ) );\r
+\r
+    p_mad = NULL;\r
+    goto Exit;\r
+  }\r
+\r
+  CL_ASSERT( p_vw->p_elem );\r
+  p_mad = ib_get_mad_buf( p_vw->p_elem );\r
+\r
+  if( osm_log_get_level( p_vend->p_log ) >= OSM_LOG_DEBUG )\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+             "osm_vendor_get: "\r
+             "Acquired MAD %p, size = %u.\n", p_mad, mad_size );\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( p_vend->p_log );\r
+  return( p_mad );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_vendor_put(\r
+  IN osm_bind_handle_t h_bind,\r
+  IN osm_vend_wrap_t* const p_vw )\r
+{\r
+  osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;\r
+  osm_vendor_t *p_vend = p_bind->p_vend;\r
+  ib_api_status_t status;\r
+\r
+  OSM_LOG_ENTER( p_vend->p_log, osm_vendor_put );\r
+\r
+  CL_ASSERT( p_vw );\r
+  CL_ASSERT( p_vw->p_elem );\r
+  CL_ASSERT( p_vw->h_bind == h_bind );\r
+\r
+  if( osm_log_get_level( p_vend->p_log ) >= OSM_LOG_DEBUG )\r
+  {\r
+       \r
+    osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+             "osm_vendor_put: "\r
+             "Retiring MAD %p.\n", ib_get_mad_buf( p_vw->p_elem ) );\r
+  //            "Retiring MAD %p.\n", p_mad);\r
+  }\r
+\r
+  status = ib_put_mad( p_vw->p_elem );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+             "osm_vendor_put: ERR 3B26: "\r
+             "Unable to retire MAD (%s).\n",\r
+             ib_get_err_str( status ) );\r
+  }\r
+\r
+  OSM_LOG_EXIT( p_vend->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osm_vendor_send(\r
+  IN osm_bind_handle_t h_bind,\r
+  IN osm_madw_t* const p_madw,\r
+  IN boolean_t const resp_expected )\r
+{\r
+  osm_al_bind_info_t* const p_bind = h_bind;\r
+  osm_vendor_t* const p_vend = p_bind->p_vend;\r
+  osm_vend_wrap_t* const p_vw = osm_madw_get_vend_ptr( p_madw );\r
+  osm_mad_addr_t* const p_mad_addr = osm_madw_get_mad_addr_ptr( p_madw );\r
+  ib_mad_t* const p_mad = osm_madw_get_mad_ptr( p_madw );\r
+  ib_api_status_t status;\r
+  ib_mad_element_t *p_elem;\r
+  ib_av_attr_t av;\r
+\r
+  OSM_LOG_ENTER( p_vend->p_log, osm_vendor_send );\r
+\r
+  CL_ASSERT( p_vw->h_bind == h_bind );\r
+  CL_ASSERT( p_vw->p_elem );\r
+\r
+  p_elem = p_vw->p_elem;\r
+\r
+  /*\r
+    If a response is expected to this MAD, then preallocate\r
+    a mad wrapper to contain the wire MAD received in the\r
+    response.  Allocating a wrapper here allows for easier\r
+    failure paths than after we already received the wire mad.\r
+    In order to seperate the receive callback and the send callback\r
+    dependency , we copy the request madw and send it as context2\r
+    Which in time in the receive callback will replace the req_madw \r
+    to allow avoid races with send callback\r
+  */\r
+  if( resp_expected )\r
+  {\r
+    p_vw->p_resp_madw = osm_mad_pool_get_wrapper_raw(\r
+      p_bind->p_osm_pool );\r
+    if( p_vw->p_resp_madw == NULL  )\r
+    {\r
+      osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+               "osm_vendor_send: ERR 3B27: "\r
+               "Unable to allocate MAD wrapper.\n" );\r
+      status = IB_INSUFFICIENT_RESOURCES;\r
+      goto Exit;\r
+    }\r
+    \r
+  }\r
+  else\r
+    p_vw->p_resp_madw = NULL;\r
+\r
+  /*\r
+    For all sends other than directed route SM MADs,\r
+    acquire an address vector for the destination.\r
+  */\r
+  if( p_mad->mgmt_class != IB_MCLASS_SUBN_DIR )\r
+  {\r
+    cl_memclr( &av, sizeof(av) );\r
+    av.port_num = p_bind->port_num;\r
+    av.dlid = p_mad_addr->dest_lid;\r
+    av.static_rate = p_mad_addr->static_rate;\r
+    av.path_bits = p_mad_addr->path_bits;\r
+\r
+    if( (p_mad->mgmt_class != IB_MCLASS_SUBN_LID) &&\r
+        (p_mad->mgmt_class != IB_MCLASS_SUBN_DIR) )\r
+    {\r
+      av.sl = p_mad_addr->addr_type.gsi.service_level;\r
+\r
+\r
+      if(p_mad_addr->addr_type.gsi.global_route)\r
+      {\r
+        av.grh_valid = TRUE;\r
+        /* ANIL */\r
+        /* av.grh = p_mad_addr->addr_type.gsi.grh_info; */\r
+      }\r
+    }\r
+\r
+    if( osm_log_is_active( p_vend->p_log, OSM_LOG_DEBUG ) )\r
+    {\r
+      osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+               "osm_vendor_send: "\r
+               "av.port_num 0x%X, "\r
+               "av.dlid 0x%X, "\r
+               "av.static_rate   %d, "\r
+               "av.path_bits %d.\n",\r
+               av.port_num, cl_ntoh16(av.dlid),\r
+               av.static_rate, av.path_bits);\r
+    }\r
+\r
+    status = ib_create_av( p_vend->h_pd, &av, &(p_vw->h_av) );\r
+    if( status != IB_SUCCESS )\r
+    {\r
+      osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+               "osm_vendor_send: ERR 3B28: "\r
+               "Unable to create address vector (%s).\n",\r
+               ib_get_err_str( status ) );\r
+\r
+      if( p_vw->p_resp_madw )\r
+        osm_mad_pool_put( p_bind->p_osm_pool, p_vw->p_resp_madw );\r
+      /* Since we in immediate error the vendor layer is expected to handle the rollback , i.e free of madw */\r
+      if (p_madw) \r
+        osm_mad_pool_put( p_bind->p_osm_pool, p_madw );\r
+      goto Exit;\r
+    }\r
+\r
+    if( osm_log_is_active( p_vend->p_log, OSM_LOG_DEBUG ) )\r
+    {\r
+      osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+               "osm_vendor_send: "\r
+               "Allocating av handle %p.\n", p_vw->h_av );\r
+    }\r
+  }\r
+  else\r
+  {\r
+    p_vw->h_av = p_bind->h_dr_av;\r
+  }\r
+\r
+  p_elem->h_av = p_vw->h_av;\r
+\r
+  p_elem->context1 = p_madw;\r
+  p_elem->context2 = NULL;\r
+\r
+  p_elem->immediate_data = 0;\r
+  p_elem->p_grh = NULL;\r
+  p_elem->resp_expected = resp_expected;\r
+  p_elem->retry_cnt = OSM_DEFAULT_RETRY_COUNT;\r
+\r
+  p_elem->send_opt = IB_SEND_OPT_SIGNALED;\r
+  p_elem->timeout_ms = p_vend->timeout;\r
+\r
+  /* Completion information. */\r
+  p_elem->status = 0; /* Not trusting AL */\r
+\r
+\r
+  if( (p_mad->mgmt_class == IB_MCLASS_SUBN_LID) ||\r
+      (p_mad->mgmt_class == IB_MCLASS_SUBN_DIR) )\r
+  {\r
+    p_elem->remote_qp = 0;\r
+    p_elem->remote_qkey = 0;\r
+  }\r
+  else\r
+  {\r
+    p_elem->remote_qp = p_mad_addr->addr_type.gsi.remote_qp;\r
+    p_elem->remote_qkey = p_mad_addr->addr_type.gsi.remote_qkey;\r
+       osm_log(p_vend->p_log, OSM_LOG_DEBUG,\r
+            "osm_vendor_send: "\r
+            "remote qp = 0x%X, remote qkey = 0x%X.\n",\r
+            cl_ntoh32(p_elem->remote_qp),\r
+            cl_ntoh32(p_elem->remote_qkey) );\r
+  }\r
+\r
+  status = ib_send_mad( p_bind->h_svc, p_elem, NULL );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+             "osm_vendor_send: ERR 3B29: "\r
+             "Send failed , cleaning up (%s).\n",\r
+             ib_get_err_str( status ) );\r
+    /* When we destroy the av - we should take the pointer from local allocation since\r
+        we do not "trust" IBAL to keep track in p_elem */\r
+\r
+    if (p_vw->h_av && (p_vw->h_av != p_bind->h_dr_av) )\r
+    {\r
+        osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+                   "__osm_al_send: "\r
+                   "Destroying av handle %p.\n", p_vw->h_av );\r
+        ib_destroy_av( p_vw->h_av );\r
+    }\r
+    if( p_vw->p_resp_madw )\r
+      osm_mad_pool_put( p_bind->p_osm_pool, p_vw->p_resp_madw );\r
+    /* Since we in immediate error the vendor layer is expected to handle the rollback , i.e free of madw */\r
+    if (p_madw) \r
+      osm_mad_pool_put( p_bind->p_osm_pool, p_madw );\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( p_vend->p_log );\r
+  return( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osm_vendor_local_lid_change(\r
+  IN osm_bind_handle_t h_bind )\r
+{\r
+  osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;\r
+  osm_vendor_t *p_vend = p_bind->p_vend;\r
+\r
+  OSM_LOG_ENTER( p_vend->p_log, osm_vendor_local_lid_change );\r
+\r
+  OSM_LOG_EXIT( p_vend->p_log );\r
+  return( IB_SUCCESS );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_vendor_set_sm(\r
+  IN osm_bind_handle_t h_bind,\r
+  IN boolean_t         is_sm_val )\r
+{\r
+  osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;\r
+  osm_vendor_t *p_vend = p_bind->p_vend;\r
+  ib_api_status_t status;\r
+  ib_port_attr_mod_t attr_mod;\r
+\r
+  OSM_LOG_ENTER( p_vend->p_log, osm_vendor_set_sm );\r
+\r
+  cl_memclr( &attr_mod, sizeof(attr_mod) );\r
+\r
+  attr_mod.cap.sm = is_sm_val;\r
+\r
+  status = ib_modify_ca( p_vend->h_ca, p_bind->port_num,\r
+                         IB_CA_MOD_IS_SM, &attr_mod );\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+             "osm_vendor_set_sm: ERR 3B34: "\r
+             "Unable set 'IS_SM' bit to:%u in port attributes (%s).\n",\r
+             is_sm_val, ib_get_err_str( status ) );\r
+  }\r
+\r
+  OSM_LOG_EXIT( p_vend->p_log );\r
+}\r
+\r
+#endif   /* OSM_VENDOR_INTF_AL */\r
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/osm_vendor_mlx_sa.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/osm_vendor_mlx_sa.c
new file mode 100644 (file)
index 0000000..6ba5888
--- /dev/null
@@ -0,0 +1,879 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_vendor_mlx_sa.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_timer.h>
+#include <vendor/osm_vendor_api.h>
+#include <vendor/osm_vendor_sa_api.h>
+
+
+/*****************************************************************************
+ *****************************************************************************/
+
+/* this struct is the internal rep of the bind handle */
+typedef struct _osmv_sa_bind_info {
+  osm_bind_handle_t  h_bind;
+  osm_log_t         *p_log;
+  osm_vendor_t      *p_vendor;
+  osm_mad_pool_t    *p_mad_pool;
+  uint64_t           port_guid;
+  cl_event_t         sync_event;
+  uint64_t           last_lids_update_sec;
+  uint16_t           lid;
+  uint16_t           sm_lid;
+} osmv_sa_bind_info_t;
+
+/*****************************************************************************
+ *****************************************************************************/
+
+/*
+  Call back on new mad received:
+
+  We basically only need to set the context of the query.
+  Or report an error.
+
+  A pointer to the actual context of the request (a copy of the oriignal
+  request structure) is attached as the p_madw->context.ni_context.node_guid
+*/
+void
+__osmv_sa_mad_rcv_cb(
+  IN osm_madw_t *p_madw,
+  IN void* bind_context,
+  IN osm_madw_t *p_req_madw)
+{
+  osmv_sa_bind_info_t   *p_bind = (osmv_sa_bind_info_t *)bind_context;
+  osmv_query_req_t      *p_query_req_copy = NULL;
+  osmv_query_res_t       query_res;
+  ib_sa_mad_t           *p_sa_mad;
+  ib_net16_t             mad_status;
+
+  OSM_LOG_ENTER( p_bind->p_log, __osmv_sa_mad_rcv_cb );
+
+  if (! p_req_madw)
+  {
+    osm_log( p_bind->p_log, OSM_LOG_DEBUG,
+             "__osmv_sa_mad_rcv_cb: "
+             "Ignoring a non-response mad\n");
+    osm_mad_pool_put(p_bind->p_mad_pool, p_madw);
+    goto Exit;
+  }
+
+  /* obtain the sent context */
+  p_query_req_copy =
+       (osmv_query_req_t *)(p_req_madw->context.arb_context.context1);
+
+  /* provide the context of the original request in the result */
+  query_res.query_context = p_query_req_copy->query_context;
+
+  /* provide the resulting madw */
+  query_res.p_result_madw = p_madw;
+
+  /* update the req fields */
+  p_sa_mad = ( ib_sa_mad_t * ) p_madw->p_mad;
+
+  /* if we got a remote error track it in the status */
+  mad_status = ( ib_net16_t ) ( p_sa_mad->status & IB_SMP_STATUS_MASK );
+  if (mad_status != IB_SUCCESS)
+  {
+    osm_log( p_bind->p_log, OSM_LOG_ERROR,
+             "__osmv_sa_mad_rcv_cb: ERR 0501: "
+             "Remote error:0x%04X .\n",  mad_status
+             );
+    query_res.status = IB_REMOTE_ERROR;
+  }
+  else
+  {
+    query_res.status = IB_SUCCESS;
+  }
+
+  /* what if we have got back an empty mad ? */
+  if (! p_madw->mad_size)
+  {
+    osm_log( p_bind->p_log, OSM_LOG_ERROR,
+             "__osmv_sa_mad_rcv_cb: ERR 0502: "
+             "Got an empty mad.\n"
+             );
+    query_res.status = IB_ERROR;
+  }
+
+  if (IB_SUCCESS == mad_status)
+  {
+
+    /* if we are in not in a method response of an rmpp nature we must get only 1 */
+    /* HACK: in the future we might need to be smarter for other methods... */
+    if (p_sa_mad->method != IB_MAD_METHOD_GETTABLE_RESP)
+    {
+      query_res.result_cnt = 1;
+    }
+    else
+    {
+#ifndef VENDOR_RMPP_SUPPORT
+      if (mad_status != IB_SUCCESS)
+        query_res.result_cnt = 0;
+      else
+        query_res.result_cnt = 1;
+#else
+      /* we used the offset value to calculate the number of
+         records in here */
+      query_res.result_cnt =
+        (uintn_t)
+        ( ( p_madw->mad_size - IB_SA_MAD_HDR_SIZE ) /
+          ib_get_attr_size( p_sa_mad->attr_offset ) );
+      osm_log( p_bind->p_log, OSM_LOG_DEBUG,
+               "__osmv_sa_mad_rcv_cb: Count = %u = %u / %u (%u)\n",
+               query_res.result_cnt, p_madw->mad_size - IB_SA_MAD_HDR_SIZE,
+               ib_get_attr_size( p_sa_mad->attr_offset ),
+               ( p_madw->mad_size - IB_SA_MAD_HDR_SIZE ) %
+               ib_get_attr_size( p_sa_mad->attr_offset )
+               );
+#endif
+    }
+  }
+
+  query_res.query_type = p_query_req_copy->query_type;
+
+  p_query_req_copy->pfn_query_cb( &query_res );
+
+  if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC)
+    cl_event_signal( &p_bind->sync_event );
+
+ Exit:
+
+  /* free the copied query request if found */
+  if (p_query_req_copy) free(p_query_req_copy);
+
+  /* put back the request madw */
+  if (p_req_madw)
+    osm_mad_pool_put(p_bind->p_mad_pool, p_req_madw);
+
+  OSM_LOG_EXIT( p_bind->p_log );
+}
+
+/*****************************************************************************
+ ****************************************************************************/
+/*
+  Send Error Callback:
+
+  Only report the error and get rid of the mad wrapper
+*/
+void
+__osmv_sa_mad_err_cb(
+  IN void* bind_context,
+  IN osm_madw_t *p_madw)
+{
+  osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *)bind_context;
+  osmv_query_req_t   *p_query_req_copy = NULL;
+  osmv_query_res_t    query_res;
+
+  OSM_LOG_ENTER( p_bind->p_log, __osmv_sa_mad_err_cb );
+
+  /* Obtain the sent context etc */
+  p_query_req_copy =
+       (osmv_query_req_t *)(p_madw->context.arb_context.context1);
+
+  /* provide the context of the original request in the result */
+  query_res.query_context = p_query_req_copy->query_context;
+
+  query_res.p_result_madw = p_madw;
+
+  query_res.status = IB_TIMEOUT;
+  query_res.result_cnt = 0;
+  query_res.p_result_madw->status = IB_TIMEOUT;
+  p_madw->status = IB_TIMEOUT;
+  query_res.query_type = p_query_req_copy->query_type;
+
+  p_query_req_copy->pfn_query_cb( &query_res );
+
+  if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC)
+    cl_event_signal( &p_bind->sync_event );
+
+  if (p_query_req_copy) free(p_query_req_copy);
+  OSM_LOG_EXIT( p_bind->p_log );
+}
+
+/*****************************************************************************
+ This routine needs to be invoked on every send - since the SM LID and Local 
+ lid might change. To do that without any major perfoermance impact we cache 
+ the results and time they were obtained. Refresh only twice a minute. 
+ To avoid the need to use statics and risk a race - we require the refresh time
+ to be stored in the context of the results. Also this coveres cases were 
+ we query for multiple guids.
+ *****************************************************************************/
+ib_api_status_t
+__osmv_get_lid_and_sm_lid_by_port_guid(
+  IN osm_vendor_t*   const p_vend,
+  IN ib_net64_t            port_guid,
+  IN OUT uint64_t*         p_lids_update_time_sec,
+  OUT uint16_t*            lid,
+  OUT uint16_t*            sm_lid)
+{
+
+  ib_api_status_t    status;
+  ib_port_attr_t    *p_attr_array;
+  uint32_t           num_ports;
+  uint32_t           port_num;
+
+  OSM_LOG_ENTER( p_vend->p_log, __osmv_get_lid_and_sm_lid_by_port_guid );
+
+  /* use prevous values if current time is close enough to previous query */
+  if (cl_get_time_stamp_sec() <= *p_lids_update_time_sec + 30)
+  {
+    osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+             "__osmv_get_lid_and_sm_lid_by_port_guid: "
+             "Using previously stored lid:0x%04x sm_lid:0x%04x\n",
+             *lid, *sm_lid
+             );
+    status = IB_SUCCESS;
+    goto Exit;
+  }
+
+  /* obtain the number of available ports */
+  num_ports = 0;
+  status = osm_vendor_get_all_port_attr(p_vend, NULL, &num_ports);
+  if (status != IB_INSUFFICIENT_MEMORY)
+  {
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,
+             "__osmv_get_lid_and_sm_lid_by_port_guid: ERR 0503: "
+             "expected to get the IB_INSUFFICIENT_MEMORY but got: %s\n",
+             ib_get_err_str(status)
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+           "__osmv_get_lid_and_sm_lid_by_port_guid: "
+           "Found total of %u ports. Looking for guid:0x%016" PRIx64 "\n",
+           num_ports, cl_ntoh64(port_guid)
+           );
+
+  /* allocate the attributes */
+  p_attr_array =
+    (ib_port_attr_t *)malloc(sizeof(ib_port_attr_t)*num_ports);
+
+  /* obtain the attributes */
+  status = osm_vendor_get_all_port_attr(p_vend, p_attr_array, &num_ports);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,
+             "__osmv_get_lid_and_sm_lid_by_port_guid: ERR 0504: "
+             "Fail to get port attributes (error: %s)\n",
+             ib_get_err_str(status)
+             );
+    free(p_attr_array);
+    goto Exit;
+  }
+
+  status = IB_ERROR;
+  /* find the port requested in the list */
+  for (port_num = 0; (port_num<num_ports) && (status == IB_ERROR); port_num++)
+  {
+    if (p_attr_array[port_num].port_guid == port_guid)
+    {
+      *lid = p_attr_array[port_num].lid;
+      *sm_lid = p_attr_array[port_num].sm_lid;
+      *p_lids_update_time_sec = cl_get_time_stamp_sec();
+      status = IB_SUCCESS;
+      osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+               "__osmv_get_lid_and_sm_lid_by_port_guid: "
+               "Found guid:0x%016" PRIx64 " with idx:%d\n",
+               cl_ntoh64(port_guid), port_num);
+    }
+  }
+
+  free(p_attr_array);
+
+ Exit:
+  OSM_LOG_EXIT( p_vend->p_log );
+  return ( status );
+}
+
+/*****************************************************************************
+ *****************************************************************************/
+osm_bind_handle_t
+osmv_bind_sa(
+  IN osm_vendor_t*   const p_vend,
+  IN osm_mad_pool_t* const p_mad_pool,
+  IN ib_net64_t            port_guid
+  )
+{
+  osm_bind_info_t bind_info;
+  osm_log_t *p_log = p_vend->p_log;
+  ib_api_status_t status = IB_SUCCESS;
+  osmv_sa_bind_info_t *p_sa_bind_info;
+  cl_status_t cl_status;
+
+  OSM_LOG_ENTER( p_log, osmv_bind_sa );
+
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "osmv_bind_sa: "
+           "Binding to port 0x%" PRIx64 ".\n",
+           cl_ntoh64( port_guid ) );
+
+  bind_info.port_guid = port_guid;
+  bind_info.mad_class = IB_MCLASS_SUBN_ADM;
+  bind_info.class_version = 2;
+  bind_info.is_responder = TRUE;
+  bind_info.is_trap_processor = FALSE;
+  bind_info.is_report_processor = TRUE;
+  bind_info.send_q_size = 256;
+  bind_info.recv_q_size = 256;
+
+  /* allocate the new sa bind info */
+  p_sa_bind_info =
+    (osmv_sa_bind_info_t *)malloc(sizeof(osmv_sa_bind_info_t));
+  if (! p_sa_bind_info)
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osmv_bind_sa: ERR 0505: "
+             "Fail to allocate new bidn structure\n" );
+    p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
+    goto Exit;
+  }
+
+  /* store some important context */
+  p_sa_bind_info->p_log = p_log;
+  p_sa_bind_info->port_guid = port_guid;
+  p_sa_bind_info->p_mad_pool = p_mad_pool;
+  p_sa_bind_info->p_vendor = p_vend;
+  p_sa_bind_info->last_lids_update_sec = 0;
+
+  /* Bind to the lower level */
+  p_sa_bind_info->h_bind =
+    osm_vendor_bind( p_vend,
+                     &bind_info,
+                     p_mad_pool,
+                     __osmv_sa_mad_rcv_cb,
+                     __osmv_sa_mad_err_cb,
+                     p_sa_bind_info); /* context provided to CBs */
+
+  if (p_sa_bind_info->h_bind == OSM_BIND_INVALID_HANDLE)
+  {
+    free(p_sa_bind_info);
+    p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osmv_bind_sa: ERR 0506: "
+             "Fail to bind to vendor SMI.\n" );
+    goto Exit;
+  }
+
+  /* obtain the sm_lid from the vendor */
+  status =
+    __osmv_get_lid_and_sm_lid_by_port_guid(
+      p_vend, port_guid,
+      &p_sa_bind_info->last_lids_update_sec,
+      &p_sa_bind_info->lid,
+      &p_sa_bind_info->sm_lid);
+  if (status != IB_SUCCESS)
+  {
+    free(p_sa_bind_info);
+    p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osmv_bind_sa: ERR 0507: "
+             "Fail to obtain the sm lid.\n" );
+    goto Exit;
+  }
+
+  /* initialize the sync_event */
+  cl_event_construct( &p_sa_bind_info->sync_event );
+  cl_status = cl_event_init( &p_sa_bind_info->sync_event, TRUE );
+  if( cl_status != CL_SUCCESS )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osmv_bind_sa: ERR 0508: "
+             "cl_init_event failed: %s\n",
+             ib_get_err_str(cl_status)
+             );
+    free(p_sa_bind_info);
+    p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return ( p_sa_bind_info );
+}
+
+/*****************************************************************************
+ *****************************************************************************/
+
+/****t* OSM Vendor SA Client/osmv_sa_mad_data
+ * NAME
+ *    osmv_sa_mad_data
+ *
+ * DESCRIPTION
+ * Extra fields required to perform a mad query
+ *  This struct is passed to the actual send method
+ *
+ * SYNOPSIS
+ */
+typedef struct _osmv_sa_mad_data
+{
+  /* MAD data. */
+  uint8_t method;
+  ib_net16_t attr_id;
+  ib_net16_t attr_offset;
+  ib_net32_t attr_mod;
+  ib_net64_t comp_mask;
+  void *p_attr;
+} osmv_sa_mad_data_t;
+/*
+ * method
+ *    The method of the mad to be sent
+ *
+ *  attr_id
+ *     Attribute ID
+ *
+ *  attr_offset
+ *     Offset as defined by RMPP
+ *
+ *  attr_mod
+ *     Attribute modifier
+ *
+ *  comp_mask
+ *     The component mask of the query
+ *
+ *  p_attr
+ *     A pointer to the record of the attribute to be sent.
+ *
+ *****/
+
+/*****************************************************************************
+ *****************************************************************************/
+/* Send a MAD out on the GSI interface */
+ib_api_status_t
+__osmv_send_sa_req(
+  IN osmv_sa_bind_info_t*             p_bind,
+  IN const osmv_sa_mad_data_t * const p_sa_mad_data,
+  IN const osmv_query_req_t     * const p_query_req )
+{
+  ib_api_status_t   status;
+  ib_mad_t         *p_mad_hdr;
+  ib_sa_mad_t      *p_sa_mad;
+  osm_madw_t       *p_madw;
+  osm_log_t        *p_log = p_bind->p_log;
+  static atomic32_t trans_id;
+  boolean_t         sync;
+  osmv_query_req_t   *p_query_req_copy;
+
+  OSM_LOG_ENTER( p_log, __osmv_send_sa_req );
+
+  /*
+    since the sm_lid might change we obtain it every send
+    (actually it is cached in the bind object and refreshed 
+    every 30sec by this proc )
+  */
+  status =
+    __osmv_get_lid_and_sm_lid_by_port_guid(
+      p_bind->p_vendor, p_bind->port_guid,
+      &p_bind->last_lids_update_sec,
+      &p_bind->lid,
+      &p_bind->sm_lid);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "__osmv_send_sa_req: ERR 0509: "
+             "Fail to obtain the sm lid.\n" );
+    goto Exit;
+  }
+
+  /* Get a MAD wrapper for the send */
+  p_madw = osm_mad_pool_get(
+    p_bind->p_mad_pool,
+    p_bind->h_bind,
+    MAD_BLOCK_SIZE,
+    NULL );
+
+  if( p_madw == NULL )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "__osmv_send_sa_req: ERR 0510: " 
+             "Unable to acquire MAD.\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+  /* Initialize the Sent MAD: */
+
+  /* Initialize the MAD buffer for the send operation. */
+  p_mad_hdr = osm_madw_get_mad_ptr( p_madw );
+  p_sa_mad =  osm_madw_get_sa_mad_ptr( p_madw );
+
+  /* Get a new transaction Id */
+  cl_atomic_inc( &trans_id );
+
+  /* Cleanup the MAD from any residue */
+  memset(p_sa_mad, 0, MAD_BLOCK_SIZE);
+
+  /* Initialize the standard MAD header. */
+  ib_mad_init_new(
+    p_mad_hdr,                         /* mad pointer */
+    IB_MCLASS_SUBN_ADM,                /* class */
+    ( uint8_t ) 2,                     /* version */
+    p_sa_mad_data->method,             /* method */
+    cl_hton64( ( uint64_t ) trans_id ),/* tid */
+    p_sa_mad_data->attr_id,            /* attr id */
+    p_sa_mad_data->attr_mod            /* attr mod */
+    );
+
+  /* Set the query information. */
+  p_sa_mad->sm_key = p_query_req->sm_key;
+  p_sa_mad->attr_offset = 0;
+  p_sa_mad->comp_mask = p_sa_mad_data->comp_mask;
+  if( p_sa_mad->comp_mask )
+  {
+    memcpy( p_sa_mad->data, p_sa_mad_data->p_attr,
+            ib_get_attr_size(p_sa_mad_data->attr_offset));
+  }
+
+  /*
+    Provide the address to send to
+  */
+  /* Patch to handle IBAL - host order , where it should take destination lid in network order */
+#ifdef OSM_VENDOR_INTF_AL
+  p_madw->mad_addr.dest_lid = p_bind->sm_lid;
+#else
+  p_madw->mad_addr.dest_lid = cl_hton16(p_bind->sm_lid);
+#endif
+  p_madw->mad_addr.addr_type.smi.source_lid =
+    cl_hton16(p_bind->lid);
+  p_madw->mad_addr.addr_type.gsi.remote_qp = CL_HTON32(1);
+  p_madw->mad_addr.addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
+  p_madw->mad_addr.addr_type.gsi.pkey = IB_DEFAULT_PKEY;
+  p_madw->resp_expected = TRUE;
+  p_madw->fail_msg = CL_DISP_MSGID_NONE;
+
+  /*
+    Provide MAD context such that the call back will know what to do.
+    We have to keep the entire request structure so we know the CB.
+    Since we can not rely on the client to keep it arroud until
+    the response - we duplicate it and will later dispose it (in CB).
+    To store on the MADW we cast it into what opensm has:
+    p_madw->context.arb_context.context1
+  */
+  p_query_req_copy = malloc(sizeof(*p_query_req_copy));
+  *p_query_req_copy = *p_query_req;
+  p_madw->context.arb_context.context1 = p_query_req_copy;
+
+  /* we can support async as well as sync calls */
+  sync = ((p_query_req->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC);
+
+  /* send the mad asynchronously */
+  status = osm_vendor_send(
+    osm_madw_get_bind_handle( p_madw ),
+    p_madw,
+    p_madw->resp_expected );
+
+  /* if synchronous - wait on the event */
+  if (sync)
+  {
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "__osmv_send_sa_req: "
+             "Waiting for async event.\n" );
+    cl_event_wait_on( &p_bind->sync_event, EVENT_NO_TIMEOUT, FALSE );
+    cl_event_reset(&p_bind->sync_event);
+    status = p_madw->status;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return status;
+}
+
+/*****************************************************************************
+ *****************************************************************************/
+/*
+ * Query the SA based on the user's request.
+ */
+ib_api_status_t
+osmv_query_sa(
+  IN osm_bind_handle_t         h_bind,
+  IN const osmv_query_req_t * const p_query_req
+  )
+{
+  osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *)h_bind;
+  osmv_sa_mad_data_t sa_mad_data;
+  osmv_user_query_t *p_user_query;
+  ib_service_record_t svc_rec;
+  ib_node_record_t node_rec;
+  ib_portinfo_record_t port_info;
+  ib_path_rec_t path_rec;
+  ib_class_port_info_t class_port_info;
+  osm_log_t *p_log = p_bind->p_log;
+  ib_api_status_t status;
+
+  OSM_LOG_ENTER( p_log, osmv_query_sa );
+
+  /* Set the request information. */
+  sa_mad_data.method = IB_MAD_METHOD_GETTABLE;
+  sa_mad_data.attr_mod = 0;
+
+  /* Set the MAD attributes and component mask correctly. */
+  switch ( p_query_req->query_type )
+  {
+
+  case OSMV_QUERY_USER_DEFINED:
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osmv_query_sa DBG:001 %s", "USER_DEFINED\n" );
+    p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input;
+    if (p_user_query->method) sa_mad_data.method = p_user_query->method;
+    sa_mad_data.attr_offset = p_user_query->attr_offset;
+    sa_mad_data.attr_id = p_user_query->attr_id;
+    sa_mad_data.attr_mod = p_user_query->attr_mod;
+    sa_mad_data.comp_mask = p_user_query->comp_mask;
+    sa_mad_data.p_attr = p_user_query->p_attr;
+#if (0)
+#ifdef OSM_VENDOR_INTF_AL
+    /* HACK for OFED OSM: convert lid order from network to
+       host for IB_MAD_ATTR_PORTINFO_RECORD */
+    if ( (sa_mad_data.attr_id == IB_MAD_ATTR_PORTINFO_RECORD) &&
+         (sa_mad_data.comp_mask & IB_PIR_COMPMASK_LID))
+    {
+       ib_portinfo_record_t * p_pir = (ib_portinfo_record_t *)sa_mad_data.p_attr;
+       p_pir->lid = cl_ntoh16(p_pir->lid);
+    }
+#endif
+#endif
+   break;
+
+  case OSMV_QUERY_ALL_SVC_RECS:
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osmv_query_sa DBG:001 %s", "SVC_REC_BY_NAME\n" );
+    sa_mad_data.method = IB_MAD_METHOD_GETTABLE;
+    sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+    sa_mad_data.attr_offset =
+      ib_get_attr_offset( sizeof( ib_service_record_t ) );
+    sa_mad_data.comp_mask = 0;
+    sa_mad_data.p_attr = &svc_rec;
+    break;
+
+  case OSMV_QUERY_SVC_REC_BY_NAME:
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osmv_query_sa DBG:001 %s", "SVC_REC_BY_NAME\n" );
+    sa_mad_data.method = IB_MAD_METHOD_GET;
+    sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+    sa_mad_data.comp_mask = IB_SR_COMPMASK_SNAME;
+    sa_mad_data.attr_offset =
+      ib_get_attr_offset( sizeof( ib_service_record_t ) );
+    sa_mad_data.p_attr = &svc_rec;
+    memcpy( svc_rec.service_name, p_query_req->p_query_input,
+            sizeof( ib_svc_name_t ) );
+    break;
+
+  case OSMV_QUERY_SVC_REC_BY_ID:
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osmv_query_sa DBG:001 %s", "SVC_REC_BY_ID\n" );
+    sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+    sa_mad_data.comp_mask = IB_SR_COMPMASK_SID;
+    sa_mad_data.attr_offset =
+      ib_get_attr_offset( sizeof( ib_service_record_t ) );
+    sa_mad_data.p_attr = &svc_rec;
+    svc_rec.service_id = *( ib_net64_t * ) ( p_query_req->p_query_input );
+    break;
+
+  case OSMV_QUERY_CLASS_PORT_INFO:
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osmv_query_sa DBG:001 %s","CLASS_PORT_INFO\n" );
+    sa_mad_data.method = IB_MAD_METHOD_GET;
+    sa_mad_data.attr_id = IB_MAD_ATTR_CLASS_PORT_INFO;
+    sa_mad_data.attr_offset =
+      ib_get_attr_offset( sizeof( ib_class_port_info_t ) );
+    sa_mad_data.comp_mask = 0;
+    sa_mad_data.p_attr = &class_port_info;
+
+    break;
+
+  case OSMV_QUERY_NODE_REC_BY_NODE_GUID:
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osmv_query_sa DBG:001 %s","NODE_REC_BY_NODE_GUID\n" );
+    sa_mad_data.method = IB_MAD_METHOD_GETTABLE;
+    sa_mad_data.attr_id = IB_MAD_ATTR_NODE_RECORD;
+    sa_mad_data.attr_offset =
+      ib_get_attr_offset( sizeof( ib_node_record_t ) );
+    sa_mad_data.comp_mask = IB_NR_COMPMASK_NODEGUID;
+    sa_mad_data.p_attr = &node_rec;
+    node_rec.node_info.node_guid =
+      *( ib_net64_t * ) ( p_query_req->p_query_input );
+
+    break;
+
+  case OSMV_QUERY_PORT_REC_BY_LID:
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osmv_query_sa DBG:001 %s","PORT_REC_BY_LID\n" );
+    sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;
+    sa_mad_data.attr_offset =
+      ib_get_attr_offset( sizeof( ib_portinfo_record_t ) );
+    sa_mad_data.comp_mask = IB_PIR_COMPMASK_LID;
+    sa_mad_data.p_attr = &port_info;
+    port_info.lid = *( ib_net16_t * ) ( p_query_req->p_query_input );
+    break;
+
+  case OSMV_QUERY_PORT_REC_BY_LID_AND_NUM:
+    sa_mad_data.method = IB_MAD_METHOD_GET;
+    p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input;
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osmv_query_sa DBG:001 %s","PORT_REC_BY_LID_AND_NUM\n" );
+    sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;
+    sa_mad_data.attr_offset =
+      ib_get_attr_offset( sizeof( ib_portinfo_record_t ) );
+    sa_mad_data.comp_mask = IB_PIR_COMPMASK_LID | IB_PIR_COMPMASK_PORTNUM;
+    sa_mad_data.p_attr = p_user_query->p_attr;
+    break;
+
+  case OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK:
+    sa_mad_data.method = IB_MAD_METHOD_GET;
+    p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input;
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osmv_query_sa DBG:001 %s","OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n" );
+    sa_mad_data.attr_id = IB_MAD_ATTR_VLARB_RECORD;
+    sa_mad_data.attr_offset =
+      ib_get_attr_offset( sizeof( ib_vl_arb_table_record_t ) );
+    sa_mad_data.comp_mask = IB_VLA_COMPMASK_LID | IB_VLA_COMPMASK_OUT_PORT | IB_VLA_COMPMASK_BLOCK;
+    sa_mad_data.p_attr = p_user_query->p_attr;
+    break;
+
+  case OSMV_QUERY_SLVL_BY_LID_AND_PORTS:
+    sa_mad_data.method = IB_MAD_METHOD_GET;
+    p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input;
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osmv_query_sa DBG:001 %s","OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n" );
+    sa_mad_data.attr_id = IB_MAD_ATTR_SLVL_RECORD;
+    sa_mad_data.attr_offset =
+      ib_get_attr_offset( sizeof( ib_slvl_table_record_t ) );
+    sa_mad_data.comp_mask = IB_SLVL_COMPMASK_LID | IB_SLVL_COMPMASK_OUT_PORT | IB_SLVL_COMPMASK_IN_PORT;
+    sa_mad_data.p_attr = p_user_query->p_attr;
+    break;
+
+  case OSMV_QUERY_PATH_REC_BY_PORT_GUIDS:
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osmv_query_sa DBG:001 %s","PATH_REC_BY_PORT_GUIDS\n" );
+    memset(&path_rec, 0, sizeof(ib_path_rec_t ));
+    sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
+    sa_mad_data.attr_offset =
+      ib_get_attr_offset( sizeof( ib_path_rec_t ) );
+    sa_mad_data.comp_mask = ( IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID );
+    sa_mad_data.p_attr = &path_rec;
+    ib_gid_set_default( &path_rec.dgid,
+                        ( ( osmv_guid_pair_t * ) ( p_query_req->
+                                                   p_query_input ) )->
+                        dest_guid );
+    ib_gid_set_default( &path_rec.sgid,
+                        ( ( osmv_guid_pair_t * ) ( p_query_req->
+                                                   p_query_input ) )->
+                        src_guid );
+    break;
+
+  case OSMV_QUERY_PATH_REC_BY_GIDS:
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osmv_query_sa DBG:001 %s","PATH_REC_BY_GIDS\n" );
+    memset(&path_rec, 0, sizeof(ib_path_rec_t ));
+    sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
+    sa_mad_data.attr_offset =
+      ib_get_attr_offset( sizeof( ib_path_rec_t ) );
+    sa_mad_data.comp_mask = ( IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID );
+    sa_mad_data.p_attr = &path_rec;
+    memcpy( &path_rec.dgid,
+            &( ( osmv_gid_pair_t * ) ( p_query_req->p_query_input ) )->
+            dest_gid, sizeof( ib_gid_t ) );
+    memcpy( &path_rec.sgid,
+            &( ( osmv_gid_pair_t * ) ( p_query_req->p_query_input ) )->
+            src_gid, sizeof( ib_gid_t ) );
+    break;
+
+  case OSMV_QUERY_PATH_REC_BY_LIDS:
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osmv_query_sa DBG:001 %s","PATH_REC_BY_LIDS\n" );
+    memset(&path_rec, 0, sizeof(ib_path_rec_t ));
+    sa_mad_data.method = IB_MAD_METHOD_GET;
+    sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
+    sa_mad_data.attr_offset =
+      ib_get_attr_offset( sizeof( ib_path_rec_t ) );
+    sa_mad_data.comp_mask = ( IB_PR_COMPMASK_DLID | IB_PR_COMPMASK_SLID );
+    sa_mad_data.p_attr = &path_rec;
+    path_rec.dlid =
+      ( ( osmv_lid_pair_t * ) ( p_query_req->p_query_input ) )->dest_lid;
+    path_rec.slid =
+      ( ( osmv_lid_pair_t * ) ( p_query_req->p_query_input ) )->src_lid;
+    break;
+
+  case OSMV_QUERY_UD_MULTICAST_SET:
+    sa_mad_data.method = IB_MAD_METHOD_SET;
+    p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input;
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osmv_query_sa DBG:001 %s","OSMV_QUERY_UD_MULTICAST_SET\n" );
+    sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
+    sa_mad_data.attr_offset =
+      ib_get_attr_offset( sizeof( ib_member_rec_t ) );
+    sa_mad_data.comp_mask = p_user_query->comp_mask;
+    sa_mad_data.p_attr = p_user_query->p_attr;
+    break;
+
+  case OSMV_QUERY_UD_MULTICAST_DELETE:
+    sa_mad_data.method = IB_MAD_METHOD_DELETE;
+    p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input;
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osmv_query_sa DBG:001 %s","OSMV_QUERY_UD_MULTICAST_DELETE\n" );
+    sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
+    sa_mad_data.attr_offset =
+      ib_get_attr_offset( sizeof( ib_member_rec_t ) );
+    sa_mad_data.comp_mask = p_user_query->comp_mask;
+    sa_mad_data.p_attr = p_user_query->p_attr;
+    break;
+
+  default:
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osmv_query_sa DBG:001 %s","UNKNOWN\n" );
+    CL_ASSERT( 0 );
+    return IB_ERROR;
+  }
+
+  status = __osmv_send_sa_req( h_bind, &sa_mad_data, p_query_req );
+
+  OSM_LOG_EXIT( p_log );
+  return status;
+}
+
+
+/*****************************************************************************
+ *****************************************************************************/
+
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/winosm_common.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/libvendor/winosm_common.c
new file mode 100644 (file)
index 0000000..361d2c0
--- /dev/null
@@ -0,0 +1,249 @@
+#include <vendor/winosm_common.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <complib/cl_memory.h>
+
+int optind=1;
+int opterr=1;
+int optopt='?';
+int iArg=1;
+
+char*
+GetOsmTempPath(void)
+{
+       char* temp_path;
+       int length;
+       temp_path = (char*)cl_malloc(OSM_MAX_LOG_NAME_SIZE);
+       length = GetTempPath(OSM_MAX_LOG_NAME_SIZE,temp_path);
+       if (length > OSM_MAX_LOG_NAME_SIZE)
+       {
+               cl_free(temp_path);
+               temp_path = (char*)cl_malloc(length+1);
+               GetTempPath(length+1,temp_path);
+       }
+       return  temp_path;
+}
+
+char*
+GetOsmCachePath(void)
+{
+       char* cache_path;
+   char* tmp_file_name;
+   char* winib_home, tmp;
+   HANDLE hFile;
+
+   winib_home = (char*)cl_malloc(OSM_MAX_LOG_NAME_SIZE);
+   winib_home = getenv("WinIB_HOME");
+   if (winib_home == NULL)
+   {
+     /* The WinIB_HOME variable isn't defined. Use the 
+        default temp path */
+     return GetOsmTempPath();
+   }
+       cache_path = (char*)cl_malloc(OSM_MAX_LOG_NAME_SIZE);
+   strcpy(cache_path, winib_home);
+
+   strcat(cache_path, "\\etc\\");
+       tmp_file_name = (char*)cl_malloc(OSM_MAX_LOG_NAME_SIZE);
+   strcpy(tmp_file_name, cache_path);
+   strcat(tmp_file_name, "opensm.opts");
+   hFile = CreateFile(tmp_file_name,
+                      GENERIC_READ,
+                      0,
+                      NULL,
+                      OPEN_EXISTING,
+                      FILE_ATTRIBUTE_NORMAL,
+                      NULL);
+   if (hFile == INVALID_HANDLE_VALUE) 
+   { 
+     cl_free(cache_path);
+     return GetOsmTempPath();
+   }
+   /* Such file exists. This means the directory is usable */
+   CloseHandle(hFile);
+
+       return cache_path;
+}
+
+/****************************************************************************/
+int getopt_long_only(int argc, char *const*argv,
+       const char *optstring,
+       const struct option *longopts, int *longindex)
+{
+  char chOpt;
+  char tmp_str[256];
+  char* tmp_arg = NULL;
+  char* tok=NULL;
+  int i;
+  char tokens[2] = {'='};
+
+  if (iArg == argc)
+  {
+      
+      return (EOF);
+  }
+
+  if (argv[iArg][0] != '-')
+  {
+      /* Does not start with a - - we are done scanning */
+      
+      return (EOF);
+  }
+  
+  /*termination of scanning */
+    if (!strcmp("--",argv[iArg])) {
+    return EOF;
+    
+    }
+    
+  
+  /* char option : -d 5 */
+  if ((argv[iArg][0] == '-') &&(argv[iArg][1] != '-') ) {
+      optarg = get_char_option(optstring,argv,argc,iArg,&optind,&chOpt);
+      iArg = optind;
+      
+      return chOpt;
+  }
+      
+  /* Look for this string in longopts */
+    strcpy(tmp_str,&(argv[iArg][2]));
+    
+    /*get the option */
+    tok = strtok(tmp_str,tokens);
+    
+    for (i = 0; longopts[i].name; i++)
+       {
+        if (strcmp (tok, longopts[i].name) == 0)
+               {
+            /* We have a match */             
+             if (longindex != NULL )
+                *longindex = i;
+              
+                if (longopts[i].flag != NULL) {
+                 *(longopts[i].flag) = longopts[i].val;
+                }
+              
+                
+                
+                if (longopts[i].has_arg != no_argument) 
+                  {
+                    /*get the argument */
+                    
+                    if (strchr(argv[iArg],'=') != NULL)
+                    {
+                        optarg = strtok(NULL,tokens);
+                    }else { /*the next arg in cmd line is the param */ 
+                        tmp_arg = argv[iArg+1];
+                        if (*tmp_arg == '-') {
+                        
+                            /*no param is found */
+                            chOpt = '?';
+                            if ((longopts[i].has_arg == required_argument) && opterr)
+                           {
+                             fprintf (stderr, "Option %s requires argument\n",tok);       
+                           }
+
+                        }else 
+                        {
+                            optarg = tmp_arg;
+                            iArg++;
+                            optind++;
+                        }
+                    }
+                                     
+                 }/*longopts */
+                                
+                iArg++;
+                optind++;
+                if (longopts[i].flag == 0)
+                    return (longopts[i].val);
+                else return 0; 
+              
+            }/*end if strcmp */
+           }
+
+  return ('?');
+}
+/******************************************************************************/
+static char* get_char_option(const char* optstring,char*const* argv,int argc, 
+                             int iArg, int* opt_ind,char* opt_p)   
+ {
+     char chOpt;
+     char* tmp_str;
+     char* prm = NULL;
+
+    chOpt = argv[iArg][1];
+    
+    
+    /*non valid argument*/
+    if (!isalpha(chOpt))
+    {
+        chOpt = EOF; 
+        goto end;
+    }
+     
+    tmp_str = strchr(optstring, chOpt);
+    
+    /*the argument wasn't found in optstring */
+    if (tmp_str == NULL){
+        chOpt = EOF; 
+        optopt = chOpt; 
+        goto end;
+    }
+        
+    /* don't need argument */
+    if (tmp_str[1]!= ':' ) {
+        goto end; 
+    }
+
+     if (argv[iArg][2] != '\0')
+     {
+       // param is attached to option: -po8889
+        prm = &(argv[iArg][2]);
+        goto end;
+      }
+         
+      // must look at next argv for param
+     /*at the end of arg list */ 
+     if ((iArg)+1 == argc) {
+      /* no param will be found */
+        if (tmp_str[2]== ':' ) {
+            /* optional argument ::*/
+            goto end; 
+        }
+        else
+        {   
+            chOpt = EOF; 
+            goto end;
+        }
+      }
+
+      prm = &(argv[(iArg)+1][0]);
+      if (*prm == '-' )
+      {   
+          // next argv is a new option, so param
+         // not given for current option
+          if (tmp_str[2]== ':' ) {
+              /* optional argument ::*/
+              goto end; 
+          }
+          else
+           {
+                chOpt = EOF; 
+                goto end;
+            }
+      }
+      
+      // next argv is the param
+      (*opt_ind)++;
+
+end:
+  (*opt_ind)++;
+  *opt_p = chOpt;
+  return prm;
+}
+
+
+/******************************************************************************/
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/Makefile b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/Makefile
new file mode 100644 (file)
index 0000000..a0c0627
--- /dev/null
@@ -0,0 +1,7 @@
+#\r
+# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source\r
+# file to this component.  This file merely indirects to the real make file\r
+# that is shared by all the driver components of the OpenIB Windows project.\r
+#\r
+\r
+!INCLUDE ..\..\..\..\inc\openib.def\r
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/SOURCES b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/SOURCES
new file mode 100644 (file)
index 0000000..03321e9
--- /dev/null
@@ -0,0 +1,62 @@
+TARGETNAME=opensm_3_0_0\r
+\r
+!if !defined(WINIBHOME)\r
+WINIBHOME=..\..\..\..\r
+!endif\r
+\r
+LIBPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)\r
+\r
+!if defined(OSM_TARGET)\r
+TARGETPATH=$(OSM_TARGET)\bin\user\obj$(BUILD_ALT_DIR)\r
+!else\r
+TARGETPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)\r
+!endif\r
+\r
+TARGETTYPE=PROGRAM\r
+UMTYPE=console\r
+USE_MSVCRT=1\r
+SOURCES=\\r
+        osm.mc \\r
+        opensm.rc \\r
+       osm_files.c\\r
+       osm_drop_mgr.c\\r
+        osm_prtn_config.c\\r
+        osm_sa_mcmember_record.c\\r
+        osm_sa_path_record.c\\r
+\r
+OSM_HOME=..\r
+\r
+TARGETLIBS=\\r
+!if $(FREEBUILD)\r
+                       $(LIBPATH)\*\ibal.lib \\r
+                       $(LIBPATH)\*\complib.lib \\r
+                       $(TARGETPATH)\*\osmv_ibal_3_0_0.lib \\r
+                       $(TARGETPATH)\*\opensm_ibal.lib\r
+\r
+!else\r
+                       $(LIBPATH)\*\ibald.lib \\r
+                       $(LIBPATH)\*\complibd.lib \\r
+                       $(TARGETPATH)\*\osmv_ibal_3_0_0d.lib \\r
+                       $(TARGETPATH)\*\opensm_ibald.lib\r
+!endif\r
+\r
+#DO NOT TOUCH the order of search path , until ib_types.h merging process will be done\r
+INCLUDES= \\r
+       $(OSM_HOME)\include; \\r
+       $(OSM_HOME); \\r
+       $(WINIBHOME)\inc; \\r
+       $(WINIBHOME)\inc\user;\r
+\r
+# Could be any special flag needed for this project \r
+USER_C_FLAGS=$(USER_C_FLAGS) /MD\r
+#Add preproccessor definitions\r
+C_DEFINES=$(C_DEFINES) -DWIN32 -D__WIN__ -D__i386__ -Dinline=__inline -DMT_LITTLE_ENDIAN -DOSM_VENDOR_INTF_AL\r
+C_DEFINES=$(C_DEFINES) -I.. -DHAVE_CONFIG_H\r
+!if !$(FREEBUILD)\r
+#C_DEFINES=$(C_DEFINES) -D_DEBUG -DDEBUG -DDBG\r
+C_DEFINES=$(C_DEFINES) \r
+!endif\r
+\r
+LINKER_FLAGS= $(LINKER_FLAGS)\r
+MSC_WARNING_LEVEL= /W3\r
+#MSC_OPTIMIZATION= /O0\r
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/cl_dispatcher.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/cl_dispatcher.c
new file mode 100644 (file)
index 0000000..252ceee
--- /dev/null
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: cl_dispatcher.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of Dispatcher abstraction.
+ *
+ * Environment:
+ *    All
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <complib/cl_dispatcher.h>
+#include <complib/cl_timer.h>
+
+/* give some guidance when we build our cl_pool of messages */
+#define CL_DISP_INITIAL_MSG_COUNT   256
+#define CL_DISP_MSG_GROW_SIZE       64
+
+/* give some guidance when we build our cl_pool of registration elements */
+#define CL_DISP_INITIAL_REG_COUNT   16
+#define CL_DISP_REG_GROW_SIZE       16
+
+/********************************************************************
+   __cl_disp_worker
+
+   Description:
+   This function takes messages off the FIFO and calls Processmsg()
+   This function executes as passive level.
+
+   Inputs:
+   p_disp - Pointer to Dispatcher object
+
+   Outputs:
+   None
+
+   Returns:
+   None
+********************************************************************/
+void
+__cl_disp_worker(
+  IN void* context )
+{
+  cl_disp_msg_t      *p_msg;
+  cl_dispatcher_t    *p_disp = (cl_dispatcher_t*)context;
+
+  cl_spinlock_acquire( &p_disp->lock );
+
+  /* Process the FIFO until we drain it dry. */
+  while( cl_qlist_count( &p_disp->msg_fifo ) )
+  {
+    /* Pop the message at the head from the FIFO. */
+    p_msg = (cl_disp_msg_t*)cl_qlist_remove_head( &p_disp->msg_fifo );
+
+    /* we track the tim ethe last message spent in the queue */
+    p_disp->last_msg_queue_time_us = cl_get_time_stamp() - p_msg->in_time;
+
+    /*
+     * Release the spinlock while the message is processed.
+     * The user's callback may reenter the dispatcher
+     * and cause the lock to be reaquired.
+     */
+    cl_spinlock_release( &p_disp->lock );
+    p_msg->p_dest_reg->pfn_rcv_callback(
+      (void*)p_msg->p_dest_reg->context, (void*)p_msg->p_data );
+
+    cl_atomic_dec( &p_msg->p_dest_reg->ref_cnt );
+
+    /* The client has seen the data.  Notify the sender as appropriate. */
+    if( p_msg->pfn_xmt_callback )
+    {
+      p_msg->pfn_xmt_callback( (void*)p_msg->context,
+                               (void*)p_msg->p_data );
+      cl_atomic_dec( &p_msg->p_src_reg->ref_cnt );
+    }
+
+    /* Grab the lock for the next iteration through the list. */
+    cl_spinlock_acquire(&p_disp->lock);
+
+    /* Return this message to the pool. */
+    cl_qpool_put( &p_disp->msg_pool, (cl_pool_item_t *)p_msg );
+  }
+
+  cl_spinlock_release( &p_disp->lock );
+}
+
+/********************************************************************
+ ********************************************************************/
+void
+cl_disp_construct(
+  IN  cl_dispatcher_t* const  p_disp )
+{
+  CL_ASSERT( p_disp );
+
+  cl_qlist_init( &p_disp->reg_list );
+  cl_ptr_vector_construct( &p_disp->reg_vec );
+  cl_thread_pool_construct( &p_disp->worker_threads );
+  cl_qlist_init( &p_disp->msg_fifo );
+  cl_spinlock_construct( &p_disp->lock );
+  cl_qpool_construct( &p_disp->msg_pool );
+}
+
+/********************************************************************
+ ********************************************************************/
+void
+cl_disp_shutdown(
+  IN  cl_dispatcher_t* const  p_disp )
+{
+  CL_ASSERT( p_disp );
+
+  /* Stop the thread pool. */
+  cl_thread_pool_destroy( &p_disp->worker_threads );
+
+  /* Process all outstanding callbacks. */
+  __cl_disp_worker( p_disp );
+
+  /* Free all registration info. */
+  while( !cl_is_qlist_empty( &p_disp->reg_list ) )
+    free( cl_qlist_remove_head( &p_disp->reg_list ) );
+}
+
+/********************************************************************
+ ********************************************************************/
+void
+cl_disp_destroy(
+  IN  cl_dispatcher_t* const  p_disp )
+{
+  CL_ASSERT( p_disp );
+
+  cl_spinlock_destroy( &p_disp->lock );
+  /* Destroy the message pool */
+  cl_qpool_destroy( &p_disp->msg_pool );
+  /* Destroy the pointer vector of registrants. */
+  cl_ptr_vector_destroy( &p_disp->reg_vec );
+}
+
+/********************************************************************
+ ********************************************************************/
+cl_status_t
+cl_disp_init(
+  IN  cl_dispatcher_t* const  p_disp,
+  IN  const uint32_t       thread_count,
+  IN  const char* const    name )
+{
+  cl_status_t status;
+
+  CL_ASSERT( p_disp );
+
+  cl_disp_construct( p_disp );
+
+  status = cl_spinlock_init( &p_disp->lock );
+  if( status != CL_SUCCESS )
+  {
+    cl_disp_destroy( p_disp );
+    return( status );
+  }
+
+  /* Specify no upper limit to the number of messages in the pool */
+  status = cl_qpool_init( &p_disp->msg_pool, CL_DISP_INITIAL_MSG_COUNT,
+                          0, CL_DISP_MSG_GROW_SIZE, sizeof(cl_disp_msg_t), NULL,
+                          NULL, NULL );
+  if( status != CL_SUCCESS )
+  {
+    cl_disp_destroy( p_disp );
+    return( status );
+  }
+
+  status = cl_ptr_vector_init( &p_disp->reg_vec, CL_DISP_INITIAL_REG_COUNT,
+                               CL_DISP_REG_GROW_SIZE );
+  if( status != CL_SUCCESS )
+  {
+    cl_disp_destroy( p_disp );
+    return( status );
+  }
+
+  status = cl_thread_pool_init( &p_disp->worker_threads, thread_count,
+                                __cl_disp_worker, p_disp, name );
+  if( status != CL_SUCCESS )
+    cl_disp_destroy( p_disp );
+
+  return( status );
+}
+
+/********************************************************************
+ ********************************************************************/
+cl_disp_reg_handle_t
+cl_disp_register(
+  IN  cl_dispatcher_t* const  p_disp,
+  IN  const cl_disp_msgid_t   msg_id,
+  IN  cl_pfn_msgrcv_cb_t      pfn_callback OPTIONAL,
+  IN  const void* const    context OPTIONAL )
+{
+  cl_disp_reg_info_t *p_reg;
+  cl_status_t status;
+
+  CL_ASSERT( p_disp );
+
+  /* Check that the requested registrant ID is available. */
+  cl_spinlock_acquire( &p_disp->lock );
+  if(    (msg_id != CL_DISP_MSGID_NONE ) &&
+         (msg_id < cl_ptr_vector_get_size( &p_disp->reg_vec )) &&
+         (cl_ptr_vector_get( &p_disp->reg_vec, msg_id )) )
+  {
+    cl_spinlock_release( &p_disp->lock );
+    return( NULL );
+  }
+
+  /* Get a registration info from the pool. */
+  p_reg = (cl_disp_reg_info_t*)malloc( sizeof(cl_disp_reg_info_t) );
+  if( !p_reg )
+  {
+    cl_spinlock_release( &p_disp->lock );
+    return( NULL );
+  }
+  else
+  {
+    memset( p_reg, 0, sizeof(cl_disp_reg_info_t) );
+  }
+
+  p_reg->p_disp = p_disp;
+  p_reg->ref_cnt = 0;
+  p_reg->pfn_rcv_callback = pfn_callback;
+  p_reg->context = context;
+  p_reg->msg_id = msg_id;
+
+  /* Insert the registration in the list. */
+  cl_qlist_insert_tail( &p_disp->reg_list, (cl_list_item_t*)p_reg );
+
+  /* Set the array entry to the registrant. */
+  /* The ptr_vector grow automatically as necessary. */
+  if( msg_id != CL_DISP_MSGID_NONE )
+  {
+    status = cl_ptr_vector_set( &p_disp->reg_vec, msg_id, p_reg );
+    if( status != CL_SUCCESS )
+    {
+      free( p_reg );
+      cl_spinlock_release( &p_disp->lock );
+      return( NULL );
+    }
+  }
+
+  cl_spinlock_release( &p_disp->lock );
+
+  return( p_reg );
+}
+
+/********************************************************************
+ ********************************************************************/
+void
+cl_disp_unregister(
+  IN const cl_disp_reg_handle_t  handle )
+{
+  cl_disp_reg_info_t *p_reg;
+  cl_dispatcher_t    *p_disp;
+
+  if( handle == CL_DISP_INVALID_HANDLE )
+    return;
+
+  p_reg = (cl_disp_reg_info_t*)handle;
+  p_disp = p_reg->p_disp;
+  CL_ASSERT( p_disp );
+
+  cl_spinlock_acquire( &p_disp->lock );
+  /*
+   * Clear the registrant vector entry.  This will cause any further
+   * post calls to fail.
+   */
+  if( p_reg->msg_id != CL_DISP_MSGID_NONE )
+  {
+    CL_ASSERT( p_reg->msg_id < cl_ptr_vector_get_size(&p_disp->reg_vec));
+    cl_ptr_vector_set( &p_disp->reg_vec, p_reg->msg_id, NULL );
+  }
+  cl_spinlock_release( &p_disp->lock );
+
+  while( p_reg->ref_cnt > 0)
+    cl_thread_suspend( 1 );
+
+  cl_spinlock_acquire(&p_disp->lock);
+  /* Remove the registrant from the list. */
+  cl_qlist_remove_item( &p_disp->reg_list, (cl_list_item_t*)p_reg );
+  /* Return the registration info to the pool */
+  free( p_reg );
+
+  cl_spinlock_release( &p_disp->lock );
+}
+
+/********************************************************************
+ ********************************************************************/
+cl_status_t
+cl_disp_post(
+  IN const cl_disp_reg_handle_t  handle,
+  IN const cl_disp_msgid_t    msg_id,
+  IN const void* const        p_data,
+  IN cl_pfn_msgdone_cb_t      pfn_callback OPTIONAL,
+  IN const void* const        context OPTIONAL )
+{
+  cl_disp_reg_info_t *p_src_reg = (cl_disp_reg_info_t*)handle;
+  cl_disp_reg_info_t *p_dest_reg;
+  cl_dispatcher_t    *p_disp;
+  cl_disp_msg_t      *p_msg;
+
+  p_disp = handle->p_disp;
+  CL_ASSERT( p_disp );
+  CL_ASSERT( msg_id != CL_DISP_MSGID_NONE );
+
+  cl_spinlock_acquire( &p_disp->lock );
+  /* Check that the recipient exists. */
+  p_dest_reg = cl_ptr_vector_get( &p_disp->reg_vec, msg_id );
+  if( !p_dest_reg )
+  {
+    cl_spinlock_release( &p_disp->lock );
+    return( CL_NOT_FOUND );
+  }
+
+  /* Get a free message from the pool. */
+  p_msg = (cl_disp_msg_t*)cl_qpool_get( &p_disp->msg_pool );
+  if( !p_msg )
+  {
+    cl_spinlock_release( &p_disp->lock );
+    return( CL_INSUFFICIENT_MEMORY );
+  }
+
+  /* Initialize the message */
+  p_msg->p_src_reg = p_src_reg;
+  p_msg->p_dest_reg = p_dest_reg;
+  p_msg->p_data = p_data;
+  p_msg->pfn_xmt_callback = pfn_callback;
+  p_msg->context = context;
+  p_msg->in_time = cl_get_time_stamp();
+
+  /*
+   * Increment the sender's reference count if they request a completion
+   * notification.
+   */
+  if( pfn_callback )
+    cl_atomic_inc( &p_src_reg->ref_cnt );
+
+  /* Increment the recipient's reference count. */
+  cl_atomic_inc( &p_dest_reg->ref_cnt );
+
+  /* Queue the message in the FIFO. */
+  cl_qlist_insert_tail( &p_disp->msg_fifo, (cl_list_item_t *)p_msg );
+  cl_spinlock_release( &p_disp->lock );
+
+  /* Signal the thread pool that there is work to be done. */
+  cl_thread_pool_signal( &p_disp->worker_threads );
+  return( CL_SUCCESS );
+}
+
+void
+cl_disp_get_queue_status(
+  IN const cl_disp_reg_handle_t handle,
+  OUT uint32_t *p_num_queued_msgs,
+  OUT uint64_t *p_last_msg_queue_time_ms)
+{
+  cl_dispatcher_t    *p_disp = ((cl_disp_reg_info_t*)handle)->p_disp;
+
+  cl_spinlock_acquire( &p_disp->lock );
+
+  if (p_last_msg_queue_time_ms)
+    *p_last_msg_queue_time_ms = p_disp->last_msg_queue_time_us/1000;
+
+  if (p_num_queued_msgs)
+    *p_num_queued_msgs = cl_qlist_count( &p_disp->msg_fifo );
+
+  cl_spinlock_release( &p_disp->lock );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/cl_event_wheel.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/cl_event_wheel.c
new file mode 100644 (file)
index 0000000..8e65c70
--- /dev/null
@@ -0,0 +1,663 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: cl_event_wheel.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <math.h>
+#include <stdlib.h>
+#include <complib/cl_event_wheel.h>
+#include <complib/cl_debug.h>
+
+cl_status_t
+__event_will_age_before(
+  IN  const cl_list_item_t* const   p_list_item,
+  IN  void*                context )
+{
+  uint64_t aging_time = *((uint64_t*)context);
+  cl_event_wheel_reg_info_t *p_event;
+
+  p_event =
+    PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item);
+
+  if (p_event->aging_time < aging_time)
+    return CL_SUCCESS;
+  else
+    return CL_NOT_FOUND;
+}
+
+void
+__cl_event_wheel_callback( IN void* context )
+{
+  cl_event_wheel_t *p_event_wheel = (cl_event_wheel_t *)context;
+  cl_list_item_t *p_list_item, *p_prev_event_list_item;
+  cl_list_item_t *p_list_next_item;
+  cl_event_wheel_reg_info_t *p_event;
+  uint64_t current_time;
+  uint64_t next_aging_time;
+  uint32_t new_timeout;
+  cl_status_t cl_status;
+
+  OSM_LOG_ENTER( p_event_wheel->p_log, __cl_event_wheel_callback);
+
+  /* might be during closing ...  */
+  if (p_event_wheel->closing)
+  {
+    goto JustExit;
+  }
+
+  current_time = cl_get_time_stamp();
+
+  if (NULL != p_event_wheel->p_external_lock) {
+
+    /* Take care of the order of acquiring locks to avoid the deadlock!
+     * The external lock goes first.
+     */
+    CL_SPINLOCK_ACQUIRE(p_event_wheel->p_external_lock);
+  }
+
+  CL_SPINLOCK_ACQUIRE(&p_event_wheel->lock);
+
+  p_list_item = cl_qlist_head(&p_event_wheel->events_wheel);
+  if (p_list_item == cl_qlist_end(&p_event_wheel->events_wheel))
+  {
+    /* the list is empty - nothing to do */
+    goto Exit;
+  }
+
+  /* we found such an item.  get the p_event */
+  p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item);
+
+  while (p_event->aging_time <= current_time)
+  {
+    /* this object has aged - invoke it's callback */
+    if (p_event->pfn_aged_callback)
+    {
+      next_aging_time =
+        p_event->pfn_aged_callback(
+          p_event->key, p_event->num_regs, p_event->context);
+    }
+    else
+    {
+      next_aging_time = 0;
+    }
+
+    /* point to the next object in the wheel */
+    p_list_next_item = cl_qlist_next(p_list_item);
+
+    /* We need to retire the event if the next aging time passed */
+    if (next_aging_time < current_time)
+    {
+      /* remove it from the map */
+      cl_qmap_remove_item(&p_event_wheel->events_map, &(p_event->map_item));
+
+      /* pop p_event from the wheel */
+      cl_qlist_remove_head(&p_event_wheel->events_wheel);
+
+      /* delete the event info object - allocated by cl_event_wheel_reg */
+      free(p_event);
+    }
+    else
+    {
+      /* update the required aging time */
+      p_event->aging_time = next_aging_time;
+      p_event->num_regs++;
+
+      /* do not remove from the map  - but remove from the list head and
+         place in the correct position */
+
+      /* pop p_event from the wheel */
+      cl_qlist_remove_head(&p_event_wheel->events_wheel);
+
+      /* find the event that ages just before */
+      p_prev_event_list_item = cl_qlist_find_from_tail(
+        &p_event_wheel->events_wheel,
+        __event_will_age_before,
+        &p_event->aging_time);
+
+      /* insert just after */
+      cl_qlist_insert_next(
+        &p_event_wheel->events_wheel,
+        p_prev_event_list_item ,
+        &p_event->list_item);
+
+      /* as we have modified the list - restart from first item: */
+      p_list_next_item = cl_qlist_head(&p_event_wheel->events_wheel);
+    }
+
+    /* advance to next event */
+    p_list_item = p_list_next_item;
+    if (p_list_item == cl_qlist_end(&p_event_wheel->events_wheel))
+    {
+      /* the list is empty - nothing to do */
+      break;
+    }
+
+    /* get the p_event */
+    p_event =  PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item);
+  }
+
+  /* We need to restart the timer only if the list is not empty now */
+  if (p_list_item != cl_qlist_end(&p_event_wheel->events_wheel))
+  {
+    /* get the p_event */
+    p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item);
+
+    /* start the timer to the timeout [msec] */
+    new_timeout = (uint32_t)(((p_event->aging_time - current_time)/1000)+0.5);
+    osm_log (p_event_wheel->p_log, OSM_LOG_DEBUG,
+               "__cl_event_wheel_callback : "
+               "Restart timer in : %u [msec]\n",
+             new_timeout);
+    cl_status = cl_timer_start(&p_event_wheel->timer, new_timeout);
+    if (cl_status != CL_SUCCESS)
+    {
+      osm_log (p_event_wheel->p_log, OSM_LOG_ERROR,
+               "__cl_event_wheel_callback : ERR 6100: "
+               "Failed to start timer\n" );
+    }
+  }
+
+  /* release the lock */
+ Exit:
+  CL_SPINLOCK_RELEASE( &p_event_wheel->lock );
+  if (NULL != p_event_wheel->p_external_lock) {
+    CL_SPINLOCK_RELEASE(p_event_wheel->p_external_lock);
+  }
+ JustExit:
+  OSM_LOG_EXIT( p_event_wheel->p_log );
+}
+
+/*
+ * Construct and Initialize
+ */
+void
+cl_event_wheel_construct(
+  IN  cl_event_wheel_t* const p_event_wheel )
+{
+  cl_spinlock_construct( &(p_event_wheel->lock) );
+  cl_timer_construct( &(p_event_wheel->timer) );
+}
+
+cl_status_t
+cl_event_wheel_init(
+  IN  cl_event_wheel_t* const p_event_wheel,
+  IN  osm_log_t *p_log)
+{
+  cl_status_t cl_status = CL_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, cl_event_wheel_init );
+
+  /* initialize */
+  p_event_wheel->p_log = p_log;
+  p_event_wheel->p_external_lock = NULL;
+  p_event_wheel->closing = FALSE;
+  cl_status =  cl_spinlock_init( &(p_event_wheel->lock) );
+  if (cl_status != CL_SUCCESS)
+  {
+    osm_log (p_event_wheel->p_log, OSM_LOG_ERROR,
+             "cl_event_wheel_init : ERR 6101: "
+             "Failed to initialize cl_spinlock\n" );
+    goto Exit;
+  }
+  cl_qlist_init( &p_event_wheel->events_wheel);
+  cl_qmap_init( &p_event_wheel->events_map );
+
+  /* init the timer with timeout */
+  cl_status = cl_timer_init(&p_event_wheel->timer,
+                            __cl_event_wheel_callback,
+                            p_event_wheel ); /* cb context */
+
+  if (cl_status != CL_SUCCESS)
+  {
+    osm_log (p_event_wheel->p_log, OSM_LOG_ERROR,
+             "cl_event_wheel_init : ERR 6102: "
+             "Failed to initialize cl_timer\n" );
+    goto Exit;
+  }
+ Exit:
+  OSM_LOG_EXIT( p_event_wheel->p_log );
+  return(cl_status);
+}
+
+cl_status_t
+cl_event_wheel_init_ex(
+  IN  cl_event_wheel_t* const p_event_wheel,
+  IN  osm_log_t       *p_log,
+  IN  cl_spinlock_t   *p_external_lock)
+{
+  cl_status_t cl_status;
+
+  cl_status = cl_event_wheel_init(p_event_wheel, p_log);
+  if (CL_SUCCESS != cl_status)
+  {
+    return cl_status;
+  }
+
+  p_event_wheel->p_external_lock = p_external_lock;
+  return cl_status;
+}
+
+void
+cl_event_wheel_dump(
+  IN cl_event_wheel_t* const p_event_wheel )
+{
+  cl_list_item_t *p_list_item;
+  cl_event_wheel_reg_info_t *p_event;
+
+  OSM_LOG_ENTER( p_event_wheel->p_log, cl_event_wheel_dump );
+
+  p_list_item = cl_qlist_head(&p_event_wheel->events_wheel);
+  osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+           "cl_event_wheel_dump: "
+           "event_wheel ptr:%p\n",
+           p_event_wheel);
+
+  while (p_list_item != cl_qlist_end(&p_event_wheel->events_wheel) )
+  {
+    p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item);
+    osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+             "cl_event_wheel_dump: "
+             "Found event key:<0x%"PRIx64">, aging time:%" PRIu64"\n",
+             p_event->key, p_event->aging_time );
+    p_list_item = cl_qlist_next( p_list_item );
+  }
+  OSM_LOG_EXIT( p_event_wheel->p_log );
+}
+
+void
+cl_event_wheel_destroy(
+  IN cl_event_wheel_t* const p_event_wheel )
+{
+  cl_list_item_t  *p_list_item;
+  cl_map_item_t   *p_map_item;
+  cl_event_wheel_reg_info_t *p_event;
+
+  OSM_LOG_ENTER( p_event_wheel->p_log, cl_event_wheel_destroy );
+
+  /* we need to get a lock */
+  CL_SPINLOCK_ACQUIRE( &p_event_wheel->lock );
+
+  cl_event_wheel_dump( p_event_wheel);
+
+  /* go over all the items in the list and remove them */
+  p_list_item = cl_qlist_remove_head(&p_event_wheel->events_wheel);
+  while ( p_list_item != cl_qlist_end(&p_event_wheel->events_wheel) )
+  {
+    p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item);
+
+    osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+             "cl_event_wheel_destroy: "
+             "Found outstanding event key:<0x%"PRIx64">\n",
+             p_event->key );
+
+    /* remove it from the map */
+    p_map_item = &(p_event->map_item);
+    cl_qmap_remove_item(&p_event_wheel->events_map, p_map_item);
+    free(p_event); /* allocated by cl_event_wheel_reg */
+    p_list_item = cl_qlist_remove_head(&p_event_wheel->events_wheel);
+  }
+
+  /* destroy the timer */
+  cl_timer_destroy( &p_event_wheel->timer );
+
+  /* destroy the lock (this should be done without releasing - we don't want
+     any other run to grab the lock at this point. */
+  CL_SPINLOCK_RELEASE( &p_event_wheel->lock );
+  cl_spinlock_destroy( &(p_event_wheel->lock) );
+
+  OSM_LOG_EXIT( p_event_wheel->p_log );
+}
+
+cl_status_t
+cl_event_wheel_reg(
+  IN cl_event_wheel_t* const p_event_wheel,
+  IN const uint64_t          key,
+  IN const uint64_t          aging_time_usec,
+  IN cl_pfn_event_aged_cb_t  pfn_callback,
+  IN void* const       context )
+{
+  cl_event_wheel_reg_info_t *p_event;
+  uint64_t timeout;
+  uint32_t to;
+  cl_status_t cl_status = CL_SUCCESS;
+  cl_list_item_t *prev_event_list_item;
+  cl_map_item_t  *p_map_item;
+
+  OSM_LOG_ENTER( p_event_wheel->p_log, cl_event_wheel_reg );
+
+  /* Get the lock on the manager */
+  CL_SPINLOCK_ACQUIRE( &(p_event_wheel->lock) );
+
+  cl_event_wheel_dump( p_event_wheel);
+
+  /* Make sure such a key does not exists */
+  p_map_item = cl_qmap_get( &p_event_wheel->events_map, key );
+  if (p_map_item != cl_qmap_end( &p_event_wheel->events_map ))
+  {
+    osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+             "cl_event_wheel_reg: "
+             "Already exists key:0x%"PRIx64"\n", key);
+
+    /* already there - remove it from the list as it is getting a new time */
+    p_event = PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t, map_item);
+
+    /* remove the item from the qlist */
+    cl_qlist_remove_item( &p_event_wheel->events_wheel, &p_event->list_item );
+    /* and the qmap */
+    cl_qmap_remove_item( &p_event_wheel->events_map, &p_event->map_item );
+  }
+  else
+  {
+    /* make a new one */
+    p_event = (cl_event_wheel_reg_info_t *)
+      malloc( sizeof (cl_event_wheel_reg_info_t) );
+    p_event->num_regs = 0;
+  }
+
+  p_event->key = key;
+  p_event->aging_time = aging_time_usec;
+  p_event->pfn_aged_callback = pfn_callback;
+  p_event->context = context;
+  p_event->num_regs++;
+
+  osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+           "cl_event_wheel_reg: "
+           "Registering event key:0x%"PRIx64" aging in %u [msec]\n",
+           p_event->key,
+           (uint32_t)((p_event->aging_time - cl_get_time_stamp()) / 1000 ));
+
+  /* If the list is empty - need to start the timer */
+  if (cl_is_qlist_empty(&p_event_wheel->events_wheel))
+  {
+    /* Edward Bortnikov 03/29/2003
+     * ++TBD Consider moving the timer manipulation behind the list manipulation.
+     */
+
+    /* calculate the new timeout */
+    timeout = (p_event->aging_time - cl_get_time_stamp() + 500) / 1000;
+
+    /* stop the timer if it is running */
+
+    /* Edward Bortnikov 03/29/2003
+     * Don't call cl_timer_stop() because it spins forever.
+     * cl_timer_start() will invoke cl_timer_stop() by itself.
+     *
+     * The problematic scenario is when __cl_event_wheel_callback()
+     * is in race condition with this code. It sets timer.in_timer_cb
+     * to TRUE and then blocks on p_event_wheel->lock. Following this,
+     * the call to cl_timer_stop() hangs. Following this, the whole system
+     * enters into a deadlock.
+     *
+     * cl_timer_stop(&p_event_wheel->timer);
+     */
+
+    /* The timeout for the cl_timer_start should be given as uint32_t.
+       if there is an overflow - warn about it. */
+    to = (uint32_t)timeout;
+    if ( timeout > (uint32_t)timeout )
+    {
+      to = 0xffffffff; /* max 32 bit timer */
+      osm_log (p_event_wheel->p_log, OSM_LOG_INFO,
+               "cl_event_wheel_reg: "
+               "timeout requested is too large. Using timeout: %u\n",
+               to );
+    }
+
+    /* start the timer to the timeout [msec] */
+    cl_status = cl_timer_start(&p_event_wheel->timer, to);
+    if (cl_status != CL_SUCCESS)
+    {
+      osm_log (p_event_wheel->p_log, OSM_LOG_ERROR,
+               "cl_event_wheel_reg : ERR 6103: "
+               "Failed to start timer\n" );
+      goto Exit;
+    }
+  }
+
+  /* insert the object to the qlist and the qmap */
+
+  /* BUT WE MUST INSERT IT IN A SORTED MANNER */
+  prev_event_list_item = cl_qlist_find_from_tail(
+    &p_event_wheel->events_wheel,
+    __event_will_age_before,
+    &p_event->aging_time);
+
+  cl_qlist_insert_next(
+    &p_event_wheel->events_wheel,
+    prev_event_list_item ,
+    &p_event->list_item);
+
+  cl_qmap_insert( &p_event_wheel->events_map, key, &(p_event->map_item));
+
+ Exit:
+  CL_SPINLOCK_RELEASE( &p_event_wheel->lock );
+  OSM_LOG_EXIT( p_event_wheel->p_log );
+
+  return cl_status;
+}
+
+void
+cl_event_wheel_unreg(
+  IN cl_event_wheel_t* const p_event_wheel,
+  IN uint64_t key )
+{
+  cl_event_wheel_reg_info_t *p_event;
+  cl_map_item_t* p_map_item;
+
+  OSM_LOG_ENTER( p_event_wheel->p_log, cl_event_wheel_unreg );
+
+  osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+           "cl_event_wheel_unreg: "
+           "Removing key:0x%"PRIx64"\n", key );
+
+  CL_SPINLOCK_ACQUIRE( &p_event_wheel->lock );
+  p_map_item = cl_qmap_get( &p_event_wheel->events_map, key );
+  if (p_map_item != cl_qmap_end( &p_event_wheel->events_map ))
+  {
+    /* we found such an item. */
+    p_event = PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t, map_item);
+
+    /* remove the item from the qlist */
+    cl_qlist_remove_item( &p_event_wheel->events_wheel, &(p_event->list_item));
+    /* remove the item from the qmap */
+    cl_qmap_remove_item( &p_event_wheel->events_map, &(p_event->map_item) );
+
+    osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+             "cl_event_wheel_unreg: "
+             "Removed key:0x%"PRIx64"\n", key );
+
+    /* free the item */
+    free(p_event);
+  }
+  else
+  {
+    osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+             "cl_event_wheel_unreg: "
+             "Did not find key:0x%"PRIx64"\n", key );
+  }
+
+  CL_SPINLOCK_RELEASE( &p_event_wheel->lock );
+  OSM_LOG_EXIT( p_event_wheel->p_log );
+
+}
+
+uint32_t
+cl_event_wheel_num_regs(
+  IN cl_event_wheel_t* const p_event_wheel,
+  IN uint64_t key )
+{
+
+  cl_event_wheel_reg_info_t *p_event;
+  cl_map_item_t* p_map_item;
+  uint32_t num_regs = 0;
+
+  OSM_LOG_ENTER( p_event_wheel->p_log, cl_event_wheel_num_regs );
+
+  /* try to find the key in the map */
+  osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+           "cl_event_wheel_num_regs: "
+           "Looking for key:0x%"PRIx64"\n", key );
+
+  CL_SPINLOCK_ACQUIRE( &p_event_wheel->lock );
+  p_map_item = cl_qmap_get( &p_event_wheel->events_map, key );
+  if (p_map_item != cl_qmap_end( &p_event_wheel->events_map ))
+  {
+    /* ok so we can simply return it's num_regs */
+    p_event = PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t, map_item);
+    num_regs = p_event->num_regs;
+  }
+
+  CL_SPINLOCK_RELEASE( &p_event_wheel->lock );
+  OSM_LOG_EXIT( p_event_wheel->p_log );
+  return(num_regs);
+}
+
+#ifdef __CL_EVENT_WHEEL_TEST__
+
+/* Dump out the complete state of the event wheel */
+void __cl_event_wheel_dump(
+  IN cl_event_wheel_t* const p_event_wheel)
+{
+  cl_list_item_t *p_list_item;
+  cl_map_item_t  *p_map_item;
+  cl_event_wheel_reg_info_t *p_event;
+
+  printf("************** Event Wheel Dump ***********************\n");
+  printf("Event Wheel List has %u items:\n",
+         cl_qlist_count( &p_event_wheel->events_wheel ));
+
+  p_list_item = cl_qlist_head(&p_event_wheel->events_wheel);
+  while (p_list_item != cl_qlist_end(&p_event_wheel->events_wheel))
+  {
+    p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item);
+    printf("Event key:0x%"PRIx64" Conetxt:%s NumRegs:%u\n",
+           p_event->key, (char *)p_event->context, p_event->num_regs);
+
+    /* next */
+    p_list_item = cl_qlist_next(p_list_item);
+  }
+
+  printf("Event Map has %u items:\n",
+         cl_qmap_count( &p_event_wheel->events_map ));
+
+  p_map_item = cl_qmap_head(&p_event_wheel->events_map);
+  while (p_map_item != cl_qmap_end(&p_event_wheel->events_map))
+  {
+    p_event = PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t, map_item);
+    printf("Event key:0x%"PRIx64" Conetxt:%s NumRegs:%u\n",
+           p_event->key, (char *)p_event->context, p_event->num_regs);
+
+    /* next */
+    p_map_item = cl_qmap_next(p_map_item);
+  }
+
+}
+
+/* The callback for aging event */
+/* We assume we pass a text context */
+void __test_event_aging(uint64_t key, void *context)
+{
+  printf("*****************************************************\n");
+  printf("Aged key: 0x%"PRIx64" Conetxt:%s\n", key, (char *)context);
+}
+
+int
+main ()
+{
+  osm_log_t log;
+  cl_event_wheel_t event_wheel;
+  /*  uint64_t key; */
+
+  /* construct */
+  osm_log_construct( &log );
+  cl_event_wheel_construct( &event_wheel );
+
+  /* init */
+  osm_log_init_v2( &log, TRUE, 0xff, NULL, 0, FALSE);
+  cl_event_wheel_init( &event_wheel, &log );
+
+  /* Start Playing */
+  cl_event_wheel_reg( &event_wheel,
+                      1, /*  key */
+                      cl_get_time_stamp() + 3000000, /*  3 sec lifetime */
+                      __test_event_aging, /*  cb */
+                      "The first Aging Event"
+                      );
+
+  cl_event_wheel_reg( &event_wheel,
+                      2, /*  key */
+                      cl_get_time_stamp() + 3000000, /*  3 sec lifetime */
+                      __test_event_aging, /*  cb */
+                      "The Second Aging Event"
+                      );
+
+  cl_event_wheel_reg( &event_wheel,
+                      3, /*  key */
+                      cl_get_time_stamp() + 3500000, /*  3 sec lifetime */
+                      __test_event_aging, /*  cb */
+                      "The Third Aging Event"
+                      );
+
+  __cl_event_wheel_dump(&event_wheel);
+
+  sleep(2);
+  cl_event_wheel_reg( &event_wheel,
+                      2, /*  key */
+                      cl_get_time_stamp() + 8000000, /*  3 sec lifetime */
+                      __test_event_aging, /*  cb */
+                      "The Second Aging Event Moved"
+                      );
+
+  __cl_event_wheel_dump(&event_wheel);
+
+  sleep(1);
+  /* remove the third event */
+  cl_event_wheel_unreg( &event_wheel,
+                        3); /*  key */
+
+  /* get the number of registrations for the keys */
+  printf("Event 1 Registred: %u\n", cl_event_wheel_num_regs(&event_wheel, 1));
+  printf("Event 2 Registred: %u\n", cl_event_wheel_num_regs(&event_wheel, 2));
+
+  sleep(5);
+  /* destroy */
+  cl_event_wheel_destroy( &event_wheel );
+
+  return(0);
+}
+
+#endif /* __CL_EVENT_WHEEL_TEST__ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/main.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/main.c
new file mode 100644 (file)
index 0000000..0aed5cc
--- /dev/null
@@ -0,0 +1,1158 @@
+/*
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: main.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Command line interface for opensm.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.23 $
+ */
+#pragma warning(disable : 4996)
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include "stdio.h"
+#include <stdlib.h>
+#include <complib/cl_types.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_version.h>
+#include <opensm/osm_opensm.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_base.h>
+
+/********************************************************************
+       D E F I N E    G L O B A L    V A R I A B L E S
+*********************************************************************/
+/*
+  This is the global opensm object.
+  One opensm object is required per subnet.
+  Future versions could support multiple subnets by
+  instantiating more than one opensm object.
+*/
+osm_opensm_t osm;
+volatile unsigned int osm_exit_flag = 0;
+HANDLE osm_exit_event = NULL;
+
+#define GUID_ARRAY_SIZE 64
+#define INVALID_GUID (0xFFFFFFFFFFFFFFFFULL)
+
+typedef struct _osm_main_args_t
+{
+  int                   argc;
+  char**                argv;
+  boolean_t             is_service;
+} osm_main_args_t;
+
+osm_main_args_t osm_main_args;
+
+enum service_state {
+  SERVICE_STATE_STARTING,
+  SERVICE_STATE_STARTED_OK,
+  SERVICE_STATE_START_FAILED
+};
+
+enum service_state g_service_state = SERVICE_STATE_STARTING;
+
+void OsmReportState(IN const char *p_str)
+{
+  if ( !strcmp(p_str, "SUBNET UP\n") ||
+       !strcmp(p_str, "SM port is down\n") ||
+       !strcmp(p_str, "Errors during initialization\n") ||
+       !strcmp(p_str, "Entering STANDBY state\n") )
+  {
+    InterlockedCompareExchange((LONG *)&g_service_state , SERVICE_STATE_STARTED_OK, SERVICE_STATE_STARTING);
+    return;
+  }
+
+  if ( !strcmp(p_str, "Found remote SM with non-matching sm_key. Exiting\n") ||
+       !strcmp(p_str, "Errors on subnet. Duplicate GUID found ""by link from a port to itself. ""See osm log for more details\n") ||
+       !strcmp(p_str, "Errors on subnet. SM found duplicated guids or 12x ""link with lane reversal badly configured. ""See osm log for more details\n") ||
+       !strcmp(p_str, "Fatal: Error restoring Guid-to-Lid persistent database\n") )
+
+  {
+    InterlockedCompareExchange((LONG *)&g_service_state , SERVICE_STATE_START_FAILED, SERVICE_STATE_STARTING);
+    return;
+  }
+
+  if( !strcmp(p_str, "OpenSM Rev:openib-1.2.0\n") || 
+      !strcmp(p_str, "OpenSM Rev:openib-2.0.3\n") ||
+      !strcmp(p_str, "OpenSM Rev:openib-3.0.0\n") ||
+      !strcmp(p_str, "Entering MASTER state\n") ||
+      !strcmp(p_str, "Exiting SM\n") )
+  {
+    // This are messages that it is safe to ignore
+    return;
+  }
+  CL_ASSERT(FALSE);
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+void show_usage(void);
+
+void
+show_usage(void)
+{
+  printf( "\n------- OpenSM - Usage and options ----------------------\n" );
+  printf( "Usage:   opensm [options]\n");
+  printf( "Options:\n" );
+  printf( "-c\n"
+          "--cache-options\n"
+          "          Cache the given command line options into the file\n"
+          "          /var/cache/osm/opensm.opts for use next invocation\n"
+          "          The cache directory can be changed by the environment\n"
+          "          variable OSM_CACHE_DIR\n\n");
+  printf( "-g[=]<GUID in hex>\n"
+          "--guid[=]<GUID in hex>\n"
+          "          This option specifies the local port GUID value\n"
+          "          with which OpenSM should bind.  OpenSM may be\n"
+          "          bound to 1 port at a time.\n"
+          "          If GUID given is 0, OpenSM displays a list\n"
+          "          of possible port GUIDs and waits for user input.\n"
+          "          Without -g, OpenSM tries to use the default port.\n\n");
+  printf( "-l <LMC>\n"
+          "--lmc <LMC>\n"
+          "          This option specifies the subnet's LMC value.\n"
+          "          The number of LIDs assigned to each port is 2^LMC.\n"
+          "          The LMC value must be in the range 0-7.\n"
+          "          LMC values > 0 allow multiple paths between ports.\n"
+          "          LMC values > 0 should only be used if the subnet\n"
+          "          topology actually provides multiple paths between\n"
+          "          ports, i.e. multiple interconnects between switches.\n"
+          "          Without -l, OpenSM defaults to LMC = 0, which allows\n"
+          "          one path between any two ports.\n\n" );
+  printf( "-p <PRIORITY>\n"
+          "--priority <PRIORITY>\n"
+          "          This option specifies the SM's PRIORITY.\n"
+          "          This will effect the handover cases, where master\n"
+          "          is chosen by priority and GUID.\n\n" );
+  printf( "-smkey <SM_Key>\n"
+          "          This option specifies the SM's SM_Key (64 bits).\n"
+          "          This will effect SM authentication.\n\n" );
+  printf( "-r\n"
+          "--reassign_lids\n"
+          "          This option causes OpenSM to reassign LIDs to all\n"
+          "          end nodes. Specifying -r on a running subnet\n"
+          "          may disrupt subnet traffic.\n"
+          "          Without -r, OpenSM attempts to preserve existing\n"
+          "          LID assignments resolving multiple use of same LID.\n\n");
+  printf( "-R\n"
+          "--routing_engine <engine name>\n"
+          "          This option chooses routing engine instead of Min Hop\n"
+          "          algorithm (default). Supported engines: updn, file\n\n");
+  printf( "-U\n"
+          "--ucast_file <file name>\n"
+          "          This option specifies name of the unicast dump file\n"
+          "          from where switch forwarding tables will be loaded.\n\n");
+  printf ("-a\n"
+          "--add_guid_file <path to file>\n"
+          "          Set the root nodes for the Up/Down routing algorithm\n"
+          "          to the guids provided in the given file (one to a line)\n"
+          "\n");
+  printf( "-o\n"
+          "--once\n"
+          "          This option causes OpenSM to configure the subnet\n"
+          "          once, then exit.  Ports remain in the ACTIVE state.\n\n" );
+  printf( "-s <interval>\n"
+          "--sweep <interval>\n"
+          "          This option specifies the number of seconds between\n"
+          "          subnet sweeps.  Specifying -s 0 disables sweeping.\n"
+          "          Without -s, OpenSM defaults to a sweep interval of\n"
+          "          10 seconds.\n\n" );
+  printf( "-t <milliseconds>\n"
+          "--timeout <milliseconds>\n"
+          "          This option specifies the time in milliseconds\n"
+          "          used for transaction timeouts.\n"
+          "          Specifying -t 0 disables timeouts.\n"
+          "          Without -t, OpenSM defaults to a timeout value of\n"
+          "          200 milliseconds.\n\n" );
+  printf( "-maxsmps <number>\n"
+          "          This option specifies the number of VL15 SMP MADs\n"
+          "          allowed on the wire at any one time.\n"
+          "          Specifying -maxsmps 0 allows unlimited outstanding\n"
+          "          SMPs.\n"
+          "          Without -maxsmps, OpenSM defaults to a maximum of\n"
+          "          4 outstanding SMPs.\n\n" );
+  printf( "-i <equalize-ignore-guids-file>\n"
+          "-ignore-guids <equalize-ignore-guids-file>\n"
+          "          This option provides the means to define a set of ports\n"
+          "          (by guid) that will be ignored by the link load\n"
+          "          equalization algorithm.\n\n" );
+  printf( "-x\n"
+          "--honor_guid2lid\n"
+          "          This option forces OpenSM to honor the guid2lid file,\n"
+          "          when it comes out of Standby state, if such file exists\n"
+          "          under OSM_CACHE_DIR, and is valid. By default, this is FALSE.\n\n" );
+  printf( "-f\n"
+          "--log_file\n"
+          "          This option defines the log to be the given file.\n"
+          "          By default, the log goes to %temp%/log/osm.log.\n"
+          "          For the log to go to standard output use -f stdout.\n\n");
+  printf( "-e\n"
+          "--erase_log_file\n"
+          "          This option will cause deletion of the log file\n"
+          "          (if it previously exists). By default, the log file\n"
+          "          is accumulative.\n\n");
+  printf( "-P\n"
+          "--Pconfig\n"
+          "          This option defines the optional partition configuration file.\n"
+                        "          The default name is '%s'.\n\n", OSM_DEFAULT_PARTITION_CONFIG_FILE);
+  printf( "-Q\n"
+          "--no_qos\n"
+          "          This option disables QoS setup.\n\n");
+  printf( "-N\n"
+          "--no_part_enforce\n"
+          "          This option disables partition enforcement on switch external ports.\n\n");
+  printf( "-y\n"
+          "--stay_on_fatal\n"
+          "          This option will cause SM not to exit on fatal initialization\n"
+          "          issues: if SM discovers duplicated guids or 12x link with\n"
+          "          lane reversal badly configured.\n"
+          "          By default, the SM will exit on these errors.\n\n");
+  printf( "-v\n"
+          "--verbose\n"
+          "          This option increases the log verbosity level.\n"
+          "          The -v option may be specified multiple times\n"
+          "          to further increase the verbosity level.\n"
+          "          See the -D option for more information about\n"
+          "          log verbosity.\n\n" );
+  printf( "-V\n"
+          "          This option sets the maximum verbosity level and\n"
+          "          forces log flushing.\n"
+          "          The -V is equivalent to '-D 0xFF -d 2'.\n"
+          "          See the -D option for more information about\n"
+          "          log verbosity.\n\n" );
+  printf( "-D <flags>\n"
+          "          This option sets the log verbosity level.\n"
+          "          A flags field must follow the -D option.\n"
+          "          A bit set/clear in the flags enables/disables a\n"
+          "          specific log level as follows:\n"
+          "          BIT    LOG LEVEL ENABLED\n"
+          "          ----   -----------------\n"
+          "          0x01 - ERROR (error messages)\n"
+          "          0x02 - INFO (basic messages, low volume)\n"
+          "          0x04 - VERBOSE (interesting stuff, moderate volume)\n"
+          "          0x08 - DEBUG (diagnostic, high volume)\n"
+          "          0x10 - FUNCS (function entry/exit, very high volume)\n"
+          "          0x20 - FRAMES (dumps all SMP and GMP frames)\n"
+          "          0x40 - ROUTING (dump FDB routing information)\n"
+          "          0x80 - currently unused.\n"
+          "          Without -D, OpenSM defaults to ERROR + INFO (0x3).\n"
+          "          Specifying -D 0 disables all messages.\n"
+          "          Specifying -D 0xFF enables all messages (see -V).\n"
+          "          High verbosity levels may require increasing\n"
+          "          the transaction timeout with the -t option.\n\n" );
+  printf( "-d <number>\n"
+          "--debug <number>\n"
+          "          This option specifies a debug option.\n"
+          "          These options are not normally needed.\n"
+          "          The number following -d selects the debug\n"
+          "          option to enable as follows:\n"
+          "          OPT   Description\n"
+          "          ---    -----------------\n"
+          "          -d0  - Ignore other SM nodes\n"
+          "          -d1  - Force single threaded dispatching\n"
+          "          -d2  - Force log flushing after each log message\n"
+          "          -d3  - Disable multicast support\n"
+          "          -d10 - Put OpenSM in testability mode\n"
+          "          Without -d, no debug options are enabled\n\n" );
+  printf( "-h\n"
+          "--help\n"
+          "          Display this usage info then exit.\n\n" );
+  printf( "-?\n"
+          "          Display this usage info then exit.\n\n" );
+  fflush( stdout );
+  osm_exit_flag = TRUE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void show_menu(void);
+
+void
+show_menu(void)
+{
+  printf("\n------- Interactive Menu -------\n");
+  printf("X - Exit.\n\n");
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_net64_t
+get_port_guid(
+  IN osm_opensm_t *p_osm, uint64_t port_guid,
+  IN boolean_t is_service)
+{
+  uint32_t i;
+  uint32_t choice = 0;
+  char junk[128];
+  boolean_t done_flag = FALSE;
+  ib_api_status_t status;
+  uint32_t num_ports = GUID_ARRAY_SIZE;
+  ib_port_attr_t attr_array[GUID_ARRAY_SIZE];
+  
+  /*
+    Call the transport layer for a list of local port
+    GUID values.
+  */
+  status = osm_vendor_get_all_port_attr( p_osm->p_vendor, attr_array, &num_ports );
+  if( status != IB_SUCCESS )
+  {
+    printf( "\nError from osm_vendor_get_all_port_attr (%x)\n", status);
+    return( 0 );
+  }
+
+  /* if num_ports is 0 - return 0 */
+  if( num_ports == 0 )
+  {
+    printf( "\nNo local ports detected!\n" );
+    return( 0 );
+  }
+  /* If num_ports is 1, then there is only one possible port to use. Use it. */
+  if ( num_ports == 1 )
+  {
+    printf("Using default GUID 0x%" PRIx64 "\n", cl_hton64(attr_array[0].port_guid));
+    return( attr_array[0].port_guid );
+  }
+
+#if defined ( OSM_VENDOR_INTF_OPENIB )
+  /* If port_guid is 0, and this is gen2 - use the default port whose info is in attr_array[0] */
+  if ( port_guid == 0 )
+  {
+    printf("Using default GUID 0x%" PRIx64 "\n", cl_hton64(attr_array[0].port_guid));
+    return( attr_array[0].port_guid );
+  }
+#endif /* OSM_VENDOR_INTF_OPENIB */
+
+  /* If port_guid is 0, and we are in windows - find the first port with link_state != DOWN and
+     use it as default port. */
+  if ( port_guid == 0 )
+  {
+    for ( i = 0; i < num_ports; i++ )
+    {
+      if (attr_array[i].link_state > IB_LINK_DOWN)
+      {
+        /* Use this port */
+        printf("Using default guid 0x%" PRIx64 "\n", cl_hton64(attr_array[i].port_guid));
+        return( attr_array[i].port_guid );
+      }
+    }
+    /* If we are running as a service, and all ports are doen we return the 
+       first port (we can't open a window, as a service)*/
+       if (is_service) {
+         return( attr_array[0].port_guid );
+       }
+  }
+
+  /* More than one possible port - list all ports and let the user to choose. */
+  while( done_flag == FALSE )
+  {
+    printf( "\nChoose a local port number with which to bind:\n\n" );
+    /* If this is gen2 code - then port 0 has details of the default port used. 
+       no need to print it.
+       If this is not gen2 code - need to print details of all ports. */
+#if defined ( OSM_VENDOR_INTF_OPENIB )
+    for( i = 1; i < num_ports; i++ )
+    {
+      printf("\t%u: GUID = 0x%8" PRIx64 ", lid = 0x%04X, state = %s\n",
+             i, cl_ntoh64( attr_array[i].port_guid ),
+             attr_array[i].lid,
+             ib_get_port_state_str( attr_array[i].link_state ) );
+    }
+    printf( "\nEnter choice (1-%u): ", i-1 );
+# else
+    for( i = 0; i < num_ports; i++ )
+    {
+      /*
+        Print the index + 1 since by convention, port numbers
+        start with 1 on host channel adapters.
+      */
+
+      printf("\t%u: GUID = 0x%8" PRIx64 ", lid = 0x%04X, state = %s\n",
+             i+1, cl_ntoh64( attr_array[i].port_guid ),
+             attr_array[i].lid,
+             ib_get_port_state_str( attr_array[i].link_state ) );
+    }
+    printf( "\nEnter choice (1-%u): ", i );
+#endif /* OSM_VENDOR_INTF_OPENIB */
+
+    fflush( stdout );
+    if (scanf( "%u", &choice ))
+    {
+      /* If gen2 code - choice can be between 1 to num_ports-1
+         if not gen2 code - choice can be between 1 to num_ports */
+#if defined ( OSM_VENDOR_INTF_OPENIB )
+      if( choice >= num_ports )
+# else
+      if( choice > num_ports || choice < 1 )
+#endif /* OSM_VENDOR_INTF_OPENIB */
+      {
+        printf("\nError: Lame choice!\n");
+        fflush( stdin );
+      }
+      else
+      {
+        done_flag = TRUE;
+      }
+    }
+    else
+    {
+      /* get rid of the junk in the selection line */
+      scanf( "%s", junk );
+      printf("\nError: Lame choice!\n"); 
+      fflush( stdin );
+    }
+  }
+#if defined ( OSM_VENDOR_INTF_OPENIB )
+  printf("Choice guid=0x%8" PRIx64 "\n", cl_ntoh64( attr_array[choice].port_guid ));       
+  return( attr_array[choice].port_guid );
+# else
+  return( attr_array[choice - 1].port_guid );
+#endif /* OSM_VENDOR_INTF_OPENIB */
+}
+
+/**********************************************************************
+ **********************************************************************/
+#define OSM_MAX_IGNORE_GUID_LINES_LEN 128
+int
+parse_ignore_guids_file(IN char *guids_file_name,
+                        IN osm_opensm_t *p_osm)
+{
+  FILE *fh;
+  char line[OSM_MAX_IGNORE_GUID_LINES_LEN];
+  char *p_c, *p_ec;
+  uint32_t line_num = 0;
+  uint64_t port_guid;
+  ib_api_status_t status = IB_SUCCESS;
+  unsigned int  port_num;
+
+  OSM_LOG_ENTER( &p_osm->log, parse_ignore_guids_file );
+
+  fh = fopen( guids_file_name, "r" );
+  if( fh == NULL )
+  {
+    osm_log( &p_osm->log, OSM_LOG_ERROR,
+             "parse_ignore_guids_file: ERR 0601: "
+             "Unable to open ignore guids file (%s)\n" );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /*
+   * Parse the file and add to the ignore guids map.
+   */
+  while( fgets( line, OSM_MAX_IGNORE_GUID_LINES_LEN, fh ) != NULL )
+  {
+    line_num++;
+    p_c = line;
+    while ( (*p_c == ' ') && (*p_c != '\0')) p_c++ ;
+    port_guid = cl_hton64( strtoull( p_c, &p_ec, 16 ) );
+    if (p_ec == p_c)
+    {
+      osm_log( &p_osm->log, OSM_LOG_ERROR,
+               "parse_ignore_guids_file: ERR 0602: "
+               "Error in line (%u): %s\n" ,
+               line_num, line
+               );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+    while ( (*p_ec == ' ') && (*p_ec != '\0')) p_ec++ ;
+    if (! sscanf(p_ec, "%d", &port_num))
+    {
+      osm_log( &p_osm->log, OSM_LOG_ERROR,
+               "parse_ignore_guids_file: ERR 0603: "
+               "Error in line (%u): %s\n" ,
+               line_num, p_ec
+               );
+      status = IB_ERROR;
+      goto Exit;
+    }
+    /* Make sure the port_num isn't greater than 256 */
+    if (port_num > 256)
+    {
+      osm_log( &p_osm->log, OSM_LOG_ERROR,
+               "parse_ignore_guids_file: ERR 0604: "
+               "Error in line (%u): %s. "
+               "port number is greater than 256 (%d) \n",
+               line_num, p_ec, port_num
+               );
+      status = IB_ERROR;
+      goto Exit;
+    }
+    /* ok insert it */
+    osm_port_prof_set_ignored_port(&p_osm->subn, port_guid, (uint8_t)port_num);
+    osm_log( &p_osm->log, OSM_LOG_DEBUG,
+             "parse_ignore_guids_file: "
+             "Inserted Port: 0x%" PRIx64 " into ignored guids list\n" ,
+             port_guid
+             );
+
+  }
+
+  fclose( fh );
+
+ Exit:
+  OSM_LOG_EXIT( &p_osm->log );
+  return ( status );
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+int 
+opensm_main(
+  void *osm_main_args)
+{
+  int                   argc = ((osm_main_args_t*)osm_main_args)->argc;
+  char**                 argv = ((osm_main_args_t*)osm_main_args)->argv;
+  osm_subn_opt_t        opt;
+  ib_net64_t            sm_key = 0;
+  ib_api_status_t       status;
+  uint32_t              log_flags = OSM_LOG_DEFAULT_LEVEL;
+  int long              temp;
+  uint32_t              dbg_lvl;
+  boolean_t             run_once_flag = FALSE;
+  boolean_t             mem_track = FALSE;
+  uint32_t              next_option;
+  uint32_t                 exitTimeout;
+  boolean_t             cache_options = FALSE;
+  char                 *ignore_guids_file_name = NULL;
+  uint32_t              val;
+  const char * const    short_option = "i:f:ed:g:l:L:s:t:a:R:U:P:NQvVhorcyx";
+
+
+  /*
+    In the array below, the 2nd parameter specified the number
+    of arguments as follows:
+    0: no arguments
+    1: argument
+    2: optional
+  */
+  const struct option long_option[] =
+    {
+      {  "service",         0, NULL, 'Z'},
+      {  "debug",                1, NULL, 'd'},
+      {  "guid",          1, NULL, 'g'},
+      {  "ignore_guids",  1, NULL, 'i'},
+      {  "lmc",           1, NULL, 'l'},
+      {  "sweep",         1, NULL, 's'},
+      {  "timeout",       1, NULL, 't'},
+      {  "verbose",       0, NULL, 'v'},
+      {  "D",             1, NULL, 'D'},
+      {  "log_file",      1, NULL, 'f'},
+      {  "log_limit",     1, NULL, 'L'},
+      {  "erase_log_file",0, NULL, 'e'},
+      {  "Pconfig",       1, NULL, 'P'},
+      {  "no_part_enforce",0,NULL, 'N'},
+      {  "no_qos",        0, NULL, 'Q'},
+      {  "maxsmps",       1, NULL, 'n'},
+      {  "console",       0, NULL, 'q'},
+      {  "V",             0, NULL, 'V'},
+      {  "help",          0, NULL, 'h'},
+      {  "once",          0, NULL, 'o'},
+      {  "reassign_lids", 0, NULL, 'r'},
+      {  "priority",      1, NULL, 'p'},
+      {  "smkey",         1, NULL, 'k'},
+      {  "routing_engine",1, NULL, 'R'},
+      {  "ucast_file"    ,1, NULL, 'U'},
+      {  "add_guid_file", 1, NULL, 'a'},
+      {  "cache-options", 0, NULL, 'c'},
+      {  "stay_on_fatal", 0, NULL, 'y'},
+      {  "honor_guid2lid", 0, NULL, 'x'},
+      {  NULL,            0, NULL,  0 }  /* Required at the end of the array */
+    };
+  printf("-------------------------------------------------\n");
+  printf("%s\n", OSM_VERSION);
+
+  osm_subn_set_default_opt(&opt);
+  osm_subn_parse_conf_file(&opt);
+
+  printf("Command Line Arguments:\n");
+  do
+  {
+    next_option = getopt_long_only(argc, argv, short_option,
+                                   long_option, NULL);
+    switch(next_option)
+    {
+       case 'Z':
+       /*
+         service option - nothing to do
+       */
+       break;
+       
+       case 'o':
+      /*
+        Run once option.
+      */
+      run_once_flag = TRUE;
+      printf(" Run Once\n");
+      break;
+
+    case 'r':
+      /*
+        Reassign LIDs subnet option.
+      */
+      opt.reassign_lids = TRUE;
+      printf(" Reassign LIDs\n");
+      break;
+
+    case 'i':
+      /*
+        Specifies ignore guids file.
+      */
+      ignore_guids_file_name = optarg;
+      printf(" Ignore Guids File = %s\n", ignore_guids_file_name);
+      break;
+
+    case 'g':
+      /*
+        Specifies port guid with which to bind.
+      */
+      opt.guid = cl_hton64( strtoull( optarg, NULL, 16 ));
+      if (! opt.guid)
+      {
+        /* If guid is 0 - need to display the guid list */
+        opt.guid = INVALID_GUID;
+      }
+      else
+        printf(" Guid <0x%"PRIx64">\n", cl_hton64( opt.guid ));
+      break;
+
+    case 's':
+      val = strtol(optarg, NULL, 0);
+      /* Check that the number is not too large */
+      if ( ((uint32_t)(val * 1000000)) / 1000000 != val )
+        fprintf(stderr, "ERROR: sweep interval given is too large. Ignoring it.\n");
+      else
+      {
+        opt.sweep_interval = val;
+        printf(" sweep interval = %d\n", opt.sweep_interval);
+      }
+      break;
+
+    case 't':
+      opt.transaction_timeout = strtol(optarg, NULL, 0);
+      printf(" Transaction timeout = %d\n", opt.transaction_timeout);
+      break;
+
+    case 'n':
+      opt.max_wire_smps = strtol(optarg, NULL, 0);
+      if( opt.max_wire_smps <= 0 )
+        opt.max_wire_smps = 0x7FFFFFFF;
+      printf(" Max wire smp's = %d\n", opt.max_wire_smps);
+      break;
+
+    case 'q':
+      /*
+       * OpenSM interactive console
+       */
+      opt.console = TRUE;
+      printf(" Enabling OpenSM interactive console\n");
+      break;
+
+    case 'd':
+      dbg_lvl = strtol(optarg, NULL, 0);
+      printf(" d level = 0x%x\n", dbg_lvl);
+      if (dbg_lvl == 0)
+      {
+        printf(" Debug mode: Ignore Other SMs\n");
+        opt.ignore_other_sm = TRUE;
+      }
+      else if(dbg_lvl == 1)
+      {
+        printf(" Debug mode: Forcing Single Thread\n");
+        opt.single_thread = TRUE;
+      }
+      else if(dbg_lvl == 2)
+      {
+        printf(" Debug mode: Force Log Flush\n");
+        opt.force_log_flush = TRUE;
+      }
+      else if(dbg_lvl == 3)
+      {
+        printf(" Debug mode: Disable multicast support\n");
+        opt.disable_multicast = TRUE;
+      }
+      /*
+       * NOTE: Debug level 4 used to be used for memory tracking
+       * but this is now deprecated
+       */
+      else if(dbg_lvl >= 10)
+      {
+        /* Please look at osm_subnet.h for list of testability modes. */
+        opt.testability_mode = dbg_lvl - 9;
+      }
+      else
+        printf(   " OpenSM: Unknown debug option %d ignored\n",
+                  dbg_lvl );
+      break;
+
+    case 'l':
+      temp = strtol(optarg, NULL, 0);
+      if( temp > 7 )
+      {
+        fprintf(stderr, "ERROR: LMC must be 7 or less.");
+        return( -1 );
+      }
+      opt.lmc = (uint8_t)temp;
+      printf(" LMC = %d\n", temp);
+      break;
+
+    case 'D':
+      log_flags = strtol(optarg, NULL, 0);
+      printf(" verbose option -D = 0x%x\n", log_flags);
+      break;
+
+    case 'f':
+      if (!strcmp(optarg, "stdout"))
+        /* output should be to standard output */
+        opt.log_file = NULL;
+      else
+        opt.log_file = optarg;
+      break;
+
+    case 'L':
+      opt.log_max_size = strtoul(optarg, NULL, 0) * (1024*1024);
+      printf(" Log file max size is %lu bytes\n", opt.log_max_size);
+      break;
+
+    case 'e':
+      opt.accum_log_file = FALSE;
+      printf(" Creating new log file\n");
+      break;
+
+    case 'P':
+      opt.partition_config_file = optarg;
+      break;
+
+    case 'N':
+      opt.no_partition_enforcement = TRUE;
+      break;
+
+    case 'Q':
+      opt.no_qos = TRUE;
+      break;
+
+    case 'y':
+      opt.exit_on_fatal = FALSE;
+      printf(" Staying on fatal initialization errors\n");
+      break;
+
+    case 'v':
+      log_flags = (log_flags <<1 )|1;
+      printf(" Verbose option -v (log flags = 0x%X)\n", log_flags );
+      break;
+
+    case 'V':
+      log_flags = 0xFFFFFFFF;
+      opt.force_log_flush = TRUE;
+      printf(" Big V selected\n");
+      break;
+
+    case 'p':
+      temp = strtol(optarg, NULL, 0);
+      if (0 > temp || 15 < temp) {
+        fprintf(stderr, "ERROR: priority must be between 0 and 15\n");
+        return (-1);
+      }
+      opt.sm_priority = (uint8_t)temp;
+      printf(" Priority = %d\n", temp);
+      break;
+
+    case 'k':
+      sm_key = cl_hton64( strtoull( optarg, NULL, 16 ));
+      printf(" SM Key <0x%"PRIx64">\n", cl_hton64( sm_key ));
+      opt.sm_key = sm_key;
+      break;
+
+    case 'R':
+      opt.routing_engine_name = optarg;
+      printf(" Activate \'%s\' routing engine\n", optarg);
+      break;
+
+    case 'U':
+      opt.ucast_dump_file = optarg;
+      printf(" Ucast dump file is \'%s\'\n", optarg);
+      break;
+
+    case 'a':
+      /*
+        Specifies port guids file
+      */
+      opt.updn_guid_file = optarg;
+      printf (" UPDN Guid File: %s\n", opt.updn_guid_file );
+      break;
+
+    case 'c':
+      cache_options = TRUE;
+      printf (" Caching command line options\n");
+      break;
+
+    case 'x':
+      opt.honor_guid2lid_file = TRUE;
+      printf (" Honor guid2lid file, if possible\n");
+      break;
+
+    case 'h':
+    case '?':
+    case ':':
+      show_usage();
+      return 0;
+      break;
+
+    case -1:
+      break; /* done with option */
+    default: /* something wrong */
+      abort();
+    }
+  }
+  while(next_option != -1);
+
+  if (opt.log_file != NULL )
+    printf(" Log File: %s\n", opt.log_file );
+  /* Done with options description */
+  printf("-------------------------------------------------\n");
+
+  opt.log_flags = (uint8_t)log_flags;
+
+  status = osm_opensm_init( &osm, &opt );
+  if( status != IB_SUCCESS )
+  {
+    char      buffer[LOG_ENTRY_SIZE_MAX];
+    const char *err_str = ib_get_err_str( status );
+    if (err_str == NULL)
+    {
+      err_str = "Unknown Error Type";
+    }
+    printf( "\nError from osm_opensm_init: %s.\n",
+            err_str);
+    sprintf(buffer, "Error from osm_opensm_init: %s. See opensm log file for more details", err_str);
+    /* We will just exit, and not go to Exit, since we don't
+       want the destroy to be called. */
+    cl_log_event("OpenSM", LOG_ERR, buffer , NULL, 0);
+    g_service_state = SERVICE_STATE_START_FAILED;
+    return( status );
+  }
+
+  /*
+    If the user didn't specify a GUID on the command line,
+    then get a port GUID value with which to bind.
+  */
+  if( opt.guid == 0 || cl_hton64(opt.guid) == CL_HTON64(INVALID_GUID))
+    opt.guid = get_port_guid( &osm, opt.guid, ((osm_main_args_t*)osm_main_args)->is_service );
+
+  if ( opt.guid == 0 )
+  {
+    printf( "Error: Could not get port guid \n" );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  if ( cache_options == TRUE )
+    osm_subn_write_conf_file( &opt );
+
+  status = osm_opensm_bind( &osm, opt.guid );
+  if( status != IB_SUCCESS )
+  {
+    printf( "\nError from osm_opensm_bind (0x%X)\n", status );
+    goto Exit;
+  }
+
+  /*
+   * Define some port guids to ignore during path equalization
+   */
+  if (ignore_guids_file_name != NULL)
+  {
+    status = parse_ignore_guids_file(ignore_guids_file_name, &osm);
+    if( status != IB_SUCCESS )
+    {
+      printf( "\nError from parse_ignore_guids_file (0x%X)\n", status );
+      goto Exit;
+    }
+  }
+
+  osm_opensm_sweep( &osm );
+
+  status = osm_opensm_wait_for_subnet_up(
+      &osm, EVENT_NO_TIMEOUT, TRUE );
+
+  if( status != CL_SUCCESS )
+  {
+    printf( "\nError from osm_opensm_wait_for_subnet_up (0x%X)\n", status );
+    goto Exit;
+  }
+
+  if( run_once_flag == FALSE )
+  {
+    /*
+      Sit here forever
+      In the future, some sort of console interactivity could
+      be implemented in this loop.
+    */
+      WaitForSingleObject(osm_exit_event, INFINITE);
+      osm_exit_flag = TRUE;
+  }
+
+  /* wait for all transactions to end */
+  CL_ASSERT( ((opt.polling_retry_number + 1) * opt.transaction_timeout / 1000.0) < 0x100000000ULL ); 
+  exitTimeout = 
+     (uint32_t) ((opt.polling_retry_number + 1) * opt.transaction_timeout / 1000.0);
+
+  if (exitTimeout < 3) exitTimeout = 3;
+
+  /*
+    printf( "\n------- OpenSM Exiting (in %u seconds) -------\n",
+    exitTimeout);
+    sleep(exitTimeout); 
+  */
+
+  if (osm.mad_pool.mads_out)
+    fprintf(stdout, 
+            "There are still %u MADs out. Forcing the exit of the OpenSM application...\n",
+            osm.mad_pool.mads_out);
+
+ Exit:
+  g_service_state = SERVICE_STATE_START_FAILED;
+  osm_opensm_destroy( &osm );
+
+  exit( 0 );
+}
+
+SERVICE_STATUS          OsmServiceStatus; 
+SERVICE_STATUS_HANDLE   OsmServiceStatusHandle; 
+
+VOID SvcDebugOut(LPSTR String, DWORD Status);
+VOID  WINAPI OsmServiceCtrlHandler (DWORD opcode); 
+__stdcall OsmServiceStart (DWORD argc, LPTSTR *argv);
+
+DWORD OsmServiceInitialization (DWORD argc, LPTSTR *argv, 
+        DWORD *specificError); 
+
+int __cdecl
+main (
+  int                   argc,
+  char*                 argv[] )
+{
+  int i;
+  boolean_t run_as_service = FALSE;
+  osm_main_args.argc = argc;
+  osm_main_args.argv = argv;
+  /* If there are arguments that the executable is ran with, then this is 
+     not running as service - just run the opensm_main. */
+  for (i = 0 ; i< argc ; i++)
+    if (!strcmp(argv[i], "--service"))
+    {
+      run_as_service = TRUE;
+      osm_main_args.is_service = TRUE;
+      break;
+    }
+    osm_exit_event = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if(osm_exit_event == NULL)
+    {
+      printf( "\nCreateEvent failed gle=%d\n", GetLastError());
+      return( 1 );      
+    }
+
+  if (!run_as_service)
+  {
+    /* Running as executable */
+    osm_main_args.is_service = FALSE;
+    return opensm_main(&osm_main_args);
+  }
+  else
+  {
+    /* Running as service */
+     SERVICE_TABLE_ENTRY   DispatchTable[] =
+     {
+       { "OsmService", OsmServiceStart      }, 
+       { NULL,              NULL          } 
+     }; 
+     // Give older versions of opensm a chance to stop
+     Sleep(3000); 
+     if (!StartServiceCtrlDispatcher( DispatchTable)) 
+     { 
+       SvcDebugOut(" [OSM_SERVICE] StartServiceCtrlDispatcher (%d)\n", 
+                   GetLastError()); 
+     }
+  }
+}
+
+VOID SvcDebugOut(LPSTR String, DWORD Status) 
+{ 
+   CHAR  Buffer[1024]; 
+   if (strlen(String) < 1000) 
+   { 
+      sprintf(Buffer, String, Status); 
+      OutputDebugStringA(Buffer); 
+   } 
+}
+
+VOID WINAPI OsmServiceCtrlHandler (DWORD Opcode) 
+{ 
+   DWORD status; 
+   switch(Opcode) 
+   { 
+          case SERVICE_CONTROL_SHUTDOWN: 
+          case SERVICE_CONTROL_STOP: 
+      // Do whatever it takes to stop here. 
+         osm_exit_flag = TRUE;
+         SetEvent(osm_exit_event);
+         OsmServiceStatus.dwWin32ExitCode = 0; 
+         OsmServiceStatus.dwCurrentState  = SERVICE_STOPPED; 
+         OsmServiceStatus.dwCheckPoint    = 0; 
+         OsmServiceStatus.dwWaitHint      = 0; 
+
+         if (!SetServiceStatus (OsmServiceStatusHandle, 
+           &OsmServiceStatus))
+         { 
+            status = GetLastError(); 
+            SvcDebugOut(" [OSM_SERVICE] SetServiceStatus error %ld\n", 
+               status); 
+         } 
+         SvcDebugOut(" [OSM_SERVICE] Leaving OsmService \n",0); 
+         return; 
+      case SERVICE_CONTROL_INTERROGATE: 
+      // Fall through to send current status. 
+         break; 
+      default: 
+         SvcDebugOut(" [OSM_SERVICE] Unrecognized opcode %ld\n", 
+             Opcode); 
+   } 
+   // Send current status. 
+   if (!SetServiceStatus (OsmServiceStatusHandle,  &OsmServiceStatus)) 
+   { 
+      status = GetLastError(); 
+      SvcDebugOut(" [OSM_SERVICE] SetServiceStatus error %ld\n", 
+         status); 
+   } 
+   return; 
+}
+
+__stdcall  OsmServiceStart (DWORD argc, LPTSTR *argv) 
+{ 
+    DWORD status; 
+    DWORD specificError; 
+    OsmServiceStatus.dwServiceType        = SERVICE_WIN32; 
+    OsmServiceStatus.dwCurrentState       = SERVICE_START_PENDING; 
+    OsmServiceStatus.dwControlsAccepted   = SERVICE_ACCEPT_STOP | 
+        SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN; 
+    OsmServiceStatus.dwWin32ExitCode      = 0; 
+    OsmServiceStatus.dwServiceSpecificExitCode = 0; 
+    OsmServiceStatus.dwCheckPoint         = 0; 
+    OsmServiceStatus.dwWaitHint           = 2000; 
+
+    OsmServiceStatusHandle = RegisterServiceCtrlHandler( 
+        "OsmService", 
+        OsmServiceCtrlHandler); 
+    if (OsmServiceStatusHandle == (SERVICE_STATUS_HANDLE)0) 
+    { 
+        SvcDebugOut(" [OSM_SERVICE] RegisterServiceCtrlHandler failed %d\n", GetLastError()); 
+        return 0; 
+    } 
+
+    // Initialization code goes here. 
+    status = OsmServiceInitialization(argc,argv, &specificError); 
+    while (status == NO_ERROR && g_service_state == SERVICE_STATE_STARTING)
+    {
+        Sleep(1000);
+        OsmServiceStatus.dwCheckPoint++;
+        if (!SetServiceStatus (OsmServiceStatusHandle, &OsmServiceStatus)) 
+        { 
+          status = GetLastError(); 
+          SvcDebugOut(" [OSM_SERVICE] SetServiceStatus error %ld\n",status); 
+        } 
+
+    }
+    CL_ASSERT(g_service_state == SERVICE_STATE_STARTED_OK ||
+              g_service_state == SERVICE_STATE_START_FAILED ||
+              status != NO_ERROR);
+    // Handle error condition 
+    if (status != NO_ERROR || g_service_state == SERVICE_STATE_START_FAILED) 
+    { 
+        OsmServiceStatus.dwCurrentState       = SERVICE_STOPPED; 
+        OsmServiceStatus.dwCheckPoint         = 0; 
+        OsmServiceStatus.dwWaitHint           = 0; 
+        OsmServiceStatus.dwWin32ExitCode      = status; 
+        OsmServiceStatus.dwServiceSpecificExitCode = specificError; 
+        SetServiceStatus (OsmServiceStatusHandle, &OsmServiceStatus); 
+        return 0; 
+    } 
+    // Initialization complete - report running status. 
+    OsmServiceStatus.dwCurrentState       = SERVICE_RUNNING; 
+    OsmServiceStatus.dwCheckPoint         = 0; 
+    OsmServiceStatus.dwWaitHint           = 0; 
+    if (!SetServiceStatus (OsmServiceStatusHandle, &OsmServiceStatus)) 
+    { 
+        status = GetLastError(); 
+        SvcDebugOut(" [OSM_SERVICE] SetServiceStatus error %ld\n",status); 
+    } 
+    // This is where the service does its work. 
+    SvcDebugOut(" [OSM_SERVICE] Returning the Main Thread \n",0); 
+    return 1; 
+}
+// Stub initialization function. 
+DWORD OsmServiceInitialization(DWORD   argc, LPTSTR  *argv, 
+    DWORD *specificError) 
+{ 
+  if (CreateThread(NULL, 0, opensm_main, &osm_main_args, 0, NULL) == NULL)
+  {
+    SvcDebugOut(" [OSM_SERVICE] failed to create thread (%d)\n",
+                GetLastError());
+    return(1);
+  }
+  return(0); 
+}
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/opensm.opts b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/opensm.opts
new file mode 100644 (file)
index 0000000..122e151
--- /dev/null
@@ -0,0 +1,139 @@
+#\r
+# DEVICE ATTRIBUTES OPTIONS\r
+#\r
+# The port GUID on which the OpenSM is running.\r
+#guid <PORT GUID>\r
+\r
+# M_Key value sent to all ports qualifing all Set(PortInfo).\r
+#m_key 0x0000000000000000\r
+\r
+# The lease period used for the M_Key on this subnet in [msec]\r
+#m_key_lease_period 0\r
+\r
+# SM_Key value of the SM to qualify rcv SA queries as 'trusted'\r
+#sm_key 0x0100000000000000\r
+\r
+# Subnet prefix used on this subnet\r
+#subnet_prefix 0xfe80000000000000\r
+\r
+# The LMC value used on this subnet\r
+#lmc 0\r
+\r
+# The code of maximal time a packet can live in a switch\r
+# The actual time is 4.096usec * 2^<packet_life_time code>\r
+# The value 0x14 disables this mechanism\r
+#packet_life_time 0x12\r
+\r
+# The code of maximal time a packet can wait at the head of\r
+# transmission queue. \r
+# The actual time is 4.096usec * 2^<head_of_queue_lifetime>\r
+# The value 0x14 disables this mechanism\r
+#head_of_queue_lifetime 0x12\r
+\r
+# The maximal time a packet can wait at the head of queue on \r
+# switch port connected to a HCA\r
+#leaf_head_of_queue_lifetime 0x0c\r
+\r
+# Limit the maximal operational VLs\r
+#max_op_vls 5\r
+\r
+# The subnet_timeout code that will be set for all the ports\r
+# The actual timeout is 4.096usec * 2^<subnet_timeout code>\r
+#subnet_timeout 18\r
+\r
+# Threshold of local phy errors for sending Trap 129\r
+#local_phy_errors_threshold 0x08\r
+\r
+# Threshold of credits over-run errors for sending Trap 129\r
+#overrun_errors_threshold 0x08\r
+\r
+#\r
+# SWEEP OPTIONS\r
+#\r
+# The number of seconds between subnet sweeps (0 disables it)\r
+#sweep_interval 10\r
+\r
+# If TRUE cause all lids to be re-assigned\r
+#reassign_lids FALSE\r
+\r
+# If TRUE ignore existing LFT entries on first sweep (default).\r
+# Otherwise only non minimal hop cases are modified.\r
+# NOTE: A standby SM clears its first sweep flag - since the\r
+# master SM already sweeps...\r
+#reassign_lfts TRUE\r
+\r
+# If true forces every sweep to be a heavy sweep\r
+#force_heavy_sweep FALSE\r
+\r
+# If true every trap will cause a heavy sweep.\r
+# NOTE: successive same traps (>10) are supressed\r
+#sweep_on_trap TRUE\r
+\r
+#\r
+# ROUTING OPTIONS\r
+#\r
+# If true do not count switches as link subscriptions\r
+#port_profile_switch_nodes FALSE\r
+\r
+# Activate the Up/Down routing algorithm\r
+#updn_activate FALSE\r
+\r
+#\r
+# HANDOVER - MULTIPLE SM's OPTIONS\r
+#\r
+# SM priority used for deciding who is the master\r
+#sm_priority 1\r
+\r
+# If TRUE other SM's on the subnet should be ignored\r
+#ignore_other_sm FALSE\r
+\r
+# Timeout in [sec] between two polls of active master SM\r
+#sminfo_polling_timeout 10000\r
+\r
+# Number of failing polls of remote SM that declares it dead\r
+#polling_retry_number 4\r
+\r
+#\r
+# TIMING AND THREADING OPTIONS\r
+#\r
+# Number of MADs sent in parallel\r
+#max_wire_smps 4\r
+\r
+# The time taken to a transaction to finish in [msec]\r
+#transaction_timeout 200\r
+\r
+# Maximal time in [msec] a message can stay in the incoming message queue.\r
+# If there is more then one message in the queue and the last message\r
+# stayed in the queue more then this value any SA request will be \r
+# immediately returned with a BUSY status.\r
+#max_msg_fifo_timeout 10000\r
+\r
+# Use a single thread for handling SA queries\r
+#single_thread FALSE\r
+\r
+#\r
+# DEBUG FEATURES\r
+#\r
+# The log flags used\r
+#log_flags 0x03\r
+\r
+# Force flush of the log file after each log message\r
+#force_log_flush TRUE\r
+\r
+# Log file to be used\r
+#log_file <LOG_FILE>\r
+\r
+#accum_log_file TRUE\r
+\r
+# The directory to hold the file OpenSM dumps\r
+#dump_files_dir <DUMP_FILES_DIR>\r
+\r
+# If TRUE if OpenSM should disable multicast support\r
+#no_multicast_option FALSE\r
+\r
+# No multicast routing is performed if TRUE\r
+#disable_multicast FALSE\r
+\r
+# If TRUE opensm will exit on fatal initialization issues\r
+#exit_on_fatal TRUE\r
+\r
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/opensm.rc b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/opensm.rc
new file mode 100644 (file)
index 0000000..68e4faa
--- /dev/null
@@ -0,0 +1,46 @@
+/*\r
+ * Copyright (c) 2005 Mellanox Technologies.  All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: opensm.rc 2624 2009-12-07 18:06:48Z stansmith $\r
+ */\r
+\r
+\r
+#include <oib_ver.h>\r
+\r
+#define VER_FILETYPE                           VFT_APP\r
+#define VER_FILESUBTYPE                                VFT2_UNKNOWN\r
+#ifdef _DEBUG_\r
+#define VER_FILEDESCRIPTION_STR     "Debug OpenSM Subnet Manager (3.0.0)"\r
+#define VER_INTERNALNAME_STR        "opensm.exe"\r
+#define VER_ORIGINALFILENAME_STR    "opensm.exe"\r
+#else\r
+#define VER_FILEDESCRIPTION_STR     "OpenSM Subnet Manager (3.0.0)"\r
+#define VER_INTERNALNAME_STR        "opensm.exe"\r
+#define VER_ORIGINALFILENAME_STR    "opensm.exe"\r
+#endif\r
+#include <common.ver>\r
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm.mc b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm.mc
new file mode 100644 (file)
index 0000000..3030f71
--- /dev/null
@@ -0,0 +1,29 @@
+;/*++
+;=============================================================================
+;Copyright (c) 2005 Mellanox Technologies
+;
+;Module Name:
+;
+;    osm.mc
+;
+;Abstract:
+;
+;    OpenSM event log messages
+;
+;Authors:
+;
+;    Leonid Keller
+;
+;Environment:
+;
+;   Kernel Mode .
+;
+;=============================================================================
+;--*/
+;
+
+MessageId=0x0000 SymbolicName=EVENT_OSM_ANY_INFO
+Language=English
+%1
+.
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_console.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_console.c
new file mode 100644 (file)
index 0000000..45c16e1
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_console.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#define _GNU_SOURCE            /* for getline */
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/poll.h>
+#include <opensm/osm_console.h>
+
+#define OSM_COMMAND_LINE_LEN   120
+#define OSM_COMMAND_PROMPT     "$ "
+
+struct command {
+       char *name;
+       void (*help_function)(void);
+       void (*parse_function)(char **p_last, osm_opensm_t *p_osm);
+};
+
+static const struct command console_cmds[];
+
+static inline char *next_token(char **p_last)
+{
+       return strtok_r(NULL, " \t\n", p_last);
+}
+
+static void help_command()
+{
+       int i;
+
+       printf("Supported commands and syntax:\n");
+       printf("help [<command>]\n");
+       /* skip help command */
+       for (i = 1; console_cmds[i].name; i++)
+               console_cmds[i].help_function();
+}
+
+static void help_loglevel()
+{
+       printf("loglevel [<log-level>]\n");
+}
+
+static void help_priority()
+{
+       printf("priority [<sm-priority>]\n");
+}
+
+/* more help routines go here */
+
+static void help_parse(char **p_last, osm_opensm_t *p_osm)
+{
+       char *p_cmd;
+       int i, found = 0;
+
+       p_cmd = next_token(p_last);
+       if (!p_cmd)
+               help_command();
+       else {
+               for (i = 1; console_cmds[i].name; i++) {
+                       if (!strcmp(p_cmd, console_cmds[i].name)) {
+                               found = 1;
+                               console_cmds[i].help_function();
+                               break;
+                       }
+               }
+               if (!found) {
+                       printf("Command %s not found\n\n", p_cmd);
+                       help_command();
+               }
+       }
+}
+
+static void loglevel_parse(char **p_last, osm_opensm_t *p_osm)
+{
+       char *p_cmd;
+       int level;
+
+       p_cmd = next_token(p_last);
+       if (!p_cmd)
+               printf("Current log level is 0x%x\n", osm_log_get_level(&p_osm->log));
+       else {
+               /* Handle x, 0x, and decimal specification of log level */
+               if (!strncmp(p_cmd, "x", 1)) { 
+                       p_cmd++;
+                       level = strtoul(p_cmd, NULL, 16); 
+               } else {
+                       if (!strncmp(p_cmd, "0x", 2)) {
+                               p_cmd += 2;
+                               level = strtoul(p_cmd, NULL, 16); 
+                       } else
+                               level = strtol(p_cmd, NULL, 10);
+               }
+               if ((level >= 0) && (level < 256)) {
+                       printf("Setting log level to 0x%x\n", level);
+                       osm_log_set_level(&p_osm->log, level);
+               } else
+                       printf("Invalid log level 0x%x\n", level);
+       }
+}
+
+static void priority_parse(char **p_last, osm_opensm_t *p_osm)
+{
+       char *p_cmd;
+       int priority;
+
+       p_cmd = next_token(p_last);
+       if (!p_cmd)
+               printf("Current sm-priority is %d\n", p_osm->subn.opt.sm_priority);
+       else {
+               priority = strtol(p_cmd, NULL, 0);
+               if (0 > priority || 15 < priority)
+                       printf("Invalid sm-priority %d; must be between 0 and 15\n", priority);
+               else {
+                       printf("Setting sm-priority to %d\n", priority);
+                       p_osm->subn.opt.sm_priority = (uint8_t)priority;
+                       /* Does the SM state machine need a kick now ? */
+               }
+       }
+}
+
+/* more parse routines go here */
+
+static const struct command console_cmds[] =
+{
+       { "help",       &help_command,          &help_parse},
+       { "loglevel",   &help_loglevel,         &loglevel_parse},       
+       { "priority",   &help_priority,         &priority_parse},
+       { NULL,         NULL,                   NULL}   /* end of array */
+};
+
+static void parse_cmd_line(char *line, osm_opensm_t *p_osm)
+{
+       char *p_cmd, *p_last;
+       int i, found = 0;
+
+       /* find first token which is the command */
+       p_cmd = strtok_r(line, " \t\n", &p_last);
+       if (p_cmd) {
+               for (i = 0; console_cmds[i].name; i++) {
+                       if (!strcmp(p_cmd, console_cmds[i].name)) {
+                               found = 1;
+                               console_cmds[i].parse_function(&p_last, p_osm);
+                               break;
+                       }
+               }
+               if (!found) {
+                       printf("Command %s not found\n\n", p_cmd);
+                       help_command();
+               }
+       } else {
+               printf("Error parsing command line: %s\n", line);
+               return;
+       }
+}
+
+void osm_console_prompt(void)
+{
+       printf("%s", OSM_COMMAND_PROMPT);
+       fflush(stdout);
+}
+
+void osm_console(osm_opensm_t *p_osm)
+{
+       struct pollfd pollfd;
+       char *p_line;
+       size_t len;
+       ssize_t n;
+
+       pollfd.fd = 0;
+       pollfd.events = POLLIN;
+       pollfd.revents = 0;
+
+       if (poll(&pollfd, 1, 10000) <= 0)
+               return;
+
+       if (pollfd.revents|POLLIN) {
+               p_line = NULL;
+               /* Get input line */
+               n = getline(&p_line, &len, stdin);
+               if (n > 0) {
+                       /* Parse and act on input */
+                       parse_cmd_line(p_line, p_osm);
+                       free(p_line);
+               } else {
+                       printf("Input error\n");
+                       fflush(stdin);
+               }
+               osm_console_prompt();
+       }
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_db_files.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_db_files.c
new file mode 100644 (file)
index 0000000..ebbb307
--- /dev/null
@@ -0,0 +1,796 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_db_files.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implemntation of the osm_db interface using simple text files
+ *
+ * $Revision: 1.4 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <opensm/st.h>
+#include <opensm/osm_db.h>
+
+/****d* Database/OSM_DB_MAX_LINE_LEN
+ * NAME
+ * OSM_DB_MAX_LINE_LEN
+ *
+ * DESCRIPTION
+ * The Maximal line length allowed for the file
+ *
+ * SYNOPSIS
+ */
+#define OSM_DB_MAX_LINE_LEN 1024
+/**********/
+
+/****d* Database/OSM_DB_MAX_GUID_LEN
+ * NAME
+ * OSM_DB_MAX_GUID_LEN
+ *
+ * DESCRIPTION
+ * The Maximal word length allowed for the file (guid or lid)
+ *
+ * SYNOPSIS
+ */
+#define OSM_DB_MAX_GUID_LEN 32
+/**********/
+
+/****s* OpenSM: Database/osm_db_domain_imp
+ * NAME
+ * osm_db_domain_imp
+ *
+ * DESCRIPTION
+ * An implementation for domain of the database based on text files and
+ *  hash tables.
+ *
+ * SYNOPSIS
+ */
+typedef struct _osm_db_domain_imp {
+  char          *file_name;
+  st_table      *p_hash;
+  cl_spinlock_t lock;
+} osm_db_domain_imp_t;
+/*
+ * FIELDS
+ *
+ * SEE ALSO
+ * osm_db_domain_t
+ *********/
+
+/****s* OpenSM: Database/osm_db_imp_t
+ * NAME
+ * osm_db_imp_t
+ *
+ * DESCRIPTION
+ * An implementation for file based database
+ *
+ * SYNOPSIS
+ */
+typedef struct _osm_db_imp {
+  char      *db_dir_name;
+} osm_db_imp_t;
+/*
+ * FIELDS
+ *
+ * db_dir_name
+ *   The directory holding the database
+ *
+ * SEE ALSO
+ * osm_db_t
+ *********/
+
+/***************************************************************************
+ ***************************************************************************/
+void
+osm_db_construct(
+  IN osm_db_t* const p_db )
+{
+  memset(p_db, 0, sizeof(osm_db_t));
+  cl_list_construct( &p_db->domains );
+}
+
+/***************************************************************************
+ ***************************************************************************/
+void
+osm_db_domain_destroy(
+  IN osm_db_domain_t* const p_db_domain)
+{
+  osm_db_domain_imp_t *p_domain_imp;
+  p_domain_imp = (osm_db_domain_imp_t *)p_db_domain->p_domain_imp;
+
+  osm_db_clear( p_db_domain );
+
+  cl_spinlock_destroy( &p_domain_imp->lock );
+
+  st_free_table( p_domain_imp->p_hash );
+  free( p_domain_imp->file_name );
+  free( p_domain_imp );
+}
+
+/***************************************************************************
+ ***************************************************************************/
+void
+osm_db_destroy(
+  IN osm_db_t* const p_db )
+{
+  osm_db_domain_t   *p_domain;
+
+  while ((p_domain = cl_list_remove_head( &p_db->domains )) != NULL )
+  {
+    osm_db_domain_destroy( p_domain );
+    free( p_domain );
+  }
+  cl_list_destroy( &p_db->domains );
+  free( p_db->p_db_imp );
+}
+
+/***************************************************************************
+ ***************************************************************************/
+int
+osm_db_init(
+  IN osm_db_t* const p_db,
+  IN osm_log_t *p_log )
+{
+  osm_db_imp_t *p_db_imp;
+  struct stat  dstat;
+
+  OSM_LOG_ENTER( p_log, osm_db_init );
+
+  p_db_imp = (osm_db_imp_t *)malloc(sizeof(osm_db_imp_t));
+  CL_ASSERT( p_db_imp != NULL);
+
+  p_db_imp->db_dir_name = getenv("OSM_CACHE_DIR");
+  if (!p_db_imp->db_dir_name || !(*p_db_imp->db_dir_name))
+    p_db_imp->db_dir_name = OSM_DEFAULT_CACHE_DIR;
+
+  /* Create the directory if it doesn't exist */
+  /* There is a difference in creating directory between windows and linux */
+#ifdef __WIN__
+  /* Check if the directory exists. If not - create it. */
+  CreateDirectory(p_db_imp->db_dir_name, NULL);
+#else /* __WIN__ */  
+  /* make sure the directory exists */
+  if (lstat(p_db_imp->db_dir_name, &dstat))
+  {
+    if (mkdir(p_db_imp->db_dir_name, 0755))
+    {
+      osm_log( p_log, OSM_LOG_ERROR,
+               "osm_db_init: ERR 6101: "
+               " Failed to create the db directory:%s\n",
+               p_db_imp->db_dir_name);
+      OSM_LOG_EXIT( p_log );
+      return 1;
+    }
+  }
+#endif
+
+  p_db->p_log = p_log;
+  p_db->p_db_imp = (void*)p_db_imp;
+
+  cl_list_init( &p_db->domains, 5 );
+
+  OSM_LOG_EXIT( p_log );
+
+  return 0;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+osm_db_domain_t*
+osm_db_domain_init(
+  IN osm_db_t* const p_db,
+  IN char *domain_name)
+{
+  osm_db_domain_t     *p_domain;
+  osm_db_domain_imp_t *p_domain_imp;
+  int                  dir_name_len;
+  osm_log_t           *p_log = p_db->p_log;
+  FILE                *p_file;
+
+  OSM_LOG_ENTER( p_log, osm_db_domain_init );
+
+  /* allocate a new domain object */
+  p_domain = (osm_db_domain_t *)malloc(sizeof(osm_db_domain_t));
+  CL_ASSERT( p_domain != NULL );
+
+  p_domain_imp =
+    (osm_db_domain_imp_t *)malloc(sizeof(osm_db_domain_imp_t));
+  CL_ASSERT( p_domain_imp != NULL );
+
+  dir_name_len = strlen(((osm_db_imp_t*)p_db->p_db_imp)->db_dir_name);
+
+  /* set the domain file name */
+  p_domain_imp->file_name =
+    (char *)malloc(sizeof(char)*(dir_name_len) + strlen(domain_name) + 2);
+  CL_ASSERT(p_domain_imp->file_name != NULL);
+  strcpy(p_domain_imp->file_name,((osm_db_imp_t*)p_db->p_db_imp)->db_dir_name);
+  strcat(p_domain_imp->file_name,domain_name);
+
+  /* make sure the file exists - or exit if not writable */
+  p_file = fopen(p_domain_imp->file_name, "a+");
+  if (! p_file)
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_db_domain_init: ERR 6102: "
+             " Failed to open the db file:%s\n",
+             p_domain_imp->file_name);
+    free(p_domain_imp);
+    free(p_domain);
+    p_domain = NULL;
+    goto Exit;
+  }
+  fclose(p_file);
+
+  /* initialize the hash table object */
+  p_domain_imp->p_hash = st_init_strtable();
+  CL_ASSERT( p_domain_imp->p_hash != NULL );
+
+  p_domain->p_db = p_db;
+  cl_list_insert_tail( &p_db->domains, p_domain );
+  p_domain->p_domain_imp = p_domain_imp;
+  cl_spinlock_construct( &p_domain_imp->lock );
+  cl_spinlock_init( &p_domain_imp->lock );
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return p_domain;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+int
+osm_db_restore(
+  IN osm_db_domain_t *p_domain)
+{
+
+  osm_log_t           *p_log = p_domain->p_db->p_log;
+  osm_db_domain_imp_t *p_domain_imp =
+    (osm_db_domain_imp_t *)p_domain->p_domain_imp;
+  FILE                *p_file;
+  int                  status;
+  char                 sLine[OSM_DB_MAX_LINE_LEN];
+  boolean_t            before_key;
+  char                *p_first_word, *p_rest_of_line, *p_last;
+  char                *p_key = NULL;
+  char                *p_prev_val, *p_accum_val = NULL;
+  unsigned int         line_num;
+
+  OSM_LOG_ENTER( p_log, osm_db_restore );
+
+  /* take the lock on the domain */
+  cl_spinlock_acquire( &p_domain_imp->lock );
+
+  /* open the file - read mode */
+  p_file = fopen(p_domain_imp->file_name, "r");
+
+  if (! p_file)
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_db_restore: ERR 6103: "
+             " Failed to open the db file:%s\n",
+             p_domain_imp->file_name);
+    status = 1;
+    goto Exit;
+  }
+
+  /* parse the file allocating new hash tables as required */
+  /*
+     states:
+     before_key (0) -> in_key (1)
+
+     before_key: if a word on the first byte - it is the key. state=in_key
+     the rest of the line is start of the value.
+     in_key: unless the line is empty - add it (with newlines) to the value.
+     if empty: state=before_key
+  */
+  status = 0;
+  before_key = TRUE;
+  line_num = 0;
+  /* if we got to EOF in the middle of a key we add a last newline */
+  while (
+    (fgets(sLine, OSM_DB_MAX_LINE_LEN, p_file) != NULL) ||
+    ((before_key == FALSE) && strcpy(sLine,"\n"))
+    )
+  {
+    line_num++;
+    if (before_key)
+    {
+      if ((sLine[0] != ' ') && (sLine[0] != '\t') && (sLine[0] != '\n'))
+      {
+        /* we got a new key */
+        before_key = FALSE;
+
+        /* handle the key */
+        p_first_word = strtok_r(sLine, " \t\n", &p_last);
+        if (! p_first_word)
+        {
+          osm_log( p_log, OSM_LOG_ERROR,
+                   "osm_db_restore: ERR 6104: "
+                   " Failed to get key from line:%u : %s (file:%s)\n",
+                   line_num, sLine, p_domain_imp->file_name);
+          status = 1;
+          goto EndParsing;
+        }
+        if (strlen(p_first_word) > OSM_DB_MAX_GUID_LEN)
+        {
+          osm_log( p_log, OSM_LOG_ERROR,
+                   "osm_db_restore: ERR 610A: "
+                   " Illegal key from line:%u : %s (file:%s)\n",
+                   line_num, sLine, p_domain_imp->file_name);
+          status = 1;
+          goto EndParsing;
+        }
+
+        p_key = (char *)malloc(sizeof(char)*(strlen(p_first_word) + 1));
+        strcpy(p_key, p_first_word);
+
+        p_rest_of_line = strtok_r(NULL, "\n", &p_last);
+        if (p_rest_of_line != NULL)
+        {
+          p_accum_val =
+            (char*)malloc(sizeof(char)*(strlen(p_rest_of_line) + 1));
+          strcpy(p_accum_val, p_rest_of_line);
+        }
+        else
+        {
+          p_accum_val = (char*)malloc(2);
+          strcpy(p_accum_val, "\0");
+        }
+      }
+      else if (sLine[0] != '\n')
+      {
+        osm_log( p_log, OSM_LOG_ERROR,
+                 "osm_db_restore: ERR 6105: "
+                 " How did we get here? line:%u : %s (file:%s)\n",
+                 line_num, sLine, p_domain_imp->file_name);
+        status = 1;
+        goto EndParsing;
+      }
+    } /* before key */
+    else
+    {
+      /* we already have a key */
+
+      if (sLine[0] == '\n')
+      {
+        /* got an end of key */
+        before_key = TRUE;
+
+        /* make sure the key was not previously used */
+        if (st_lookup(p_domain_imp->p_hash,
+                      (st_data_t)p_key,
+                      (st_data_t*)&p_prev_val))
+        {
+          osm_log( p_log, OSM_LOG_ERROR,
+                   "osm_db_restore: ERR 6106: "
+                   " Key:%s already exists in:%s with value:%s."
+                   " Removing it\n",
+                   p_key,
+                   p_domain_imp->file_name,
+                   p_prev_val);
+        }
+        else
+        {
+          p_prev_val = NULL;
+        }
+
+        /* store our key and value */
+        st_insert(p_domain_imp->p_hash,
+                  (st_data_t)p_key, (st_data_t)p_accum_val);
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "osm_db_restore: "
+                 "Got key:%s value:%s\n", p_key, p_accum_val);
+      }
+      else
+      {
+        /* accumulate into the value */
+        p_prev_val = p_accum_val;
+        p_accum_val =
+          (char *)malloc(strlen(p_prev_val) + strlen(sLine) + 1);
+        strcpy(p_accum_val, p_prev_val);
+        free(p_prev_val);
+        strcat(p_accum_val, sLine);
+      }
+    } /* in key */
+  } /* while lines or last line */
+
+ EndParsing:
+  fclose(p_file);
+
+ Exit:
+  cl_spinlock_release( &p_domain_imp->lock );
+  OSM_LOG_EXIT( p_log );
+  return status;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+int
+__osm_dump_tbl_entry(st_data_t key, st_data_t val, st_data_t arg)
+{
+  FILE *p_file = (FILE*)arg;
+  char *p_key = (char*)key;
+  char *p_val = (char *)val;
+
+  fprintf(p_file, "%s %s\n\n", p_key, p_val);
+  return ST_CONTINUE;
+}
+
+int
+osm_db_store(
+  IN osm_db_domain_t *p_domain)
+{
+  osm_log_t           *p_log = p_domain->p_db->p_log;
+  osm_db_domain_imp_t *p_domain_imp;
+  FILE                *p_file;
+  int                  status = 0;
+  char                *p_tmp_file_name;
+
+  OSM_LOG_ENTER( p_log, osm_db_store );
+
+  p_domain_imp = (osm_db_domain_imp_t *)p_domain->p_domain_imp;
+  p_tmp_file_name =
+    (char *)malloc(sizeof(char)*(strlen(p_domain_imp->file_name)+8));
+  strcpy(p_tmp_file_name, p_domain_imp->file_name);
+  strcat(p_tmp_file_name,".tmp");
+
+  cl_spinlock_acquire( &p_domain_imp->lock );
+
+  /* open up the output file */
+  p_file = fopen(p_tmp_file_name, "w");
+  if (! p_file)
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_db_store: ERR 6107: "
+             " Failed to open the db file:%s for writing\n",
+             p_domain_imp->file_name);
+    status = 1;
+    goto Exit;
+  }
+
+  st_foreach(p_domain_imp->p_hash, __osm_dump_tbl_entry, (st_data_t)p_file);
+  fclose(p_file);
+
+  /* move the domain file */
+  status = remove(p_domain_imp->file_name);
+  if (status)
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_db_store: ERR 6109: "
+             " Failed to remove file:%s (err:%u)\n",
+             p_domain_imp->file_name, status);
+  }
+
+  status = rename(p_tmp_file_name, p_domain_imp->file_name);
+  if (status)
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_db_store: ERR 6108: "
+             " Failed to rename the db file to:%s (err:%u)\n",
+             p_domain_imp->file_name, status);
+  }
+ Exit:
+  cl_spinlock_release( &p_domain_imp->lock );
+  free(p_tmp_file_name);
+  OSM_LOG_EXIT( p_log );
+  return status;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+/* simply de-allocate the key and the value and return the code
+   that makes the st_foreach delete the entry */
+int
+__osm_clear_tbl_entry(st_data_t key, st_data_t val, st_data_t arg)
+{
+  free((char*)key);
+  free((char*)val);
+  return ST_DELETE;
+}
+
+int
+osm_db_clear(
+  IN osm_db_domain_t *p_domain)
+{
+  osm_db_domain_imp_t *p_domain_imp =
+    (osm_db_domain_imp_t *)p_domain->p_domain_imp;
+
+  cl_spinlock_acquire( &p_domain_imp->lock );
+  st_foreach(p_domain_imp->p_hash, __osm_clear_tbl_entry, (st_data_t)NULL);
+  cl_spinlock_release( &p_domain_imp->lock );
+
+  return 0;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+int
+__osm_get_key_of_tbl_entry(st_data_t key, st_data_t val, st_data_t arg)
+{
+  cl_list_t *p_list = (cl_list_t *)arg;
+  cl_list_insert_tail(p_list, (void*)key);
+  return ST_CONTINUE;
+}
+
+int
+osm_db_keys(
+  IN osm_db_domain_t *p_domain,
+  OUT cl_list_t* p_key_list)
+{
+  osm_db_domain_imp_t *p_domain_imp =
+    (osm_db_domain_imp_t *)p_domain->p_domain_imp;
+
+  cl_spinlock_acquire( &p_domain_imp->lock );
+
+  st_foreach(p_domain_imp->p_hash,
+             __osm_get_key_of_tbl_entry, (st_data_t)p_key_list);
+
+  cl_spinlock_release( &p_domain_imp->lock );
+
+  return 0;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+char *
+osm_db_lookup(
+  IN osm_db_domain_t *p_domain,
+  IN char *const p_key)
+{
+  osm_db_domain_imp_t *p_domain_imp =
+    (osm_db_domain_imp_t *)p_domain->p_domain_imp;
+  char *p_val = NULL;
+
+  cl_spinlock_acquire( &p_domain_imp->lock );
+
+  if (!st_lookup(p_domain_imp->p_hash, (st_data_t)p_key, (st_data_t*)&p_val))
+    p_val = NULL;
+
+  cl_spinlock_release( &p_domain_imp->lock );
+  return p_val;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+int
+osm_db_update(
+  IN osm_db_domain_t *p_domain,
+  IN char *const p_key,
+  IN char *const p_val)
+{
+  osm_log_t           *p_log = p_domain->p_db->p_log;
+  osm_db_domain_imp_t *p_domain_imp =
+    (osm_db_domain_imp_t *)p_domain->p_domain_imp;
+  char *p_prev_val = NULL;
+  char *p_new_key;
+  char *p_new_val;
+
+  cl_spinlock_acquire( &p_domain_imp->lock );
+
+  if (st_lookup(p_domain_imp->p_hash,
+                (st_data_t)p_key, (st_data_t*)&p_prev_val))
+  {
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osm_db_update: "
+             " Key:%s previously exists in:%s with value:%s\n",
+             p_key,
+             p_domain_imp->file_name,
+             p_prev_val);
+    p_new_key = p_key;
+  }
+  else
+  {
+    /* need to allocate the key */
+    p_new_key = malloc(sizeof(char)*(strlen(p_key) + 1));
+    strcpy(p_new_key, p_key);
+  }
+
+  /* need to arange a new copy of the  value */
+  p_new_val = malloc(sizeof(char)*(strlen(p_val) + 1));
+  strcpy(p_new_val, p_val);
+
+  st_insert(p_domain_imp->p_hash, (st_data_t)p_new_key, (st_data_t)p_new_val);
+
+  if (p_prev_val)
+    free(p_prev_val);
+
+  cl_spinlock_release( &p_domain_imp->lock );
+
+  return 0;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+int
+osm_db_delete(
+  IN osm_db_domain_t *p_domain,
+  IN char *const p_key)
+{
+  osm_log_t           *p_log = p_domain->p_db->p_log;
+  osm_db_domain_imp_t *p_domain_imp =
+    (osm_db_domain_imp_t *)p_domain->p_domain_imp;
+  char *p_prev_val = NULL;
+  int res;
+
+  OSM_LOG_ENTER( p_log, osm_db_delete );
+
+  cl_spinlock_acquire( &p_domain_imp->lock );
+  if (st_delete(p_domain_imp->p_hash,
+                (st_data_t*)&p_key, (st_data_t*)&p_prev_val))
+  {
+    if (st_lookup(p_domain_imp->p_hash,
+                  (st_data_t)p_key, (st_data_t*)&p_prev_val))
+    {
+      osm_log( p_log, OSM_LOG_ERROR,
+               "osm_db_delete: "
+               " key:%s still exists in:%s with value:%s\n",
+               p_key,
+               p_domain_imp->file_name,
+               p_prev_val);
+      res = 1;
+    }
+    else
+    {
+      free(p_key);
+      free(p_prev_val);
+      res = 0;
+    }
+  }
+  else
+  {
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osm_db_update: "
+             " fail to find key:%s. delete failed\n",
+             p_key);
+    res = 1;
+  }
+  cl_spinlock_release( &p_domain_imp->lock );
+
+  OSM_LOG_EXIT( p_log );
+  return res;
+}
+
+#ifdef TEST_OSMDB
+#include <stdlib.h>
+#include <math.h>
+
+int
+main(int argc, char **argv)
+{
+  osm_db_t db;
+  osm_log_t log;
+  osm_db_domain_t *p_dbd;
+  cl_list_t keys;
+  cl_list_iterator_t kI;
+  char *p_key;
+  char *p_val;
+  int i;
+
+  cl_list_construct( &keys );
+  cl_list_init( &keys, 10 );
+
+  osm_log_init_v2( &log, TRUE, 0xff, "/var/log/osm_db_test.log", 0, FALSE);
+
+  osm_db_construct(&db);
+  if (osm_db_init(&db, &log))
+  {
+    printf("db init failed\n");
+    exit(1);
+  }
+
+  p_dbd = osm_db_domain_init(&db, "lid_by_guid");
+
+  if (osm_db_restore(p_dbd))
+  {
+    printf("failed to restore\n");
+  }
+
+  if (osm_db_keys(p_dbd, &keys))
+  {
+    printf("failed to get keys\n");
+  }
+  else
+  {
+    kI = cl_list_head( &keys );
+    while (kI != cl_list_end( & keys ))
+    {
+      p_key = cl_list_obj(kI);
+      kI = cl_list_next( kI );
+
+      p_val = osm_db_lookup(p_dbd, p_key);
+      printf("key = %s val = %s\n", p_key, p_val);
+    }
+  }
+
+  cl_list_remove_all(&keys);
+
+  /* randomly add and remove numbers */
+  for (i =  0; i < 10; i++)
+  {
+    int k;
+    float v;
+    int is_add;
+    char val_buf[16];
+    char key_buf[16];
+
+    k = floor(1.0 * rand()/ RAND_MAX * 100);
+    v = rand();
+    sprintf(key_buf, "%u", k);
+    sprintf(val_buf, "%u", v);
+
+    is_add = (rand() < RAND_MAX/ 2);
+
+    if (is_add)
+    {
+      osm_db_update(p_dbd, key_buf, val_buf);
+    }
+    else
+    {
+      osm_db_delete(p_dbd, key_buf);
+    }
+  }
+  if (osm_db_keys(p_dbd, &keys))
+  {
+    printf("failed to get keys\n");
+  }
+  else
+  {
+    kI = cl_list_head( &keys );
+    while (kI != cl_list_end( & keys ))
+    {
+      p_key = cl_list_obj(kI);
+      kI = cl_list_next( kI );
+
+      p_val = osm_db_lookup(p_dbd, p_key);
+      printf("key = %s val = %s\n", p_key, p_val);
+    }
+  }
+  if (osm_db_store(p_dbd))
+    printf("failed to store\n");
+
+  osm_db_destroy( &db );
+  cl_list_destroy( &keys );
+}
+#endif
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_db_pack.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_db_pack.c
new file mode 100644 (file)
index 0000000..29450e8
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_db_pack.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_db_pack.h>
+
+static inline void
+__osm_pack_guid(uint64_t guid, char *p_guid_str)
+{
+  sprintf(p_guid_str, "0x%016" PRIx64, guid);
+}
+
+static inline uint64_t 
+__osm_unpack_guid(char *p_guid_str)
+{
+#if __WORDSIZE == 64
+  return (strtoul(p_guid_str, NULL, 0));
+#else
+  return (strtoull(p_guid_str, NULL, 0));
+#endif
+}
+
+static inline void
+__osm_pack_lids(uint16_t min_lid, uint16_t max_lid, char *p_lid_str)
+{
+  sprintf(p_lid_str, "0x%04x 0x%04x", min_lid, max_lid);
+}
+
+static inline int
+__osm_unpack_lids(
+  IN char *p_lid_str,
+  OUT uint16_t *p_min_lid,
+  OUT uint16_t *p_max_lid )
+{
+  unsigned long tmp;
+  char *p_next;
+  char *p_num;
+  char lids_str[24];
+  
+  strncpy(lids_str, p_lid_str, 23);
+  lids_str[23] = '\0';
+  p_num = strtok_r(lids_str, " \t", &p_next);
+  if (! p_num) return 1;
+  tmp = strtoul(p_num, NULL, 0);
+  CL_ASSERT( tmp < 0x10000 );
+  *p_min_lid = (uint16_t)tmp;
+
+  p_num = strtok_r(NULL, " \t", &p_next);
+  if (! p_num) return 1;
+  tmp = strtoul(p_num, NULL, 0);
+  CL_ASSERT( tmp < 0x10000 );
+  *p_max_lid = (uint16_t)tmp;
+  
+  return 0;
+}
+
+int
+osm_db_guid2lid_guids(
+  IN osm_db_domain_t* const p_g2l,
+  OUT cl_qlist_t* p_guid_list )
+{
+  char               *p_key;
+  cl_list_t           keys;
+  osm_db_guid_elem_t *p_guid_elem;
+
+  cl_list_construct( &keys );
+  cl_list_init( &keys , 10);
+  
+  if (osm_db_keys(p_g2l, &keys))
+    return 1;
+  
+  while ( (p_key = cl_list_remove_head( &keys )) != NULL )
+  {
+    p_guid_elem = (osm_db_guid_elem_t*)malloc(sizeof(osm_db_guid_elem_t));
+    CL_ASSERT( p_guid_elem != NULL );
+
+    p_guid_elem->guid = __osm_unpack_guid(p_key);
+    cl_qlist_insert_head(p_guid_list, &p_guid_elem->item);
+  }
+
+  cl_list_destroy( &keys );
+  return 0;
+}
+
+int
+osm_db_guid2lid_get(
+  IN osm_db_domain_t* const p_g2l,
+  IN uint64_t guid,
+  OUT uint16_t *p_min_lid, 
+  OUT uint16_t *p_max_lid)
+{
+  char guid_str[20];
+  char *p_lid_str;
+  uint16_t min_lid, max_lid;
+  
+  __osm_pack_guid(guid, guid_str);
+  p_lid_str = osm_db_lookup(p_g2l, guid_str);
+  if (! p_lid_str)
+    return 1;
+  if (__osm_unpack_lids(p_lid_str, &min_lid, &max_lid))
+    return 1;
+  
+  if (p_min_lid) *p_min_lid = min_lid;
+  if (p_max_lid) *p_max_lid = max_lid;
+  
+  return 0;
+}
+
+int
+osm_db_guid2lid_set(
+  IN osm_db_domain_t* const p_g2l,
+  IN uint64_t guid,
+  IN uint16_t min_lid,
+  IN uint16_t max_lid)
+{
+  char guid_str[20];
+  char lid_str[16];
+
+  __osm_pack_guid(guid, guid_str);
+  __osm_pack_lids(min_lid, max_lid, lid_str);
+  
+  return( osm_db_update( p_g2l, guid_str, lid_str) );
+}
+
+int
+osm_db_guid2lid_delete(
+  IN osm_db_domain_t* const p_g2l,
+  IN uint64_t guid )
+{
+  char guid_str[20];
+  __osm_pack_guid(guid, guid_str);
+  return( osm_db_delete( p_g2l, guid_str) );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_drop_mgr.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_drop_mgr.c
new file mode 100644 (file)
index 0000000..1537044
--- /dev/null
@@ -0,0 +1,721 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_drop_mgr.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_drop_mgr_t.
+ * This object represents the Drop Manager object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_ptr_vector.h>
+#include <opensm/osm_drop_mgr.h>
+#include <opensm/osm_router.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_mcm_info.h>
+#include <opensm/osm_multicast.h>
+#include <opensm/osm_remote_sm.h>
+#include <opensm/osm_inform.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_drop_mgr_construct(
+  IN osm_drop_mgr_t* const p_mgr )
+{
+  CL_ASSERT( p_mgr );
+  memset( p_mgr, 0, sizeof(*p_mgr) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_drop_mgr_destroy(
+  IN osm_drop_mgr_t* const p_mgr )
+{
+  CL_ASSERT( p_mgr );
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_drop_mgr_destroy );
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_drop_mgr_init(
+  IN osm_drop_mgr_t* const p_mgr,
+  IN osm_subn_t* const p_subn,
+  IN osm_log_t* const p_log,
+  IN osm_req_t* const p_req,
+  IN cl_plock_t* const p_lock )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_drop_mgr_init );
+
+  osm_drop_mgr_construct( p_mgr );
+
+  p_mgr->p_log = p_log;
+  p_mgr->p_subn = p_subn;
+  p_mgr->p_lock = p_lock;
+  p_mgr->p_req = p_req;
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_drop_mgr_remove_router(
+  IN const osm_drop_mgr_t* const p_mgr,
+  IN const ib_net64_t portguid )
+{
+  osm_router_t *p_rtr;
+  cl_qmap_t* p_rtr_guid_tbl;
+
+  p_rtr_guid_tbl = &p_mgr->p_subn->rtr_guid_tbl;
+  p_rtr = (osm_router_t*)cl_qmap_remove( p_rtr_guid_tbl, portguid );
+  if( p_rtr != (osm_router_t*)cl_qmap_end( p_rtr_guid_tbl ) )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+             "__osm_drop_mgr_remove_router: "
+             "Cleaned router for port guid 0x%016" PRIx64 "\n",
+             cl_ntoh64( portguid ) );
+    osm_router_delete( &p_rtr );
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_drop_mgr_remove_port(
+  IN const osm_drop_mgr_t* const p_mgr,
+  IN osm_port_t* p_port )
+{
+  ib_net64_t port_guid;
+  osm_port_t *p_port_check;
+  cl_list_t* p_new_ports_list;
+  cl_list_iterator_t cl_list_item;
+  cl_qmap_t* p_port_guid_tbl;
+  cl_qmap_t* p_sm_guid_tbl;
+  osm_mcm_info_t* p_mcm;
+  osm_mgrp_t*  p_mgrp;
+  cl_ptr_vector_t* p_port_lid_tbl;
+  uint16_t min_lid_ho;
+  uint16_t max_lid_ho;
+  uint16_t lid_ho;
+  uint32_t port_num;
+  uint32_t remote_port_num;
+  uint32_t num_physp;
+  osm_node_t *p_node;
+  osm_node_t *p_remote_node;
+  osm_physp_t *p_physp;
+  osm_physp_t *p_remote_physp;
+  osm_remote_sm_t *p_sm;
+  ib_gid_t port_gid;
+  ib_mad_notice_attr_t    notice;
+  ib_api_status_t         status;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_drop_mgr_remove_port );
+
+  port_guid = osm_port_get_guid( p_port );
+  osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+           "__osm_drop_mgr_remove_port: "
+           "Unreachable port 0x%016" PRIx64 "\n",
+           cl_ntoh64( port_guid ) );
+
+  /*
+    Remove this port from the new_ports_list, if it exists there.
+    Remove this port from the guid and LID tables.
+    Remove also from the sm guid table - if the object
+    exists there.
+  */
+  p_new_ports_list = &p_mgr->p_subn->new_ports_list;
+  cl_list_item = cl_list_head(p_new_ports_list);
+  while( cl_list_item != cl_list_end(p_new_ports_list) )
+  {
+    if ( (osm_port_t*)(cl_list_obj(cl_list_item)) == p_port )
+    {
+      /* Found the port in the new_ports_list. Remove it from there. */
+      cl_list_remove_item(p_new_ports_list, cl_list_item);
+      break;
+    }
+    cl_list_item = cl_list_next(cl_list_item);
+  }
+
+  p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
+  p_port_check = (osm_port_t*)cl_qmap_remove( p_port_guid_tbl, port_guid );
+  if( p_port_check != p_port )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "__osm_drop_mgr_remove_port: ERR 0101: "
+             "Port 0x%016" PRIx64 " not in guid table\n",
+             cl_ntoh64( port_guid ) );
+    goto Exit;
+  }
+
+  p_sm_guid_tbl = &p_mgr->p_subn->sm_guid_tbl;  
+  p_sm = (osm_remote_sm_t*)cl_qmap_remove( p_sm_guid_tbl, port_guid );
+  if( p_sm != (osm_remote_sm_t*)cl_qmap_end( p_sm_guid_tbl ) )
+  {
+    /* need to remove this item */
+    osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+             "__osm_drop_mgr_remove_port: "
+             "Cleaned SM for port guid\n" );
+    
+    free(p_sm);
+  }
+
+  __osm_drop_mgr_remove_router( p_mgr, port_guid );
+
+  osm_port_get_lid_range_ho( p_port, &min_lid_ho, &max_lid_ho );
+
+  osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+           "__osm_drop_mgr_remove_port: "
+           "Clearing abandoned LID range [0x%X,0x%X]\n",
+           min_lid_ho, max_lid_ho );
+
+  p_port_lid_tbl = &p_mgr->p_subn->port_lid_tbl;
+  for( lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++ )
+    cl_ptr_vector_set( p_port_lid_tbl, lid_ho, NULL );
+
+  /*
+    For each Physical Port associated with this port:
+    Unlink the remote Physical Port, if any
+    Re-initialize each Physical Port.
+  */
+
+  num_physp = osm_port_get_num_physp( p_port );
+  for( port_num = 0; port_num < num_physp; port_num++ )
+  {
+    p_physp = osm_port_get_phys_ptr( p_port, (uint8_t)port_num );
+
+    if( p_physp )
+    {
+      p_remote_physp = osm_physp_get_remote( p_physp );
+      if( p_remote_physp && osm_physp_is_valid( p_remote_physp ) )
+      {
+        osm_port_t* p_remote_port;
+
+        p_node = osm_physp_get_node_ptr( p_physp );
+        p_remote_node = osm_physp_get_node_ptr( p_remote_physp );
+        remote_port_num = osm_physp_get_port_num( p_remote_physp );
+        p_remote_port = (osm_port_t*)cl_qmap_get( p_port_guid_tbl, p_remote_physp->port_guid );
+
+        if ( p_remote_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl ) )
+        {
+          /* Let's check if this is a case of link that is lost (both ports
+             weren't recognized), or a "hiccup" in the subnet - in which case
+             the remote port was recognized, and its state is ACTIVE. 
+             If this is just a "hiccup" - force a heavy sweep in the next sweep.
+             We don't want to lose that part of the subnet. */
+          if (osm_port_discovery_count_get( p_remote_port ) &&
+              osm_physp_get_port_state( p_remote_physp ) == IB_LINK_ACTIVE )
+          {
+            osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+                     "__osm_drop_mgr_remove_port: "
+                     "Forcing delayed heavy sweep. Remote "
+                     "port 0x%016" PRIx64 " port num: 0x%X "
+                     "was recognized in ACTIVE state\n",
+                     cl_ntoh64( p_remote_physp->port_guid ),
+                     remote_port_num );
+            p_mgr->p_subn->force_delayed_heavy_sweep = TRUE;
+          }
+        }
+
+        osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+                 "__osm_drop_mgr_remove_port: "
+                 "Unlinking local node 0x%016" PRIx64 ", port 0x%X"
+                 "\n\t\t\t\tand remote node 0x%016" PRIx64
+                 ", port 0x%X\n",
+                 cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+                 port_num,
+                 cl_ntoh64( osm_node_get_node_guid( p_remote_node ) ),
+                 remote_port_num );
+
+        osm_node_unlink( p_node, (uint8_t)port_num,
+                         p_remote_node, (uint8_t)remote_port_num );
+
+        /* If the remote node is ca or router - need to remove the remote port,
+           since it is no longer reachable. This can be done if we reset the
+           discovery count of the remote port. */
+        if ( osm_node_get_type( p_remote_node ) != IB_NODE_TYPE_SWITCH )
+        {
+          if ( p_remote_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl ) )
+          {
+            osm_port_discovery_count_reset( p_remote_port );
+            osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+                     "__osm_drop_mgr_remove_port: "
+                     "Resetting discovery count of node: "
+                     "0x%016" PRIx64 " port num:0x%X\n",
+                     cl_ntoh64( osm_node_get_node_guid( p_remote_node ) ),
+                     remote_port_num );
+          }
+        }
+      }
+
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "__osm_drop_mgr_remove_port: "
+               "Clearing physical port number 0x%X\n",
+               port_num );
+
+      osm_physp_destroy( p_physp );
+    }
+  }
+
+  p_mcm = (osm_mcm_info_t*)cl_qlist_remove_head( &p_port->mcm_list );
+  while( p_mcm != (osm_mcm_info_t *)cl_qlist_end( &p_port->mcm_list ) )
+  {
+    p_mgrp = (osm_mgrp_t *)cl_qmap_get( &p_mgr->p_subn->mgrp_mlid_tbl,
+                                        p_mcm->mlid );
+    if(p_mgrp != (osm_mgrp_t *)cl_qmap_end( &p_mgr->p_subn->mgrp_mlid_tbl ) )
+    {
+      osm_mgrp_remove_port(p_mgr->p_subn, p_mgr->p_log, p_mgrp, p_port->guid );
+      osm_mcm_info_delete( (osm_mcm_info_t*)p_mcm );
+    }
+    p_mcm = (osm_mcm_info_t*)cl_qlist_remove_head( &p_port->mcm_list );
+  }
+
+  /* initialize the p_node - may need to get node_desc later */
+  p_node = p_port->p_node;
+
+  osm_port_delete( &p_port );
+
+  /* issue a notice - trap 65 */
+  
+  /* details of the notice */
+  notice.generic_type = 0x83; /* is generic subn mgt type */
+  ib_notice_set_prod_type_ho(&notice, 4); /* A class manager generator */
+  /* endport ceases to be reachable */
+  notice.g_or_v.generic.trap_num = CL_HTON16(65); 
+  /* The sm_base_lid is saved in network order already. */
+  notice.issuer_lid = p_mgr->p_subn->sm_base_lid;
+  /* following C14-72.1.2 and table 119 p725 */
+  /* we need to provide the GID */
+  port_gid.unicast.prefix = p_mgr->p_subn->opt.subnet_prefix;
+  port_gid.unicast.interface_id = port_guid;
+  memcpy(&(notice.data_details.ntc_64_67.gid),
+         &(port_gid),
+         sizeof(ib_gid_t));
+  /* According to page 653 - the issuer gid in this case of trap
+     is the SM gid, since the SM is the initiator of this trap. */
+  notice.issuer_gid.unicast.prefix = p_mgr->p_subn->opt.subnet_prefix;
+  notice.issuer_gid.unicast.interface_id = p_mgr->p_subn->sm_port_guid;
+
+  status = osm_report_notice(p_mgr->p_log, p_mgr->p_subn, &notice);
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "__osm_drop_mgr_remove_port: ERR 0103: "
+             "Error sending trap reports (%s)\n",
+             ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  if (osm_log_is_active( p_mgr->p_log, OSM_LOG_INFO ))
+  {
+    char desc[IB_NODE_DESCRIPTION_SIZE + 1];
+
+    if (p_node)
+    {
+      memcpy(desc, p_node->node_desc.description, IB_NODE_DESCRIPTION_SIZE);
+      desc[IB_NODE_DESCRIPTION_SIZE] = '\0';
+    }
+    osm_log( p_mgr->p_log, OSM_LOG_INFO,
+             "__osm_drop_mgr_remove_port: "
+             "Removed port with GUID:0x%016" PRIx64
+             " LID range [0x%X,0x%X] of node:%s\n",
+             cl_ntoh64( port_gid.unicast.interface_id ),
+             min_lid_ho, max_lid_ho, p_node ? desc : "UNKNOWN" );
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_drop_mgr_remove_switch(
+  IN const osm_drop_mgr_t* const p_mgr,
+  IN osm_node_t* p_node )
+{
+  osm_switch_t *p_sw;
+  cl_qmap_t* p_sw_guid_tbl;
+  ib_net64_t node_guid;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_drop_mgr_remove_switch );
+
+  node_guid = osm_node_get_node_guid( p_node );
+  p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+  p_sw = (osm_switch_t*)cl_qmap_remove( p_sw_guid_tbl, node_guid );
+  if( p_sw == (osm_switch_t*)cl_qmap_end( p_sw_guid_tbl ) )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "__osm_drop_mgr_remove_switch: ERR 0102: "
+             "Node 0x%016" PRIx64 " not in switch table\n",
+             cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+  }
+  else
+  {
+    p_node->sw = NULL;
+    osm_switch_delete( &p_sw );
+  }
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+__osm_drop_mgr_process_node(
+  IN const osm_drop_mgr_t* const p_mgr,
+  IN osm_node_t* p_node )
+{
+  osm_physp_t *p_physp;
+  osm_port_t *p_port;
+  osm_node_t *p_node_check;
+  cl_qmap_t *p_node_guid_tbl;
+  uint32_t port_num;
+  uint32_t max_ports;
+  ib_net64_t port_guid;
+  cl_qmap_t* p_port_guid_tbl;
+  boolean_t return_val = FALSE;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_drop_mgr_process_node );
+
+  osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+           "__osm_drop_mgr_process_node: "
+           "Unreachable node 0x%016" PRIx64 "\n",
+           cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+
+  /*
+    Delete all the logical and physical port objects
+    associated with this node.
+  */
+  p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+  max_ports = osm_node_get_num_physp( p_node );
+  for( port_num = 0; port_num < max_ports; port_num++ )
+  {
+    p_physp = osm_node_get_physp_ptr( p_node, port_num );
+    if( osm_physp_is_valid( p_physp ) )
+    {
+      port_guid = osm_physp_get_port_guid( p_physp );
+
+      p_port = (osm_port_t*)cl_qmap_get( p_port_guid_tbl, port_guid );
+
+      if( p_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl ) )
+        __osm_drop_mgr_remove_port( p_mgr, p_port );
+    }
+  }
+
+  return_val = TRUE;
+
+  if (p_node->sw)
+    __osm_drop_mgr_remove_switch( p_mgr, p_node );
+
+  p_node_guid_tbl = &p_mgr->p_subn->node_guid_tbl;
+  p_node_check = (osm_node_t*)cl_qmap_remove( p_node_guid_tbl,
+                                              osm_node_get_node_guid( p_node ) );
+  if( p_node_check != p_node )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "__osm_drop_mgr_process_node: ERR 0105: "
+             "Node 0x%016" PRIx64 " not in guid table\n",
+             cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+  }
+
+  /* free memory allocated to node */
+  osm_node_delete( &p_node );
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return( return_val );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_drop_mgr_check_node(
+  IN const osm_drop_mgr_t* const p_mgr,
+  IN osm_node_t* p_node )
+{
+  ib_net64_t node_guid;
+  osm_physp_t *p_physp;
+  osm_port_t *p_port;
+  cl_qmap_t* p_port_guid_tbl;
+  ib_net64_t port_guid;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_drop_mgr_check_node );
+
+  node_guid = osm_node_get_node_guid( p_node );
+
+  if ( osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "__osm_drop_mgr_check_node: ERR 0107: "
+             "Node 0x%016" PRIx64 " is not a switch node\n",
+             cl_ntoh64( node_guid ) );
+    goto Exit;
+  }
+
+  /* Make sure we have a switch object for this node */
+  if (!p_node->sw)
+  {
+    /* We do not have switch info for this node */
+    osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+             "__osm_drop_mgr_check_node: "
+             "Node 0x%016" PRIx64 " no switch in table\n",
+             cl_ntoh64( node_guid ) );
+    
+    __osm_drop_mgr_process_node( p_mgr, p_node );
+    goto Exit;
+  }
+
+  /* Make sure we have a port object for port zero */
+  p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
+  p_physp = osm_node_get_physp_ptr( p_node, 0 );
+  if ( !osm_physp_is_valid( p_physp ) )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+             "__osm_drop_mgr_check_node: "
+             "Node 0x%016" PRIx64 " no valid physical port 0\n",
+             cl_ntoh64( node_guid ) );
+    
+    __osm_drop_mgr_process_node( p_mgr, p_node );
+    goto Exit;
+  }
+   
+  port_guid = osm_physp_get_port_guid( p_physp );
+
+  p_port = (osm_port_t*)cl_qmap_get(
+    p_port_guid_tbl, port_guid );
+
+  if( p_port == (osm_port_t*)cl_qmap_end( p_port_guid_tbl ) )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+             "__osm_drop_mgr_check_node: "
+             "Node 0x%016" PRIx64 " has no port object\n",
+             cl_ntoh64( node_guid ) );
+    
+    __osm_drop_mgr_process_node( p_mgr, p_node );
+    goto Exit;
+  }
+
+  if ( osm_port_discovery_count_get( p_port ) == 0 )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+             "__osm_drop_mgr_check_node: "
+             "Node 0x%016" PRIx64 " port has discovery count zero\n",
+             cl_ntoh64( node_guid ) );
+    
+    __osm_drop_mgr_process_node( p_mgr, p_node );
+    goto Exit;
+  }
+
+  Exit:
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_drop_mgr_process(
+  IN const osm_drop_mgr_t* const p_mgr )
+{
+  cl_qmap_t   *p_node_guid_tbl;
+  cl_qmap_t   *p_port_guid_tbl;
+  cl_list_t   *p_lsweep_ports;
+  osm_port_t  *p_port;
+  osm_port_t  *p_next_port;
+  osm_node_t  *p_node;
+  osm_node_t  *p_next_node;
+  ib_net64_t   port_guid;
+  ib_net64_t   node_guid;
+  uint8_t      port_num;
+  osm_physp_t *p_physp;
+
+  CL_ASSERT( p_mgr );
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_drop_mgr_process );
+
+  p_node_guid_tbl = &p_mgr->p_subn->node_guid_tbl;
+  p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
+  p_lsweep_ports = &p_mgr->p_subn->light_sweep_physp_list;
+
+  CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
+
+  p_next_node = (osm_node_t*)cl_qmap_head( p_node_guid_tbl );
+  while( p_next_node != (osm_node_t*)cl_qmap_end( p_node_guid_tbl ) )
+  {
+    p_node = p_next_node;
+    p_next_node = (osm_node_t*)cl_qmap_next( &p_next_node->map_item );
+
+    CL_ASSERT( cl_qmap_key( &p_node->map_item ) ==
+               osm_node_get_node_guid( p_node ) );
+
+    if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+    {
+      node_guid = osm_node_get_node_guid( p_node );
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "osm_drop_mgr_process: "
+               "Checking node 0x%016" PRIx64 "\n",
+               cl_ntoh64( node_guid ) );
+    }
+
+    /*
+      Check if this node was discovered during the last sweep.
+      If not, it is unreachable in the current subnet, and
+      should therefore be removed from the subnet object.
+    */
+    if( osm_node_discovery_count_get( p_node ) == 0 )
+      __osm_drop_mgr_process_node( p_mgr, p_node );
+  }
+
+  /*
+    Go over all the nodes. If the node is a switch - make sure
+    there is also a switch record for it, and a portInfo record for
+    port zero of of the node.
+    If not - this means that there was some error in getting the data
+    of this node. Drop the node.
+  */
+  p_next_node = (osm_node_t*)cl_qmap_head( p_node_guid_tbl );  
+  while( p_next_node != (osm_node_t*)cl_qmap_end( p_node_guid_tbl ) )
+  {
+    p_node = p_next_node;
+    p_next_node = (osm_node_t*)cl_qmap_next( &p_next_node->map_item );
+
+    if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+    {
+      node_guid = osm_node_get_node_guid( p_node );
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "osm_drop_mgr_process: "
+               "Checking full discovery of node 0x%016" PRIx64 "\n",
+               cl_ntoh64( node_guid ) );
+    }
+
+    if ( osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH )
+      continue;
+
+    /* We are handling a switch node */
+    __osm_drop_mgr_check_node( p_mgr, p_node );
+  }
+    
+  p_next_port = (osm_port_t*)cl_qmap_head( p_port_guid_tbl );
+  while( p_next_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl ) )
+  {
+    p_port = p_next_port;
+    p_next_port = (osm_port_t*)cl_qmap_next( &p_next_port->map_item );
+
+    CL_ASSERT( cl_qmap_key( &p_port->map_item ) ==
+               osm_port_get_guid( p_port ) );
+
+    if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+    {
+      port_guid = osm_port_get_guid( p_port );
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "osm_drop_mgr_process: "
+               "Checking port 0x%016" PRIx64 "\n",
+               cl_ntoh64( port_guid ) );
+    }
+
+    /*
+      If the port is unreachable, remove it from the guid table.
+    */
+    if( osm_port_discovery_count_get( p_port ) == 0 )
+      __osm_drop_mgr_remove_port( p_mgr, p_port );
+  }
+
+  /* 
+     scan through all the ports left - if the port is not DOWN and 
+     it does not have a valid remote port - we need to track it for 
+     next light sweep scan...
+  */
+  cl_list_remove_all( p_lsweep_ports );
+  p_next_node = (osm_node_t*)cl_qmap_head( p_node_guid_tbl );
+  while( p_next_node != (osm_node_t*)cl_qmap_end( p_node_guid_tbl ) )
+  {
+    p_node = p_next_node;
+    p_next_node = (osm_node_t*)cl_qmap_next( &p_next_node->map_item );
+    
+    for (port_num = 1; port_num < osm_node_get_num_physp(p_node); port_num++)
+    {
+      p_physp = osm_node_get_physp_ptr(p_node, port_num);
+      if (osm_physp_is_valid(p_physp) && 
+          (osm_physp_get_port_state(p_physp) != IB_LINK_DOWN) &&
+          ! osm_physp_get_remote(p_physp))
+      {
+        osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+                 "osm_drop_mgr_process: ERR 0108: "
+                 "Unknown remote side for node 0x%016" PRIx64 
+                 " port %u. Adding to light sweep sampling list\n",
+                 cl_ntoh64( osm_node_get_node_guid( p_node )),
+                 port_num);
+        
+        osm_dump_dr_path(p_mgr->p_log, 
+                         osm_physp_get_dr_path_ptr( p_physp ),
+                         OSM_LOG_ERROR);
+        
+        cl_list_insert_head( p_lsweep_ports, p_physp );
+      }
+    }
+  }
+  CL_PLOCK_RELEASE( p_mgr->p_lock );
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_files.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_files.c
new file mode 100644 (file)
index 0000000..c7f6fbf
--- /dev/null
@@ -0,0 +1,99 @@
+#include <osm_db_files.c>\r
+#include <osm_db_pack.c>\r
+#include <osm_fwd_tbl.c>\r
+#include <osm_inform.c>\r
+#include <osm_lid_mgr.c>\r
+#include <osm_lin_fwd_rcv.c>\r
+#include <osm_lin_fwd_rcv_ctrl.c>\r
+#include <osm_lin_fwd_tbl.c>\r
+\r#include <osm_link_mgr.c>\r
+#include <osm_matrix.c>\r
+#include <osm_mcast_fwd_rcv.c>\r
+#include <osm_mcast_fwd_rcv_ctrl.c>\r
+#include <osm_mcast_mgr.c>\r
+#include <osm_mcast_tbl.c>\r
+#include <osm_mcm_info.c>\r
+#include <osm_mcm_port.c>\r
+#include <osm_mtree.c>\r
+#include <osm_multicast.c>\r
+#include <osm_node.c>\r
+#include <osm_node_desc_rcv.c>\r
+#include <osm_node_desc_rcv_ctrl.c>\r
+#include <osm_node_info_rcv.c>\r
+#include <osm_node_info_rcv_ctrl.c>\r
+#include <osm_opensm.c>\r
+#include <osm_pkey.c>\r
+#include <osm_pkey_mgr.c>\r
+#include <osm_prtn.c>\r
+#include <osm_pkey_rcv.c>\r
+#include <osm_pkey_rcv_ctrl.c>\r
+#include <osm_qos.c>\r
+#include <osm_port.c>\r
+#include <osm_port_info_rcv.c>\r
+#include <osm_port_info_rcv_ctrl.c>\r
+#include <osm_remote_sm.c>\r
+#include <osm_req.c>\r
+#include <osm_req_ctrl.c>\r
+#include <osm_resp.c>\r
+#include <osm_sa.c>\r
+#include <osm_router.c>\r
+#include <osm_sa_class_port_info.c>\r
+#include <osm_sa_class_port_info_ctrl.c>\r
+#include <osm_sa_guidinfo_record.c>\r
+#include <osm_sa_guidinfo_record_ctrl.c>\r
+#include <osm_sa_informinfo.c>\r
+#include <osm_sa_informinfo_ctrl.c>\r
+#include <osm_sa_lft_record.c>\r
+#include <osm_sa_lft_record_ctrl.c>\r
+#include <osm_sa_link_record.c>\r
+#include <osm_sa_link_record_ctrl.c>\r
+\r#include <osm_sa_mad_ctrl.c>\r
+\r#include <osm_sa_mcmember_record_ctrl.c>\r
+\r#include <osm_sa_mft_record.c>\r
+\r#include <osm_sa_mft_record_ctrl.c>\r
+\r#include <osm_sa_node_record.c>\r
+\r#include <osm_sa_node_record_ctrl.c>\r
+\r#include <osm_sa_path_record_ctrl.c>\r
+\r#include <osm_sa_pkey_record.c>\r
+\r#include <osm_sa_pkey_record_ctrl.c>\r
+\r#include <osm_sa_portinfo_record.c>\r
+\r#include <osm_sa_portinfo_record_ctrl.c>\r
+\r#include <osm_sa_response.c>\r
+\r#include <osm_sa_service_record.c>\r
+\r#include <osm_sa_service_record_ctrl.c>\r
+\r#include <osm_sa_slvl_record.c>\r
+\r#include <osm_sa_slvl_record_ctrl.c>\r
+\r#include <osm_sa_sminfo_record.c>\r
+\r#include <osm_sa_sminfo_record_ctrl.c>\r
+\r#include <osm_sa_sw_info_record.c>\r
+\r#include <osm_sa_sw_info_record_ctrl.c>\r
+\r#include <osm_sa_vlarb_record.c>\r
+\r#include <osm_sa_vlarb_record_ctrl.c>\r
+\r#include <osm_service.c>\r
+\r#include <osm_slvl_map_rcv.c>\r
+\r#include <osm_slvl_map_rcv_ctrl.c>\r
+\r#include <osm_sm.c>\r
+#include <osm_sminfo_rcv.c>\r
+#include <osm_sminfo_rcv_ctrl.c>\r
+#include <osm_sm_mad_ctrl.c>\r
+#include <osm_sm_state_mgr.c>\r
+#include <osm_state_mgr.c>\r
+#include <osm_state_mgr_ctrl.c>\r
+#include <osm_subnet.c>\r
+#include <osm_sweep_fail_ctrl.c>\r
+#include <osm_sw_info_rcv.c>\r
+#include <osm_sw_info_rcv_ctrl.c>\r
+#include <osm_switch.c>\r
+#include <osm_trap_rcv.c>\r
+#include <osm_trap_rcv_ctrl.c>\r
+#include <osm_ucast_mgr.c>\r
+#include <osm_ucast_updn.c>\r
+#include <osm_ucast_file.c>\r
+#include <osm_ucast_ftree.c>\r
+#include <osm_vl15intf.c>\r
+#include <osm_vl_arb_rcv.c>\r
+#include <osm_vl_arb_rcv_ctrl.c>\r
+#include <st.c>\r
+#include <main.c>\r
+#include <cl_event_wheel.c>\r
+#include <cl_dispatcher.c>\r
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_fwd_tbl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_fwd_tbl.c
new file mode 100644 (file)
index 0000000..a8d0820
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_fwd_tbl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_fwd_tbl_t.
+ * This object represents a unicast forwarding table.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_math.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_fwd_tbl.h>
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_fwd_tbl_init(
+  IN osm_fwd_tbl_t* const p_tbl,
+  IN const ib_switch_info_t* const p_si )
+{
+  uint16_t tbl_cap;
+  ib_api_status_t status = IB_SUCCESS;
+
+  /*
+    Determine the type and size of the forwarding table
+    used by this switch, then initialize accordingly.
+    The current implementation only supports switches
+    with linear forwarding tables.
+  */
+  tbl_cap = cl_ntoh16( p_si->lin_cap );
+
+  if( tbl_cap == 0 )
+  {
+    /*
+      This switch does not support linear forwarding
+      tables.  Error out for now.
+    */
+    status = IB_UNSUPPORTED;
+    goto Exit;
+  }
+
+  p_tbl->p_rnd_tbl = NULL;
+
+  p_tbl->p_lin_tbl = osm_lin_tbl_new( tbl_cap );
+
+  if( p_tbl->p_lin_tbl == NULL )
+  {
+    status = IB_INSUFFICIENT_MEMORY;
+    goto Exit;
+  }
+
+ Exit:
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_fwd_tbl_destroy(
+  IN osm_fwd_tbl_t* const p_tbl )
+{
+  if( p_tbl->p_lin_tbl )
+  {
+    CL_ASSERT( p_tbl->p_rnd_tbl == NULL );
+    osm_lin_tbl_delete( &p_tbl->p_lin_tbl );
+  }
+  else
+  {
+    osm_rand_tbl_delete( &p_tbl->p_rnd_tbl );
+  }
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_inform.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_inform.c
new file mode 100644 (file)
index 0000000..83a8d1e
--- /dev/null
@@ -0,0 +1,763 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_inform.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of inform record functions.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.18 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_timer.h>
+#include <opensm/osm_sa_informinfo.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_inform.h>
+#include <opensm/osm_trap_rcv.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_pkey.h>
+
+typedef struct _osm_infr_match_ctxt
+{
+  cl_list_t            *p_remove_infr_list;
+  ib_mad_notice_attr_t *p_ntc;
+} osm_infr_match_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_construct(
+  IN osm_infr_t* const p_infr )
+{
+  memset( p_infr, 0, sizeof(osm_infr_t) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_destroy(
+  IN osm_infr_t* const p_infr )
+{
+  free( p_infr );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_init(
+  IN osm_infr_t* const p_infr,
+  IN const osm_infr_t *p_infr_rec  )
+{
+  CL_ASSERT( p_infr );
+
+  /* what else do we need in the inform_record ??? */
+
+  /* copy the contents of the provided informinfo */
+  memcpy( p_infr, p_infr_rec, sizeof(osm_infr_t) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_infr_t*
+osm_infr_new(
+  IN const osm_infr_t *p_infr_rec )
+{
+  osm_infr_t* p_infr;
+
+  CL_ASSERT(p_infr_rec);
+
+  p_infr = (osm_infr_t*)malloc( sizeof(osm_infr_t) );
+  if( p_infr )
+  {
+    osm_infr_init( p_infr, p_infr_rec );
+  }
+
+  return( p_infr );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__dump_all_informs(
+    IN osm_subn_t  const *p_subn,
+    IN osm_log_t *p_log)
+{
+   cl_list_item_t* p_list_item;
+
+   OSM_LOG_ENTER( p_log, __dump_all_informs );
+
+   if( !osm_log_is_active( p_log, OSM_LOG_DEBUG ) )
+     goto Exit;
+
+   p_list_item = cl_qlist_head( &p_subn->sa_infr_list );
+   while (p_list_item != cl_qlist_end( &p_subn->sa_infr_list ))
+   {
+     osm_dump_inform_info( p_log,
+                           &((osm_infr_t*)p_list_item)->inform_record.inform_info,
+                           OSM_LOG_DEBUG );
+     p_list_item = cl_qlist_next( p_list_item );
+   }
+
+ Exit:
+   OSM_LOG_EXIT( p_log );
+}
+
+/**********************************************************************
+ * Match an infr by the InformInfo and Address vector
+ **********************************************************************/
+static cl_status_t
+__match_inf_rec(
+  IN  const cl_list_item_t* const p_list_item,
+  IN  void*                       context )
+{
+  osm_infr_t* p_infr_rec = (osm_infr_t *)context;
+  osm_infr_t* p_infr = (osm_infr_t*)p_list_item;
+  osm_log_t *p_log =  p_infr_rec->p_infr_rcv->p_log;
+  cl_status_t status = CL_NOT_FOUND;
+  ib_gid_t all_zero_gid;
+
+  OSM_LOG_ENTER( p_log, __match_inf_rec);
+
+  if ( memcmp( &p_infr->report_addr,
+               &p_infr_rec->report_addr,
+               sizeof(p_infr_rec->report_addr)) )
+  {
+     osm_log( p_log, OSM_LOG_DEBUG,
+              "__match_inf_rec: "
+              "Differ by Address\n" );
+     goto Exit;
+  }
+
+  memset( &all_zero_gid, 0, sizeof(ib_gid_t) );
+
+  /* if inform_info.gid is not zero, ignore lid range */
+  if ( !memcmp( &p_infr_rec->inform_record.inform_info.gid,
+                &all_zero_gid,
+                sizeof(p_infr_rec->inform_record.inform_info.gid)) )
+  {
+     if ( memcmp( &p_infr->inform_record.inform_info.gid,
+                  &p_infr_rec->inform_record.inform_info.gid,
+                  sizeof(p_infr->inform_record.inform_info.gid)) )
+     {
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__match_inf_rec: "
+                 "Differ by InformInfo.gid\n" );
+        goto Exit;
+     }
+  }
+  else
+  {
+     if ( (p_infr->inform_record.inform_info.lid_range_begin !=
+           p_infr_rec->inform_record.inform_info.lid_range_begin) ||
+          (p_infr->inform_record.inform_info.lid_range_end !=
+           p_infr_rec->inform_record.inform_info.lid_range_end) )
+     {
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__match_inf_rec: "
+                 "Differ by InformInfo.LIDRange\n" );
+        goto Exit;
+     }
+  }
+
+  if ( p_infr->inform_record.inform_info.trap_type !=
+       p_infr_rec->inform_record.inform_info.trap_type )
+  {
+     osm_log( p_log, OSM_LOG_DEBUG,
+              "__match_inf_rec: "
+              "Differ by InformInfo.TrapType\n" );
+     goto Exit;
+  }
+
+  if ( p_infr->inform_record.inform_info.is_generic !=
+       p_infr_rec->inform_record.inform_info.is_generic )
+  {
+     osm_log( p_log, OSM_LOG_DEBUG,
+              "__match_inf_rec: "
+              "Differ by InformInfo.IsGeneric\n" );
+     goto Exit;
+  }
+
+  if (p_infr->inform_record.inform_info.is_generic)
+  {
+     if ( p_infr->inform_record.inform_info.g_or_v.generic.trap_num !=
+          p_infr_rec->inform_record.inform_info.g_or_v.generic.trap_num )
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__match_inf_rec: "
+                 "Differ by InformInfo.Generic.TrapNumber\n" );
+     else if ( p_infr->inform_record.inform_info.g_or_v.generic.qpn_resp_time_val !=
+               p_infr_rec->inform_record.inform_info.g_or_v.generic.qpn_resp_time_val )
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__match_inf_rec: "
+                 "Differ by InformInfo.Generic.QPNRespTimeVal\n" );
+     else if ( p_infr->inform_record.inform_info.g_or_v.generic.node_type_msb != 
+               p_infr_rec->inform_record.inform_info.g_or_v.generic.node_type_msb )
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__match_inf_rec: "
+                 "Differ by InformInfo.Generic.NodeTypeMSB\n" );
+     else if ( p_infr->inform_record.inform_info.g_or_v.generic.node_type_lsb != 
+               p_infr_rec->inform_record.inform_info.g_or_v.generic.node_type_lsb )
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__match_inf_rec: "
+                 "Differ by InformInfo.Generic.NodeTypeLSB\n" );
+     else
+           status = CL_SUCCESS;
+  }
+  else
+  {
+     if ( p_infr->inform_record.inform_info.g_or_v.vend.dev_id !=
+          p_infr_rec->inform_record.inform_info.g_or_v.vend.dev_id )
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__match_inf_rec: "
+                 "Differ by InformInfo.Vendor.DeviceID\n" );
+     else if ( p_infr->inform_record.inform_info.g_or_v.vend.qpn_resp_time_val != 
+               p_infr_rec->inform_record.inform_info.g_or_v.vend.qpn_resp_time_val )
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__match_inf_rec: "
+                 "Differ by InformInfo.Vendor.QPNRespTimeVal\n" );
+     else if ( p_infr->inform_record.inform_info.g_or_v.vend.vendor_id_msb !=
+               p_infr_rec->inform_record.inform_info.g_or_v.vend.vendor_id_msb )
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__match_inf_rec: "
+                 "Differ by InformInfo.Vendor.VendorIdMSB\n" );
+     else if ( p_infr->inform_record.inform_info.g_or_v.vend.vendor_id_lsb !=
+               p_infr_rec->inform_record.inform_info.g_or_v.vend.vendor_id_lsb )
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__match_inf_rec: "
+                 "Differ by InformInfo.Vendor.VendorIdLSB\n" );
+     else
+        status = CL_SUCCESS;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_infr_t*
+osm_infr_get_by_rec(
+  IN osm_subn_t   const *p_subn,
+  IN osm_log_t *p_log,
+  IN osm_infr_t* const p_infr_rec )
+{
+  cl_list_item_t* p_list_item;
+
+  OSM_LOG_ENTER( p_log, osm_infr_get_by_rec );
+
+  __dump_all_informs( p_subn, p_log );
+
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "osm_infr_get_by_rec: "
+           "Looking for Inform Record\n" );
+  osm_dump_inform_info( p_log, &(p_infr_rec->inform_record.inform_info),
+                        OSM_LOG_DEBUG );
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "osm_infr_get_by_rec: "
+          "InformInfo list size %d\n",
+          cl_qlist_count(&p_subn->sa_infr_list) );
+
+  p_list_item = cl_qlist_find_from_head(
+    &p_subn->sa_infr_list,
+    __match_inf_rec,
+    p_infr_rec );
+
+  if( p_list_item == cl_qlist_end( &p_subn->sa_infr_list ) )
+    p_list_item = NULL;
+
+  OSM_LOG_EXIT( p_log );
+  return (osm_infr_t*)p_list_item;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_insert_to_db(
+  IN osm_subn_t   *p_subn,
+  IN osm_log_t    *p_log,
+  IN osm_infr_t   *p_infr)
+{
+  OSM_LOG_ENTER( p_log, osm_infr_insert_to_db );
+
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "osm_infr_insert_to_db: "
+           "Inserting new InformInfo Record into Database\n" );
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "osm_infr_insert_to_db: "
+          "Dump before insertion (size %d)\n",
+          cl_qlist_count(&p_subn->sa_infr_list) );
+  __dump_all_informs( p_subn, p_log );
+
+#if 0
+  osm_dump_inform_info( p_log, 
+    &(p_infr->inform_record.inform_info), OSM_LOG_DEBUG );
+#endif
+
+  cl_qlist_insert_head( &p_subn->sa_infr_list,
+                        &p_infr->list_item );
+
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "osm_infr_insert_to_db: "
+          "Dump after insertion (size %d)\n",
+          cl_qlist_count(&p_subn->sa_infr_list) );
+  __dump_all_informs( p_subn, p_log );
+  OSM_LOG_EXIT( p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_remove_from_db(
+  IN osm_subn_t   *p_subn,
+  IN osm_log_t    *p_log,
+  IN osm_infr_t   *p_infr)
+{
+  OSM_LOG_ENTER( p_log, osm_infr_remove_from_db );
+
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "osm_infr_remove_from_db: "
+           "Removing InformInfo Subscribing GID:0x%016" PRIx64 " : 0x%016" PRIx64
+           " Enum:0x%X from Database\n",
+           cl_ntoh64(p_infr->inform_record.subscriber_gid.unicast.prefix),
+           cl_ntoh64(p_infr->inform_record.subscriber_gid.unicast.interface_id),
+           p_infr->inform_record.subscriber_enum
+           );
+
+  osm_dump_inform_info( p_log, &(p_infr->inform_record.inform_info), OSM_LOG_DEBUG );
+
+  cl_qlist_remove_item( &p_subn->sa_infr_list,
+                        &p_infr->list_item );
+
+  osm_infr_destroy( p_infr );
+
+  OSM_LOG_EXIT( p_log );
+}
+
+/**********************************************************************
+ * Send a report:
+ * Given a target address to send to and the notice.
+ * We need to send SubnAdmReport
+ **********************************************************************/
+static ib_api_status_t
+__osm_send_report(
+  IN  osm_infr_t*          p_infr_rec, /* the informinfo */
+  IN ib_mad_notice_attr_t* p_ntc       /* notice to send */
+  )
+{
+  osm_madw_t*              p_report_madw;
+  ib_mad_notice_attr_t*    p_report_ntc;
+  ib_mad_t*                p_mad;
+  ib_sa_mad_t*             p_sa_mad;
+  static atomic32_t        trap_fwd_trans_id = 0x02DAB000; 
+  ib_api_status_t          status;
+  osm_log_t *              p_log = p_infr_rec->p_infr_rcv->p_log;
+
+  OSM_LOG_ENTER( p_log, __osm_send_report );
+
+  /* HACK: who switches or uses the src and dest GIDs in the grh_info ?? */
+
+  /* it is better to use LIDs since the GIDs might not be there for SMI traps */
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "__osm_send_report: "
+           "Forwarding Notice Event from LID:0x%X"
+           " to InformInfo LID: 0x%X TID:0x%X\n",
+           cl_ntoh16(p_ntc->issuer_lid),
+           cl_ntoh16(p_infr_rec->report_addr.dest_lid),
+           trap_fwd_trans_id
+           );
+
+  /* get the MAD to send */
+  p_report_madw = osm_mad_pool_get( p_infr_rec->p_infr_rcv->p_mad_pool,
+                                    p_infr_rec->h_bind,
+                                    MAD_BLOCK_SIZE,
+                                    &(p_infr_rec->report_addr) );
+
+  p_report_madw->resp_expected = TRUE;
+
+  if( !p_report_madw )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "__osm_send_report: ERR 0203: "
+             "osm_mad_pool_get failed\n" );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* advance trap trans id (cant simply ++ on some systems inside ntoh) */
+  p_mad = osm_madw_get_mad_ptr( p_report_madw );
+  ib_mad_init_new( p_mad,
+                   IB_MCLASS_SUBN_ADM,
+                   2,
+                   IB_MAD_METHOD_REPORT,
+                   cl_hton64( (uint64_t)cl_atomic_inc( &trap_fwd_trans_id ) ),
+                   IB_MAD_ATTR_NOTICE,
+                   0 );
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_report_madw );
+
+  p_report_ntc = (ib_mad_notice_attr_t*)&(p_sa_mad->data);
+
+  /* copy the notice */
+  *p_report_ntc = *p_ntc;
+
+  /* The TRUE is for: response is expected */
+  status = osm_vendor_send( p_report_madw->h_bind, p_report_madw, TRUE );
+  if ( status != IB_SUCCESS )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "__osm_send_report: ERR 0204: "
+             "osm_vendor_send status = %s\n",
+             ib_get_err_str(status) );
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return(status);
+}
+
+/**********************************************************************
+ * This routine compares a given Notice and a ListItem of InformInfo type.
+ * PREREQUISITE:
+ * The Notice.GID should be pre-filled with the trap generator GID
+ **********************************************************************/
+static void
+__match_notice_to_inf_rec(
+  IN  cl_list_item_t* const p_list_item,
+  IN  void*                 context )
+{
+  osm_infr_match_ctxt_t* p_infr_match = (osm_infr_match_ctxt_t *)context;
+  ib_mad_notice_attr_t*  p_ntc = p_infr_match->p_ntc;
+  cl_list_t*             p_infr_to_remove_list = p_infr_match->p_remove_infr_list;
+  osm_infr_t* p_infr_rec = (osm_infr_t*)p_list_item;
+  ib_inform_info_t  *p_ii = &(p_infr_rec->inform_record.inform_info);
+  cl_status_t status = CL_NOT_FOUND;
+  osm_log_t *p_log =  p_infr_rec->p_infr_rcv->p_log;
+  osm_subn_t *p_subn = p_infr_rec->p_infr_rcv->p_subn;
+  ib_gid_t              source_gid;
+  osm_port_t*           p_src_port;
+  osm_port_t*           p_dest_port;
+
+  OSM_LOG_ENTER( p_log, __match_notice_to_inf_rec );
+
+  /* matching rules
+   * InformInfo   Notice
+   * GID          IssuerGID    if non zero must match the trap
+   * LIDRange     IssuerLID    apply only if GID=0
+   * IsGeneric    IsGeneric    is compulsory and must match the trap
+   * Type         Type         if not 0xFFFF must match
+   * TrapNumber   TrapNumber   if not 0xFFFF must match
+   * DeviceId     DeviceID     if not 0xFFFF must match
+   * QPN dont care
+   * ProducerType ProducerType match or 0xFFFFFF // EZ: actually my interpretation
+   * VendorID     VendorID     match or 0xFFFFFF
+   */
+
+  /* GID          IssuerGID    if non zero must match the trap  */
+  if ( p_ii->gid.unicast.prefix != 0 || p_ii->gid.unicast.interface_id != 0 )
+  {
+    /* match by GID */
+    if ( memcmp(&(p_ii->gid), &(p_ntc->issuer_gid), sizeof(ib_gid_t)) )
+    {
+      osm_log( p_log, OSM_LOG_DEBUG,
+               "__match_notice_to_inf_rec: "
+               "Mismatch by GID\n" );
+      goto Exit;
+    }
+  }
+  else
+  {
+    /* LIDRange     IssuerLID    apply only if GID=0 */
+    /* If lid_range_begin of the informInfo is 0xFFFF - then it should be ignored. */
+    if ( p_ii->lid_range_begin != 0xFFFF )
+    {
+      /* a real lid range is given - check it */
+      if ( (cl_hton16(p_ii->lid_range_begin) > cl_hton16(p_ntc->issuer_lid)) ||
+           (cl_hton16(p_ntc->issuer_lid) > cl_hton16(p_ii->lid_range_end)) ) {
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__match_notice_to_inf_rec: "
+                 "Mismatch by LID Range. Needed: 0x%X <= 0x%X <= 0x%X\n",
+                 cl_hton16(p_ii->lid_range_begin),
+                 cl_hton16(p_ntc->issuer_lid),
+                 cl_hton16(p_ii->lid_range_end)
+                 );
+        goto Exit;
+      }
+    }
+  }
+
+  /* IsGeneric    IsGeneric    is compulsory and must match the trap  */
+  if ( (p_ii->is_generic && ! ib_notice_is_generic(p_ntc)) ||
+       (!p_ii->is_generic && ib_notice_is_generic(p_ntc)) )
+  {
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "__match_notice_to_inf_rec: "
+             "Mismatch by Generic/Vendor\n" );
+    goto Exit;
+  }
+
+  /* Type         Type         if not 0xFFFF must match */
+  if ( (p_ii->trap_type != 0xFFFF) &&
+       (cl_ntoh16(p_ii->trap_type) != ib_notice_get_type(p_ntc)) )
+  {
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "__match_notice_to_inf_rec: "
+             "Mismatch by Type\n" );
+    goto Exit;
+  }
+
+  /* based on generic type */
+  if ( p_ii->is_generic )
+  {
+    /* TrapNumber   TrapNumber   if not 0xFFFF must match */
+    if ( (p_ii->g_or_v.generic.trap_num != 0xFFFF) &&
+         (p_ii->g_or_v.generic.trap_num != p_ntc->g_or_v.generic.trap_num) )
+    {
+      osm_log( p_log, OSM_LOG_DEBUG,
+               "__match_notice_to_inf_rec: "
+               "Mismatch by Trap Num\n" );
+      goto Exit;
+    }
+
+    /* ProducerType ProducerType match or 0xFFFFFF  */
+    if ( (cl_ntoh32(ib_inform_info_get_node_type(p_ii)) != 0xFFFFFF) &&
+         (ib_inform_info_get_node_type(p_ii) != ib_notice_get_prod_type(p_ntc)) )
+    {
+      osm_log( p_log, OSM_LOG_DEBUG,
+               "__match_notice_to_inf_rec: "
+               "Mismatch by Node Type: II=0x%06X Trap=0x%06X\n",
+               cl_ntoh32(ib_inform_info_get_node_type(p_ii)),
+               cl_ntoh32(ib_notice_get_prod_type(p_ntc))
+               );
+      goto Exit;
+    }
+  }
+  else
+  {
+    /* DeviceId     DeviceID     if not 0xFFFF must match */
+    if ( (p_ii->g_or_v.vend.dev_id != 0xFFFF) &&
+         (p_ii->g_or_v.vend.dev_id != p_ntc->g_or_v.vend.dev_id) )
+    {
+      osm_log( p_log, OSM_LOG_DEBUG,
+               "__match_notice_to_inf_rec: "
+               "Mismatch by Dev Id\n" );
+      goto Exit;
+    }
+
+    /* VendorID     VendorID     match or 0xFFFFFF  */
+    if ( (ib_inform_info_get_vend_id(p_ii) != CL_HTON32(0xFFFFFF)) &&
+         (ib_inform_info_get_vend_id(p_ii) != ib_notice_get_vend_id(p_ntc)) )
+    {
+      osm_log( p_log, OSM_LOG_DEBUG,
+               "__match_notice_to_inf_rec: "
+               "Mismatch by Vendor ID\n" );
+      goto Exit;
+    }
+  }
+  
+  /* Check if there is a pkey match. o13-17.1.1 */
+  /* Check if the issuer of the trap is the SM. If it is, then the gid
+     comparison should be done on the trap source (saved as the gid in the 
+     data details field).
+     If the issuer gid is not the SM - then it is the guid of the trap
+     source */
+  if ( (cl_ntoh64(p_ntc->issuer_gid.unicast.prefix) == p_subn->opt.subnet_prefix) && 
+       (cl_ntoh64(p_ntc->issuer_gid.unicast.interface_id) == p_subn->sm_port_guid) )
+  {
+    /* The issuer is the SM then this is trap 64-67 - compare the gid
+       with the gid saved on the data details */
+    source_gid = p_ntc->data_details.ntc_64_67.gid;
+  }
+  else 
+  {
+    source_gid = p_ntc->issuer_gid;
+  }
+  p_src_port = (osm_port_t*)cl_qmap_get( &p_subn->port_guid_tbl,
+                                         source_gid.unicast.interface_id );
+
+  if( p_src_port == (osm_port_t*)cl_qmap_end( &(p_subn->port_guid_tbl)) )
+  {
+    osm_log( p_log, OSM_LOG_INFO,
+             "__match_notice_to_inf_rec: "
+             "Cannot find source port with GUID:0x%016" PRIx64 "\n",
+             cl_ntoh64(source_gid.unicast.interface_id) );
+    goto Exit;
+  }
+
+  p_dest_port = 
+    cl_ptr_vector_get( &p_subn->port_lid_tbl,
+                       cl_ntoh16(p_infr_rec->report_addr.dest_lid) );
+  if( !p_dest_port )
+  {
+    osm_log( p_log, OSM_LOG_INFO,
+             "__match_notice_to_inf_rec: "
+             "Cannot find destination port with LID:0x%04x\n",
+             cl_ntoh16(p_infr_rec->report_addr.dest_lid) );
+    goto Exit;
+  }
+
+  if (osm_port_share_pkey( p_log, p_src_port, p_dest_port ) == FALSE )
+  {
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "__match_notice_to_inf_rec: "
+             "Mismatch by Pkey\n" );
+    /* According to o13-17.1.2 - If this informInfo does not have 
+       lid_range_begin of 0xFFFF, then this informInfo request 
+       should be removed from database */
+    if ( p_ii->lid_range_begin != 0xFFFF )
+    {
+      osm_log( p_log, OSM_LOG_VERBOSE,
+               "__match_notice_to_inf_rec: "
+               "Pkey mismatch on lid_range_begin != 0xFFFF. "
+               "Need to remove this informInfo from db\n" );
+      /* add the informInfo record to the remove_infr list */
+      cl_list_insert_tail( p_infr_to_remove_list, p_infr_rec );
+    }
+    goto Exit;
+  }
+
+  /* send the report to the address provided in the inform record */
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "__match_notice_to_inf_rec: "
+           "MATCH! Sending Report...\n" );
+  __osm_send_report( p_infr_rec, p_ntc );
+  status = CL_SUCCESS;
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+}
+
+/**********************************************************************
+ * Once a Trap was received by osm_trap_rcv, or a Trap sourced by 
+ * the SM was sent (Traps 64-67), this routine is called with a copy of
+ * the notice data.
+ * Given a notice attribute - compare and see if it matches the InformInfo
+ * element and if it does - call the Report(Notice) for the
+ * target QP registered by the address stored in the InformInfo element
+ **********************************************************************/
+ib_api_status_t
+osm_report_notice(
+  IN osm_log_t* const p_log,
+  IN osm_subn_t*  p_subn,
+  IN ib_mad_notice_attr_t *p_ntc )
+{
+  osm_infr_match_ctxt_t context;
+  cl_list_t             infr_to_remove_list;
+  osm_infr_t*           p_infr_rec;
+  osm_infr_t*           p_next_infr_rec;
+
+  OSM_LOG_ENTER( p_log, osm_report_notice );
+
+  /*
+   * we must make sure we are ready for this...
+   * note that the trap receivers might be initialized before
+   * the osm_infr_init call is performed.
+   */
+  if ( p_subn->sa_infr_list.state != CL_INITIALIZED )
+  {
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osm_report_notice: "
+             "Ignoring Notice Reports since Inform List is not initialized yet!\n" );
+    return IB_ERROR;
+  }
+
+  /* an official Event information log */
+  if ( ib_notice_is_generic(p_ntc) )
+  {
+    osm_log( p_log, OSM_LOG_INFO,
+             "osm_report_notice: "
+             "Reporting Generic Notice type:%u num:%u"
+             " from LID:0x%04X GID:0x%016" PRIx64
+                                ",0x%016" PRIx64 "\n",
+             ib_notice_get_type(p_ntc),
+             cl_ntoh16(p_ntc->g_or_v.generic.trap_num),
+             cl_ntoh16(p_ntc->issuer_lid),
+             cl_ntoh64(p_ntc->issuer_gid.unicast.prefix),
+             cl_ntoh64(p_ntc->issuer_gid.unicast.interface_id)
+             );
+  }
+  else
+  {
+    osm_log( p_log, OSM_LOG_INFO,
+             "osm_report_notice: "
+             "Reporting Vendor Notice type:%u vend:%u dev:%u"
+             " from LID:0x%04X GID:0x%016" PRIx64
+                                ",0x%016" PRIx64 "\n",
+             ib_notice_get_type(p_ntc),
+             cl_ntoh32(ib_notice_get_vend_id(p_ntc)),
+             cl_ntoh16(p_ntc->g_or_v.vend.dev_id),
+             cl_ntoh16(p_ntc->issuer_lid),
+             cl_ntoh64(p_ntc->issuer_gid.unicast.prefix),
+             cl_ntoh64(p_ntc->issuer_gid.unicast.interface_id)
+             );
+  }
+
+  /* Create a list that will hold all the infr records that should
+     be removed due to violation. o13-17.1.2 */
+  cl_list_construct( &infr_to_remove_list );
+  cl_list_init( &infr_to_remove_list, 5 );
+  context.p_remove_infr_list = &infr_to_remove_list;
+  context.p_ntc = p_ntc;
+
+  /* go over all inform info available at the subnet */
+  /* try match to the given notice and send if match */
+  cl_qlist_apply_func(&(p_subn->sa_infr_list),
+                      __match_notice_to_inf_rec,
+                      &context );
+
+  /* If we inserted items into the infr_to_remove_list - we need to
+     remove them */
+  p_infr_rec = (osm_infr_t*)cl_list_remove_head(&infr_to_remove_list);
+  while ( p_infr_rec != NULL ) 
+  {
+    p_next_infr_rec = (osm_infr_t*)cl_list_remove_head(&infr_to_remove_list);
+    osm_infr_remove_from_db ( p_subn, p_log, p_infr_rec );
+    p_infr_rec = p_next_infr_rec;
+  }
+  cl_list_destroy(&infr_to_remove_list);
+
+  OSM_LOG_EXIT( p_log );
+
+  return(IB_SUCCESS);
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lid_mgr.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lid_mgr.c
new file mode 100644 (file)
index 0000000..3e08737
--- /dev/null
@@ -0,0 +1,1494 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_lid_mgr.c 1738 2008-11-06 20:24:37Z tzachid $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_lid_mgr_t.
+ * This file implements the LID Manager object which is responsible for
+ * assigning LIDs to all ports on the subnet.
+ *
+ * DATA STRUCTURES:
+ *  p_subn->port_lid_tbl : a vector pointing from lid to its port.
+ *  osm db guid2lid domain : a hash from guid to lid (min lid).
+ *  p_subn->port_guid_tbl : a map from guid to discovered port obj.
+ *
+ * ALGORITHM:
+ *
+ * 0. we define a function to obtain the correct port lid:
+ *    __osm_lid_mgr_get_port_lid( p_mgr, port, &min_lid ):
+ *    0.1 if the port info lid matches the guid2lid return 0
+ *    0.2 if the port info has a lid and that range is empty in
+ *        port_lid_tbl, return 0 and update the port_lid_tbl and
+ *        guid2lid
+ *    0.3 else find an empty space in port_lid_tbl, update the
+ *    port_lid_tbl and guid2lid, return 1 to flag a change required.
+ *
+ * 1. During initialization:
+ *   1.1 initialize the guid2lid database domain.
+ *   1.2 if reassign_lid is not set:
+ *   1.2.1 read the persistent data for the domain.
+ *   1.2.2 validate no duplicate use of lids and lids are 2^(lmc-1)
+ *
+ * 2. During SM port lid assignment:
+ *   2.1 if reassign_lids is set, make it 2^lmc
+ *   2.2 cleanup all port_lid_tbl and re-fill it according to guid2lid
+ *   2.3 call __osm_lid_mgr_get_port_lid the SM port
+ *   2.4 set the port info
+ *
+ * 3. During all other ports lid assignment:
+ *   3.1 go through all ports in the subnet
+ *   3.1.1 call __osm_lid_mgr_get_port_min_lid
+ *   3.1.2 if a change required send the port info
+ *   3.2 if any change send the signal PENDING...
+ *
+ * 4. Store the guid2lid
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.15 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_lid_mgr.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_db_pack.h>
+#include <stdlib.h>
+
+/**********************************************************************
+  lid range item of qlist
+ **********************************************************************/
+typedef struct _osm_lid_mgr_range {
+  cl_list_item_t item;
+  uint16_t min_lid;
+  uint16_t max_lid;
+} osm_lid_mgr_range_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lid_mgr_construct(
+  IN osm_lid_mgr_t* const p_mgr )
+{
+  memset( p_mgr, 0, sizeof(*p_mgr) );
+  cl_ptr_vector_construct( &p_mgr->used_lids );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lid_mgr_destroy(
+  IN osm_lid_mgr_t* const p_mgr )
+{
+  cl_list_item_t *p_item;
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_lid_mgr_destroy );
+
+  cl_ptr_vector_destroy( &p_mgr->used_lids );
+  p_item = cl_qlist_remove_head( &p_mgr->free_ranges );
+  while ( p_item != cl_qlist_end( &p_mgr->free_ranges ) )
+  {
+    free((osm_lid_mgr_range_t *)p_item);
+    p_item = cl_qlist_remove_head( &p_mgr->free_ranges );
+  }
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+Validate the guid to lid data by making sure that under the current
+LMC we did not get duplicates. If we do flag them as errors and remove
+the entry.
+**********************************************************************/
+static void
+__osm_lid_mgr_validate_db(
+  IN osm_lid_mgr_t* p_mgr)
+{
+  cl_qlist_t         guids;
+  osm_db_guid_elem_t *p_item;
+  uint16_t           lid;
+  uint16_t           min_lid;
+  uint16_t           max_lid;
+  uint16_t           lmc_mask;
+  boolean_t          lids_ok;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_validate_db );
+
+  if (p_mgr->p_subn->opt.lmc)
+    lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1);
+  else
+    lmc_mask = 0xffff;
+
+  cl_qlist_init( &guids );
+
+  if (osm_db_guid2lid_guids( p_mgr->p_g2l, &guids ))
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "__osm_lid_mgr_validate_db: ERR 0310: "
+             "could not get guid list\n");
+    goto Exit;
+  }
+
+  p_item = (osm_db_guid_elem_t*)cl_qlist_remove_head(&guids);
+  while ((cl_list_item_t*)p_item != cl_qlist_end(&guids))
+  {
+    if (osm_db_guid2lid_get( p_mgr->p_g2l, p_item->guid, &min_lid, &max_lid ))
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_lid_mgr_validate_db: ERR 0311: "
+               "could not get lid for guid:0x%016" PRIx64 "\n",
+               p_item->guid
+               );
+    }
+    else
+    {
+      lids_ok = TRUE;
+
+      if ((min_lid > max_lid) || (min_lid == 0) || (p_item->guid == 0) ||
+          (max_lid > p_mgr->p_subn->max_unicast_lid_ho))
+      {
+        osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+                 "__osm_lid_mgr_validate_db: ERR 0312: "
+                 "Illegal LID range [0x%x:0x%x] for guid:0x%016" PRIx64
+                 "\n",
+                 min_lid, max_lid, p_item->guid
+                 );
+        lids_ok = FALSE;
+      }
+      else if ((min_lid != max_lid) && ((min_lid & lmc_mask) != min_lid))
+      {
+        /* check that if the lids define a range that is valid
+           for the current LMC mask */
+        osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+                 "__osm_lid_mgr_validate_db: ERR 0313: "
+                 "LID range [0x%x:0x%x] for guid:0x%016" PRIx64
+                 " is not aligned according to mask:0x%04x\n",
+                 min_lid, max_lid, p_item->guid, lmc_mask
+                 );
+        lids_ok = FALSE;
+      }
+      else
+      {
+        /* check if the lids were not previously assigned */
+        for (lid = min_lid; lid <= max_lid; lid++)
+        {
+          if (( cl_ptr_vector_get_size( &p_mgr->used_lids ) > lid ) &&
+              ( cl_ptr_vector_get( &p_mgr->used_lids, lid ) ) )
+          {
+            osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+                     "__osm_lid_mgr_validate_db: ERR 0314: "
+                     "0x%04x for guid:0x%016" PRIx64
+                     " was previously used\n",
+                     lid, p_item->guid
+                     );
+            lids_ok = FALSE;
+          }
+        }
+      }
+
+      if (!lids_ok)
+      {
+        if (osm_db_guid2lid_delete( p_mgr->p_g2l, p_item->guid ))
+          osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+                   "__osm_lid_mgr_validate_db: ERR 0315: "
+                   "failed to delete entry for guid:0x%016" PRIx64
+                   "\n",
+                   p_item->guid
+                   );
+      }
+      else
+      {
+        /* mark it was visited */
+        for (lid = min_lid; lid <= max_lid; lid++)
+          cl_ptr_vector_set( &p_mgr->used_lids, lid, (void *)1);
+      }
+    } /* got a lid */
+    p_item = (osm_db_guid_elem_t*)cl_qlist_remove_head(&guids);
+  } /* all guids */
+ Exit:
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lid_mgr_init(
+  IN osm_lid_mgr_t* const p_mgr,
+  IN osm_req_t* const p_req,
+  IN osm_subn_t* const p_subn,
+  IN osm_db_t*  const p_db,
+  IN osm_log_t* const p_log,
+  IN cl_plock_t* const p_lock )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_lid_mgr_init );
+
+  CL_ASSERT( p_req );
+  CL_ASSERT( p_subn );
+  CL_ASSERT( p_lock );
+  CL_ASSERT( p_db );
+
+  osm_lid_mgr_construct( p_mgr );
+
+  p_mgr->p_log = p_log;
+  p_mgr->p_subn = p_subn;
+  p_mgr->p_db = p_db;
+  p_mgr->p_lock = p_lock;
+  p_mgr->p_req = p_req;
+
+  /* we initialize and restore the db domain of guid to lid map */
+  p_mgr->p_g2l = osm_db_domain_init(p_mgr->p_db, "guid2lid");
+  if (! p_mgr->p_g2l)
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "osm_lid_mgr_init: ERR 0316: "
+             "Error initializing Guid-to-Lid persistent database\n");
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  cl_ptr_vector_init( &p_mgr->used_lids, 100, 40 );
+  cl_qlist_init( &p_mgr->free_ranges );
+
+  /* we use the stored guid to lid table if not forced to reassign */
+  if (!p_mgr->p_subn->opt.reassign_lids)
+  {
+    if (osm_db_restore(p_mgr->p_g2l))
+    {
+#ifndef __WIN__
+      /*
+       * When Windows is BSODing, it might corrupt files that were
+       * previously opened for writing, even if the files are closed.
+       * This is because of Windows write caching option.
+       * As a result, we might see corrupted guid2lid file.
+       */    
+      if (p_subn->opt.exit_on_fatal) 
+      {      
+        osm_log( p_mgr->p_log, OSM_LOG_SYS,
+                 "FATAL: Error restoring Guid-to-Lid persistent database\n" );
+        status = IB_ERROR;
+        goto Exit;
+      }
+      else
+#endif        
+      {
+        osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+                 "osm_lid_mgr_init: ERR 0317: "
+                 "Error restoring Guid-to-Lid persistent database\n");
+      }
+    }
+
+    /* we need to make sure we did not get duplicates with
+       current lmc */
+    __osm_lid_mgr_validate_db(p_mgr);
+  }
+
+Exit:
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return( status );
+}
+
+static uint16_t
+__osm_trim_lid(
+  IN uint16_t lid )
+{
+  if ((lid > IB_LID_UCAST_END_HO) ||
+      (lid < IB_LID_UCAST_START_HO))
+    return 0;
+  return lid;
+}
+
+/**********************************************************************
+ initialize the manager for a new sweep:
+ scans the known persistent assignment and port_lid_tbl
+ re-calculate all empty ranges.
+ cleanup invalid port_lid_tbl entries
+**********************************************************************/
+static int
+__osm_lid_mgr_init_sweep(
+  IN osm_lid_mgr_t* const p_mgr )
+{
+  cl_ptr_vector_t     *p_discovered_vec = &p_mgr->p_subn->port_lid_tbl;
+  cl_ptr_vector_t     *p_persistent_vec = &p_mgr->used_lids;
+  uint16_t             max_defined_lid;
+  uint16_t             max_persistent_lid;
+  uint16_t             max_discovered_lid;
+  uint16_t             lid;
+  uint16_t             disc_min_lid;
+  uint16_t             disc_max_lid;
+  uint16_t             db_min_lid;
+  uint16_t             db_max_lid;
+  int                  status = 0;
+  cl_list_item_t      *p_item;
+  boolean_t            is_free;
+  osm_lid_mgr_range_t *p_range = NULL;
+  osm_port_t          *p_port;
+  cl_qmap_t           *p_port_guid_tbl;
+  uint8_t              lmc_num_lids = (uint8_t)(1 << p_mgr->p_subn->opt.lmc);
+  uint16_t             lmc_mask;
+  uint16_t             req_lid, num_lids;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_init_sweep );
+
+  if (p_mgr->p_subn->opt.lmc)
+    lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1);
+  else
+    lmc_mask = 0xffff;
+
+  /* if we came out of standby we need to discard any previous guid2lid
+     info we might have. 
+     Do this only if the honor_guid2lid_file option is FALSE. If not, then
+     need to honor this file. */
+  if ( p_mgr->p_subn->coming_out_of_standby == TRUE )
+  {
+    if ( p_mgr->p_subn->opt.honor_guid2lid_file == FALSE )
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "__osm_lid_mgr_init_sweep: "
+               "Ignore guid2lid file when coming out of standby\n");
+      osm_db_clear( p_mgr->p_g2l );
+      for (lid = 0; lid < cl_ptr_vector_get_size(&p_mgr->used_lids); lid++)
+        cl_ptr_vector_set(p_persistent_vec, lid, NULL);
+    }
+    else
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "__osm_lid_mgr_init_sweep: "
+               "Honor current guid2lid file when coming out of standby\n");
+      osm_db_clear( p_mgr->p_g2l );
+      if (osm_db_restore(p_mgr->p_g2l))
+        osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+                 "osm_lid_mgr_init_sweep: ERR 0306: " 
+                 "Error restoring Guid-to-Lid persistent database. Ignoring it\n");
+    }
+  }
+
+  /* we need to cleanup the empty ranges list */
+  p_item = cl_qlist_remove_head( &p_mgr->free_ranges );
+  while ( p_item != cl_qlist_end( &p_mgr->free_ranges ) )
+  {
+    free( (osm_lid_mgr_range_t *)p_item );
+    p_item = cl_qlist_remove_head( &p_mgr->free_ranges );
+  }
+
+  /* first clean up the port_by_lid_tbl */
+  for (lid = 0; lid < cl_ptr_vector_get_size(p_discovered_vec); lid++)
+    cl_ptr_vector_set(p_discovered_vec, lid, NULL);
+
+  /* we if are in the first sweep and in reassign lids mode
+     we should ignore all the available info and simply define one
+     huge empty range */
+  if ((p_mgr->p_subn->first_time_master_sweep == TRUE) &&
+      (p_mgr->p_subn->opt.reassign_lids == TRUE ))
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+             "__osm_lid_mgr_init_sweep: "
+             "Skipping all lids as we are reassigning them\n");
+    p_range =
+      (osm_lid_mgr_range_t *)malloc(sizeof(osm_lid_mgr_range_t));
+    p_range->min_lid = 1;
+    goto AfterScanningLids;
+  }
+
+  /* go over all discovered ports and mark their entries */
+  p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+  for( p_port = (osm_port_t*)cl_qmap_head( p_port_guid_tbl );
+       p_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl );
+       p_port = (osm_port_t*)cl_qmap_next( &p_port->map_item ) )
+  {
+    osm_port_get_lid_range_ho(p_port, &disc_min_lid, &disc_max_lid);
+    disc_min_lid = __osm_trim_lid(disc_min_lid);
+    disc_max_lid = __osm_trim_lid(disc_max_lid);
+    for (lid = disc_min_lid; lid <= disc_max_lid; lid++)
+      cl_ptr_vector_set(p_discovered_vec, lid, p_port );
+    /* make sure the guid2lid entry is valid. If not, clean it. */
+    if (!osm_db_guid2lid_get( p_mgr->p_g2l,
+                              cl_ntoh64(osm_port_get_guid(p_port)),
+                              &db_min_lid, &db_max_lid))
+    {
+      if ( !p_port->p_node->sw ||
+           osm_switch_sp0_is_lmc_capable(p_port->p_node->sw, p_mgr->p_subn))
+        num_lids = lmc_num_lids;
+      else
+        num_lids = 1;
+
+      if ((num_lids != 1) &&
+          (((db_min_lid & lmc_mask) != db_min_lid) ||
+           (db_max_lid - db_min_lid + 1 < num_lids)) )
+      {
+        /* Not aligned, or not wide enough, then remove the entry */
+        osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+                 "__osm_lid_mgr_init_sweep: "
+                 "Cleaning persistent entry for guid:0x%016" PRIx64
+                 " illegal range:[0x%x:0x%x]\n",
+                 cl_ntoh64(osm_port_get_guid(p_port)), db_min_lid,
+                 db_max_lid );
+        osm_db_guid2lid_delete( p_mgr->p_g2l,
+                                cl_ntoh64(osm_port_get_guid(p_port)));
+        for ( lid = db_min_lid ; lid <= db_max_lid ; lid++ )
+          cl_ptr_vector_set(p_persistent_vec, lid, NULL);
+      }
+    }
+  }
+
+  /* 
+     Our task is to find free lid ranges.
+     A lid can be used if
+     1. a persistent assignment exists
+     2. the lid is used by a discovered port that does not have a persistent
+        assignment.
+     
+     scan through all lid values of both the persistent table and
+     discovered table. 
+     If the lid has an assigned port in the discovered table:
+     * make sure the lid matches the persistent table, or 
+     * there is no other persistent assignment for that lid.
+     * else cleanup the port_by_lid_tbl, mark this as empty range.
+     Else if the lid does not have an entry in the persistent table
+     mark it as free.
+  */
+
+  /* find the range of lids to scan */
+  max_discovered_lid = (uint16_t)cl_ptr_vector_get_size(p_discovered_vec);
+  max_persistent_lid = (uint16_t)cl_ptr_vector_get_size(p_persistent_vec);
+
+  /* but the vectors have one extra entry for lid=0 */
+  if (max_discovered_lid) max_discovered_lid--;
+  if (max_persistent_lid) max_persistent_lid--;
+
+  if (max_persistent_lid > max_discovered_lid)
+    max_defined_lid = max_persistent_lid;
+  else
+    max_defined_lid = max_discovered_lid;
+
+  for (lid = 1; lid <= max_defined_lid ; lid++)
+  {
+    is_free = TRUE;
+    /* first check to see if the lid is used by a persistent assignment */
+    if ((lid <= max_persistent_lid) && cl_ptr_vector_get(p_persistent_vec, lid))
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "__osm_lid_mgr_init_sweep: "
+               "0x%04x is not free as its mapped by the persistent db\n",
+               lid);
+      is_free = FALSE;
+    }
+    else
+    {
+      /* check this is a discovered port */
+      if (lid <= max_discovered_lid && (p_port = (osm_port_t *)cl_ptr_vector_get(p_discovered_vec, lid)))
+      {
+        /* we have a port. Now lets see if we can preserve its lid range. */
+        /* For that, we need to make sure:
+           1. The port has a (legal) persistency entry. Then the local lid
+              is free (we will use the persistency value).
+           2. Can the port keep its local assignment?
+              a. Make sure the lid a aligned.
+              b. Make sure all needed lids (for the lmc) are free according
+                 to persistency table.
+        */
+      /* qualify the guid of the port is not persistently mapped to 
+         another range */
+      if (!osm_db_guid2lid_get( p_mgr->p_g2l,
+                                cl_ntoh64(osm_port_get_guid(p_port)),
+                                &db_min_lid, &db_max_lid))
+      {
+          osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+                   "__osm_lid_mgr_init_sweep: "
+                   "0x%04x is free as it was discovered "
+                   "but mapped by the persistent db to [0x%04x:0x%04x]\n",
+                   lid, db_min_lid, db_max_lid);
+        }
+        else
+        {
+          /* can the port keep its assignment ? */
+          /* get the lid range of that port, and the required number
+             of lids we are about to assign to it */
+          osm_port_get_lid_range_ho(p_port, &disc_min_lid, &disc_max_lid);
+          if ( !p_port->p_node->sw ||
+               osm_switch_sp0_is_lmc_capable(p_port->p_node->sw, p_mgr->p_subn))
+          {
+            disc_max_lid = disc_min_lid + lmc_num_lids - 1;
+            num_lids = lmc_num_lids;
+          }
+          else
+            num_lids = 1;
+
+          /* Make sure the lid is aligned */
+          if ((num_lids != 1) && ((disc_min_lid & lmc_mask) != disc_min_lid))
+          {
+            /* The lid cannot be used */
+            osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+                     "__osm_lid_mgr_init_sweep: "
+                     "0x%04x is free as it was discovered "
+                     "but not aligned\n",
+                     lid );
+          }
+          else
+          {
+            /* check that all needed lids are not persistently mapped */
+            is_free = FALSE;
+            for ( req_lid = disc_min_lid + 1 ; req_lid <= disc_max_lid ; req_lid++ )
+            {
+               if ((req_lid <= max_persistent_lid) && cl_ptr_vector_get(p_persistent_vec, req_lid))
+               {
+                  osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+                           "__osm_lid_mgr_init_sweep: "
+                           "0x%04x is free as it was discovered "
+                           "but mapped\n",
+                           lid );
+                  is_free = TRUE;
+                  break;
+               }
+            }
+
+            if (is_free == FALSE)
+            {
+              /* This port will use its local lid, and consume the entire required lid range.
+                 Thus we can skip that range. */
+              /* If the disc_max_lid is greater then lid, we can skip right to it, 
+                 since we've done all neccessary checks on the lids in between. */
+              if (disc_max_lid > lid)
+                lid = disc_max_lid;
+            }
+          }
+        }
+      }
+    }
+
+    if (is_free)
+    {
+      if (p_range)
+      {
+        p_range->max_lid = lid;
+      }
+      else
+      {
+        p_range =
+          (osm_lid_mgr_range_t *)malloc(sizeof(osm_lid_mgr_range_t));
+        p_range->min_lid = lid;
+        p_range->max_lid = lid;
+      }
+    }
+    else
+    {
+      /* this lid is used so we need to finalize the previous free range */
+      if (p_range)
+      {
+        cl_qlist_insert_tail( &p_mgr->free_ranges, &p_range->item );
+        osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+                 "__osm_lid_mgr_init_sweep: "
+                 "new free lid range [0x%x:0x%x]\n",
+                 p_range->min_lid, p_range->max_lid);
+        p_range = NULL;
+      }
+    }
+  }
+
+ AfterScanningLids:
+  /* after scanning all known lids we need to extend the last range 
+     to the max allowed lid */
+  if (!p_range)
+  {
+    p_range =
+      (osm_lid_mgr_range_t *)malloc(sizeof(osm_lid_mgr_range_t));
+    /* 
+       The p_range can be NULL in one of 2 cases:
+       1. If max_defined_lid == 0. In this case, we want the entire range.
+       2. If all lids discovered in the loop where mapped. In this case,
+          no free range exists and we want to define it after the last 
+          mapped lid.
+    */
+    p_range->min_lid = lid;
+  }
+  p_range->max_lid = p_mgr->p_subn->max_unicast_lid_ho - 1;
+  cl_qlist_insert_tail( &p_mgr->free_ranges, &p_range->item );
+  osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+           "__osm_lid_mgr_init_sweep: "
+           "final free lid range [0x%x:0x%x]\n",
+           p_range->min_lid, p_range->max_lid );
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return status;
+}
+
+/**********************************************************************
+ check if the given range of lids is free 
+**********************************************************************/
+static boolean_t
+__osm_lid_mgr_is_range_not_persistent(
+  IN osm_lid_mgr_t* const p_mgr,
+  IN const uint16_t lid,
+  IN const uint16_t num_lids )
+{
+  uint16_t        i;
+  cl_status_t     status;
+  osm_port_t     *p_port;
+  const uint8_t   start_lid = (uint8_t)(1 << p_mgr->p_subn->opt.lmc);
+  const cl_ptr_vector_t* const p_tbl = &p_mgr->used_lids;
+
+  if( lid < start_lid )
+    return( FALSE );
+
+  for( i = lid; i < lid + num_lids; i++ )
+  {
+    status = cl_ptr_vector_at( p_tbl, i, (void*)&p_port );
+    if( status == CL_SUCCESS )
+    {
+      if(p_port != NULL)
+        return( FALSE );
+    }
+    else
+    {
+      /*
+        We are out of range in the array.
+        Consider all further entries "free".
+      */
+      return( TRUE );
+    }
+  }
+
+  return( TRUE );
+}
+
+/**********************************************************************
+find a free lid range
+**********************************************************************/
+static void
+__osm_lid_mgr_find_free_lid_range(
+  IN osm_lid_mgr_t* const p_mgr,
+  IN const uint8_t num_lids,
+  OUT uint16_t* const p_min_lid,
+  OUT uint16_t* const p_max_lid )
+{
+  uint16_t             lid;
+  cl_list_item_t      *p_item;
+  cl_list_item_t      *p_next_item;
+  osm_lid_mgr_range_t *p_range = NULL;
+  uint8_t              lmc_num_lids;
+  uint16_t             lmc_mask;
+
+  osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+           "__osm_lid_mgr_find_free_lid_range: "
+           "LMC = %u, number LIDs = %u\n",
+           p_mgr->p_subn->opt.lmc, num_lids );
+
+  lmc_num_lids = (1 << p_mgr->p_subn->opt.lmc );
+  if (p_mgr->p_subn->opt.lmc)
+    lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1);
+  else
+    lmc_mask = 0xffff;
+
+  /*
+    Search the list of free lid ranges for a range which is big enough
+  */
+  p_item = cl_qlist_head( &p_mgr->free_ranges );
+  while( p_item != cl_qlist_end( &p_mgr->free_ranges ) )
+  {
+    p_next_item = cl_qlist_next( p_item );
+    p_range = (osm_lid_mgr_range_t *)p_item;
+
+    lid = p_range->min_lid;
+
+    /* if we require more then one lid we must align to LMC */
+    if (num_lids > 1)
+    {
+      if ((lid & lmc_mask) != lid)
+        lid = (lid + lmc_num_lids) & lmc_mask;
+    }
+
+    /* but we can be out of the range */
+    if (lid + num_lids - 1 <= p_range->max_lid)
+    {
+      /* ok let us use that range */
+      if (lid + num_lids - 1 == p_range->max_lid)
+      {
+        /* we consumed the entire range */
+        cl_qlist_remove_item( &p_mgr->free_ranges, p_item );
+      }
+      else
+      {
+        /* only update the available range */
+        p_range->min_lid = lid + num_lids;
+      }
+
+      *p_min_lid = lid;
+      *p_max_lid = (uint16_t)(lid + num_lids - 1);
+      return;
+    }
+    p_item = p_next_item;
+  }
+
+  /*
+    Couldn't find a free range of lids.
+  */
+  *p_min_lid = *p_max_lid = 0;
+  /* if we run out of lids, give an error and abort! */
+  osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+           "__osm_lid_mgr_find_free_lid_range: ERR 0307: "
+           "OPENSM RAN OUT OF LIDS!!!\n" );
+  CL_ASSERT( 0 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_lid_mgr_cleanup_discovered_port_lid_range(
+  IN osm_lid_mgr_t* p_mgr,
+  IN osm_port_t *p_port )
+{
+  cl_ptr_vector_t *p_discovered_vec = &p_mgr->p_subn->port_lid_tbl;
+  uint16_t         lid, min_lid, max_lid;
+  uint16_t         max_tbl_lid = (uint16_t)(cl_ptr_vector_get_size( p_discovered_vec ));
+
+  osm_port_get_lid_range_ho(p_port, &min_lid, &max_lid);
+  min_lid = __osm_trim_lid(min_lid);
+  max_lid = __osm_trim_lid(max_lid);
+  for (lid = min_lid; lid <= max_lid; lid++)
+  {
+    if ((lid < max_tbl_lid ) &&
+        (p_port == (osm_port_t*)cl_ptr_vector_get(p_discovered_vec, lid)))
+      cl_ptr_vector_set(p_discovered_vec, lid, NULL );
+  }
+}
+
+/**********************************************************************
+ 0.1 if the port info lid matches the guid2lid return 0
+ 0.2 if the port info has a lid and that range is empty in
+     port_lid_tbl, return 0 and update the port_lid_tbl and
+     guid2lid
+ 0.3 else find an empty space in port_lid_tbl,  update the
+ port_lid_tbl and guid2lid, return 1 to flag a change required.
+**********************************************************************/
+static int
+__osm_lid_mgr_get_port_lid(
+  IN osm_lid_mgr_t* const p_mgr,
+  IN osm_port_t * const p_port,
+  OUT uint16_t* const p_min_lid,
+  OUT uint16_t* const p_max_lid)
+{
+  uint16_t lid, min_lid, max_lid;
+  uint64_t guid;
+  uint8_t  num_lids = (1 << p_mgr->p_subn->opt.lmc);
+  int      lid_changed = 0;
+  uint16_t lmc_mask;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_get_port_lid );
+
+  if (p_mgr->p_subn->opt.lmc)
+    lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1);
+  else
+    lmc_mask = 0xffff;
+
+  /* get the lid from the guid2lid */
+  guid = cl_ntoh64( osm_port_get_guid( p_port ) );
+
+  /* if the port is a base switch port 0 then we only need one lid */
+  if( p_port->p_node->sw &&
+      !osm_switch_sp0_is_lmc_capable(p_port->p_node->sw, p_mgr->p_subn))
+    num_lids = 1;
+
+  /* if the port matches the guid2lid */
+  if (!osm_db_guid2lid_get( p_mgr->p_g2l, guid, &min_lid, &max_lid))
+  {
+    *p_min_lid = min_lid;
+    *p_max_lid = min_lid + num_lids - 1;
+    if (min_lid == cl_ntoh16(osm_port_get_base_lid(p_port)))
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "__osm_lid_mgr_get_port_lid: "
+               "0x%016" PRIx64" matches its known lid:0x%04x\n",
+               guid, min_lid );
+      goto Exit;
+    }
+    else
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "__osm_lid_mgr_get_port_lid: "
+               "0x%016" PRIx64
+               " with lid:0x%04x does not match its known lid:0x%04x\n",
+               guid, cl_ntoh16(osm_port_get_base_lid(p_port)), min_lid);
+      __osm_lid_mgr_cleanup_discovered_port_lid_range( p_mgr, p_port );
+      /* we still need to send the setting to the target port */
+      lid_changed = 1;
+      goto Exit;
+    }
+  }
+  else
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+             "__osm_lid_mgr_get_port_lid: "
+             "0x%016" PRIx64" has no persistent lid assigned\n",
+             guid );
+  }
+
+  /* if the port info carries a lid it must be lmc aligned and not mapped
+     by the pesistent storage  */
+  min_lid = cl_ntoh16(osm_port_get_base_lid(p_port));
+  
+  /* we want to ignore the discovered lid if we are also on first sweep of
+     reassign lids flow */
+  if (min_lid &&
+      ! ((p_mgr->p_subn->first_time_master_sweep == TRUE) &&
+         (p_mgr->p_subn->opt.reassign_lids == TRUE )))
+  {
+    /* make sure lid is valid */
+    if ((num_lids == 1) || ((min_lid & lmc_mask) == min_lid))
+    {
+      /* is it free */
+      if (__osm_lid_mgr_is_range_not_persistent(p_mgr, min_lid, num_lids))
+      {
+        *p_min_lid = min_lid;
+        *p_max_lid = min_lid + num_lids - 1;
+        osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+                 "__osm_lid_mgr_get_port_lid: "
+                 "0x%016" PRIx64" lid range:[0x%x-0x%x] is free\n",
+                 guid, *p_min_lid, *p_max_lid );
+        goto NewLidSet;
+      }
+      else
+      {
+        osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+                 "__osm_lid_mgr_get_port_lid: "
+                 "0x%016" PRIx64
+                 " existing lid range:[0x%x:0x%x] is not free\n",
+                 guid, min_lid, min_lid + num_lids - 1 );
+      }
+    }
+    else
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "__osm_lid_mgr_get_port_lid: "
+               "0x%016" PRIx64
+               " existing lid range:[0x%x:0x%x] is not lmc aligned\n",
+               guid, min_lid, min_lid + num_lids - 1 );
+    }
+  }
+
+  /* first cleanup the existing discovered lid range */
+  __osm_lid_mgr_cleanup_discovered_port_lid_range( p_mgr, p_port );
+
+  /* find an empty space */
+  __osm_lid_mgr_find_free_lid_range(p_mgr, num_lids, p_min_lid, p_max_lid);
+  osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+           "__osm_lid_mgr_get_port_lid: "
+           "0x%016" PRIx64" assigned a new lid range:[0x%x-0x%x]\n",
+           guid, *p_min_lid, *p_max_lid );
+  lid_changed = 1;
+
+ NewLidSet:
+  /* update the guid2lid db and used_lids */
+  osm_db_guid2lid_set(p_mgr->p_g2l, guid, *p_min_lid, *p_max_lid);
+  for (lid = *p_min_lid; lid <= *p_max_lid; lid++)
+    cl_ptr_vector_set(&p_mgr->used_lids, lid, (void*)1);
+
+ Exit:
+  /* make sure the assigned lids are marked in port_lid_tbl */
+  for (lid = *p_min_lid; lid <= *p_max_lid; lid++)
+    cl_ptr_vector_set(&p_mgr->p_subn->port_lid_tbl, lid, p_port);
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return lid_changed;
+}
+
+/**********************************************************************
+ Set to INIT the remote port of the given physical port
+ **********************************************************************/
+static void
+__osm_lid_mgr_set_remote_pi_state_to_init(
+  IN osm_lid_mgr_t *       const p_mgr,
+  IN osm_physp_t*          const p_physp)
+{
+  ib_port_info_t *p_pi;
+  osm_physp_t *p_rem_physp = osm_physp_get_remote(p_physp);
+
+  if ( p_rem_physp == NULL )
+    return;
+
+  if (osm_physp_is_valid( p_rem_physp ))
+  {
+    p_pi = osm_physp_get_port_info_ptr( p_rem_physp );
+    /* but in some rare cases the remote side might be irresponsive  */
+    if (p_pi)
+      ib_port_info_set_port_state( p_pi, IB_LINK_INIT );
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+__osm_lid_mgr_set_physp_pi(
+  IN osm_lid_mgr_t *    const p_mgr,
+  IN osm_port_t*        const p_port,
+  IN osm_physp_t*       const p_physp,
+  IN ib_net16_t         const lid )
+{
+  uint8_t               payload[IB_SMP_DATA_SIZE];
+  ib_port_info_t*       p_pi = (ib_port_info_t*)payload;
+  const ib_port_info_t* p_old_pi;
+  osm_madw_context_t    context;
+  osm_node_t*           p_node;
+  ib_api_status_t       status;
+  uint8_t               mtu;
+  uint8_t               op_vls;
+  uint8_t               port_num;
+  boolean_t             send_set = FALSE;
+  boolean_t             new_port = FALSE;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_set_physp_pi );
+
+  /*
+    Don't bother doing anything if this Physical Port is not valid.
+    This allows simplified code in the caller.
+  */
+  if( p_physp == NULL )
+    goto Exit;
+
+  if( !osm_physp_is_valid( p_physp ) )
+    goto Exit;
+
+  port_num = osm_physp_get_port_num( p_physp );
+  p_node = osm_physp_get_node_ptr( p_physp );
+
+  if( (osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH ) &&
+      (port_num != 0) )
+  {
+    /*
+      Switch ports that are not numbered 0 should not be set with the
+      following attributes as they are set later (during NO_CHANGE state
+      in link mgr).
+    */
+    if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "__osm_lid_mgr_set_physp_pi: "
+               "Skipping switch port %u, GUID 0x%016" PRIx64 "\n",
+               port_num,
+               cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) );
+    }
+    goto Exit;
+  }
+
+  p_old_pi = osm_physp_get_port_info_ptr( p_physp );
+
+  /*
+    First, copy existing parameters from the PortInfo attribute we
+    already have for this node.
+
+    Second, update with default values that we know must be set for
+    every Physical Port and the LID and set the neighbor MTU field
+    appropriately.
+
+    Third, send the SMP to this physical port.
+  */
+
+  memset( payload, 0, IB_SMP_DATA_SIZE );
+
+  /* Correction by FUJITSU */
+  if( port_num != 0 )
+  {
+    memcpy( payload, p_old_pi, sizeof(ib_port_info_t) );
+  }
+
+  /*
+    Correction following a bug injected by the previous
+    FUJITSU line:
+
+    Should never write back a value that is bigger then 3 in
+    the PortPhysicalState field, so cannot simply copy!
+
+    Actually we want to write there:
+    port physical state - no change
+    link down default state = polling
+    port state - no change
+  */
+  /* these values can be set only for hca ports, so if we are
+     on a switch node, set these values to zero */
+  if ( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH )
+    p_pi->state_info2 = 0x0;
+  else
+  {
+    p_pi->state_info2 = 0x02;
+    /* Check to see if the value we are setting is different than
+       the value in the port_info. If it is, turn on send_set flag */
+    if ( ib_port_info_get_link_down_def_state(p_pi) !=
+         ib_port_info_get_link_down_def_state(p_old_pi) )
+      send_set = TRUE;
+  }
+
+  ib_port_info_set_port_state( p_pi, IB_LINK_NO_CHANGE );
+
+  p_pi->m_key = p_mgr->p_subn->opt.m_key;
+  /* Check to see if the value we are setting is different than
+     the value in the port_info. If it is, turn on send_set flag */
+  if (memcmp( &p_pi->m_key, &p_old_pi->m_key, sizeof(p_pi->m_key) ))
+    send_set = TRUE;
+
+  p_pi->subnet_prefix = p_mgr->p_subn->opt.subnet_prefix;
+  /* Check to see if the value we are setting is different than
+     the value in the port_info. If it is, turn on send_set flag */
+  if (memcmp( &p_pi->subnet_prefix, &p_old_pi->subnet_prefix,
+              sizeof(p_pi->subnet_prefix) ))
+    send_set = TRUE;
+
+  p_pi->base_lid = lid;
+  /* Check to see if the value we are setting is different than
+     the value in the port_info. If it is, turn on send_set flag */
+  if (memcmp( &p_pi->base_lid, &p_old_pi->base_lid,
+              sizeof(p_pi->base_lid) ))
+    send_set = TRUE;
+
+  /* we are updating the ports with our local sm_base_lid */
+  p_pi->master_sm_base_lid = p_mgr->p_subn->sm_base_lid;
+  /* Check to see if the value we are setting is different than
+     the value in the port_info. If it is, turn on send_set flag */
+  if (memcmp( &p_pi->master_sm_base_lid, &p_old_pi->master_sm_base_lid,
+              sizeof(p_pi->master_sm_base_lid) ))
+    send_set = TRUE;
+
+  p_pi->m_key_lease_period = p_mgr->p_subn->opt.m_key_lease_period;
+  /* Check to see if the value we are setting is different than
+     the value in the port_info. If it is, turn on send_set flag */
+  if (memcmp( &p_pi->m_key_lease_period, &p_old_pi->m_key_lease_period,
+              sizeof(p_pi->m_key_lease_period) ))
+    send_set = TRUE;
+
+  /*
+    we want to set the timeout for both the switch port 0
+    and the HCA ports
+  */
+  ib_port_info_set_timeout( p_pi, p_mgr->p_subn->opt.subnet_timeout );
+  /* Check to see if the value we are setting is different than
+     the value in the port_info. If it is, turn on send_set flag */
+  if (ib_port_info_get_timeout( p_pi ) != ib_port_info_get_timeout( p_old_pi ))
+    send_set = TRUE;
+
+  if( port_num != 0 )
+  {
+    /*
+      HCA's don't have a port 0, and for switch port 0,
+      the state bits are ignored.
+      This is not the switch management port
+    */
+    p_pi->link_width_enabled = p_old_pi->link_width_supported;
+    /* Check to see if the value we are setting is different than
+       the value in the port_info. If it is, turn on send_set flag */
+    if (memcmp( &p_pi->link_width_enabled, &p_old_pi->link_width_enabled,
+                sizeof(p_pi->link_width_enabled) ))
+      send_set = TRUE;
+
+    if ( p_mgr->p_subn->opt.force_link_speed )
+      ib_port_info_set_link_speed_enabled( p_pi, IB_LINK_SPEED_ACTIVE_2_5 );
+    else if (ib_port_info_get_link_speed_enabled( p_old_pi ) != ib_port_info_get_link_speed_sup( p_pi ))
+      ib_port_info_set_link_speed_enabled( p_pi, IB_PORT_LINK_SPEED_ENABLED_MASK );
+    else
+      ib_port_info_set_link_speed_enabled( p_pi, ib_port_info_get_link_speed_enabled( p_old_pi ));
+    if (memcmp( &p_pi->link_speed, &p_old_pi->link_speed,
+                sizeof(p_pi->link_speed) ))
+      send_set = TRUE;
+
+    /* M_KeyProtectBits are always zero */
+    p_pi->mkey_lmc = p_mgr->p_subn->opt.lmc;
+    /* Check to see if the value we are setting is different than
+       the value in the port_info. If it is, turn on send_set flag */
+    if (memcmp( &p_pi->mkey_lmc, &p_old_pi->mkey_lmc, sizeof(p_pi->mkey_lmc) ))
+      send_set = TRUE;
+
+    /* calc new op_vls and mtu */
+    op_vls = osm_physp_calc_link_op_vls(
+      p_mgr->p_log, p_mgr->p_subn, p_physp );
+    mtu = osm_physp_calc_link_mtu( p_mgr->p_log, p_physp );
+
+    ib_port_info_set_neighbor_mtu( p_pi, mtu );
+
+    if ( ib_port_info_get_neighbor_mtu(p_pi) !=
+         ib_port_info_get_neighbor_mtu(p_old_pi) )
+      send_set = TRUE;
+
+    ib_port_info_set_op_vls( p_pi, op_vls );
+    if ( ib_port_info_get_op_vls(p_pi) !=
+         ib_port_info_get_op_vls(p_old_pi) )
+      send_set = TRUE;
+
+    /*
+      Several timeout mechanisms:
+    */
+    ib_port_info_set_phy_and_overrun_err_thd(
+      p_pi,
+      p_mgr->p_subn->opt.local_phy_errors_threshold,
+      p_mgr->p_subn->opt.overrun_errors_threshold);
+
+    if (memcmp( &p_pi->error_threshold, &p_old_pi->error_threshold,
+                sizeof(p_pi->error_threshold) ))
+      send_set = TRUE;
+
+    /*
+      To reset the port state machine we can send PortInfo.State = DOWN.
+      (see: 7.2.7 p171 lines:10-19)
+    */
+    if ( (mtu != ib_port_info_get_neighbor_mtu(p_old_pi)) ||
+         (op_vls !=  ib_port_info_get_op_vls(p_old_pi)))
+    {
+      if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+      {
+        osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+                 "__osm_lid_mgr_set_physp_pi: "
+                 "Sending Link Down due to op_vls or mtu change. MTU:%u,%u VL_CAP:%u,%u\n",
+                 mtu, ib_port_info_get_neighbor_mtu(p_old_pi),
+                 op_vls, ib_port_info_get_op_vls(p_old_pi)
+                 );
+      }
+
+      /* 
+         we need to make sure the internal DB will follow the fact the remote
+         port is also going through "down" state into "init"...
+      */
+      __osm_lid_mgr_set_remote_pi_state_to_init(p_mgr, p_physp);
+
+      ib_port_info_set_port_state( p_pi, IB_LINK_DOWN );
+      if ( ib_port_info_get_port_state(p_pi) !=
+           ib_port_info_get_port_state(p_old_pi) )
+        send_set = TRUE;
+    }
+  }
+  else
+  {
+    /*
+      For Port 0, NeighborMTU is relevant only for Enh. SP0.
+      In this case, we'll set the MTU according to the mtu_cap
+    */
+    ib_port_info_set_neighbor_mtu( p_pi, ib_port_info_get_mtu_cap( p_old_pi ) );
+    if ( ib_port_info_get_neighbor_mtu(p_pi) !=
+         ib_port_info_get_neighbor_mtu(p_old_pi) )
+      send_set = TRUE;
+
+    osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+             "__osm_lid_mgr_set_physp_pi: "
+             "Updating neighbor_mtu on switch port 0 to:%u\n",
+             ib_port_info_get_neighbor_mtu( p_pi ) );
+
+    /* Determine if enhanced switch port 0 and if so set LMC */
+    if (osm_switch_sp0_is_lmc_capable(p_node->sw, p_mgr->p_subn))
+    {
+      /* M_KeyProtectBits are always zero */
+      p_pi->mkey_lmc = p_mgr->p_subn->opt.lmc;
+      /* Check to see if the value we are setting is different than
+         the value in the port_info. If it is, turn on send_set flag */
+      if (memcmp( &p_pi->mkey_lmc, &p_old_pi->mkey_lmc, sizeof(p_pi->mkey_lmc) ))
+        send_set = TRUE;
+    }
+  }
+
+  context.pi_context.node_guid = osm_node_get_node_guid( p_node );
+  context.pi_context.port_guid = osm_physp_get_port_guid( p_physp );
+  context.pi_context.set_method = TRUE;
+  context.pi_context.update_master_sm_base_lid = FALSE;
+  context.pi_context.ignore_errors = FALSE;
+  context.pi_context.light_sweep = FALSE;
+  context.pi_context.active_transition = FALSE;
+
+  /*
+    We need to set the cli_rereg bit when we are in first_time_master_sweep for
+    ports supporting the ClientReregistration Vol1 (v1.2) p811 14.4.11
+    Also, if this port was just now discovered, then we should also set the
+    cli_rereg bit. We know that the port was just discovered if it is in 
+    the p_subn->new_ports_list list.
+  */
+  if ( cl_is_object_in_list(&p_mgr->p_subn->new_ports_list, p_port) )
+  {
+    /* p_port is in new_ports_list, mark new_port as TRUE */
+    new_port = TRUE;
+  }
+
+  if ( ( p_mgr->p_subn->first_time_master_sweep == TRUE || 
+         new_port == TRUE ) &&
+       !p_mgr->p_subn->opt.no_clients_rereg &&
+       ( (p_old_pi->capability_mask & IB_PORT_CAP_HAS_CLIENT_REREG) != 0 ) )
+    ib_port_info_set_client_rereg( p_pi, 1 );
+  else
+    ib_port_info_set_client_rereg( p_pi, 0 );
+
+  /* We need to send the PortInfo Set request with the new sm_lid
+     in the following cases:
+     1. There is a change in the values (send_set == TRUE)
+     2. first_time_master_sweep flag on the subnet is TRUE. This means the
+     SM just became master, and it then needs to send a PortInfo Set to
+     every port.
+     3. got_set_resp on the physical port is FALSE. This means we haven't seen
+     this port before and we need to send Set of PortInfo to it.
+  */
+  if (send_set || p_mgr->p_subn->first_time_master_sweep == TRUE ||
+      p_physp->got_set_resp == FALSE)
+  {
+
+    p_mgr->send_set_reqs = TRUE;
+    status = osm_req_set( p_mgr->p_req,
+                          osm_physp_get_dr_path_ptr( p_physp ),
+                          payload,
+                          sizeof(payload),
+                          IB_MAD_ATTR_PORT_INFO,
+                          cl_hton32(osm_physp_get_port_num( p_physp )),
+                          CL_DISP_MSGID_NONE,
+                          &context );
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return (send_set || p_mgr->p_subn->first_time_master_sweep == TRUE ||
+          p_physp->got_set_resp == FALSE);
+}
+
+/**********************************************************************
+ Processes our own node
+ Lock must already be held.
+**********************************************************************/
+static boolean_t
+__osm_lid_mgr_process_our_sm_node(
+  IN osm_lid_mgr_t* const p_mgr )
+{
+  osm_port_t     *p_port;
+  uint16_t        min_lid_ho;
+  uint16_t        max_lid_ho;
+  osm_physp_t    *p_physp;
+  boolean_t       res = TRUE;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_process_our_sm_node );
+
+  /*
+    Acquire our own port object.
+  */
+  p_port = (osm_port_t*)cl_qmap_get( &p_mgr->p_subn->port_guid_tbl,
+                                     p_mgr->p_subn->sm_port_guid );
+
+  if( p_port == (osm_port_t*)cl_qmap_end( &p_mgr->p_subn->port_guid_tbl ) )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "__osm_lid_mgr_process_our_sm_node: ERR 0308: "
+             "Can't acquire SM's port object, GUID 0x%016" PRIx64 "\n",
+             cl_ntoh64( p_mgr->p_subn->sm_port_guid ) );
+    res = FALSE;
+    goto Exit;
+  }
+
+  /*
+    Determine the LID this SM will use for its own port.
+    Be careful.  With an LMC > 0, the bottom of the LID range becomes
+    unusable, since port hardware will mask off least significant bits,
+    leaving a LID of 0 (invalid).  Therefore, make sure that we always
+    configure the SM with a LID that has non-zero bits, even after
+    LMC masking by hardware.
+  */
+  __osm_lid_mgr_get_port_lid(p_mgr, p_port, &min_lid_ho, &max_lid_ho);
+  osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+           "__osm_lid_mgr_process_our_sm_node: "
+           "Current base LID is 0x%X\n", min_lid_ho );
+  /*
+    Update subnet object.
+  */
+  p_mgr->p_subn->master_sm_base_lid = cl_hton16( min_lid_ho );
+  p_mgr->p_subn->sm_base_lid = cl_hton16( min_lid_ho );
+
+  if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+             "__osm_lid_mgr_process_our_sm_node: "
+             "Assigning SM's port 0x%016" PRIx64
+             "\n\t\t\t\tto LID range [0x%X,0x%X]\n",
+             cl_ntoh64( osm_port_get_guid( p_port ) ),
+             min_lid_ho, max_lid_ho );
+  }
+
+  /*
+    Set the PortInfo the Physical Port associated
+    with this Port.
+  */
+  p_physp = osm_port_get_default_phys_ptr( p_port );
+
+  __osm_lid_mgr_set_physp_pi( p_mgr, p_port, p_physp, cl_hton16( min_lid_ho ) );
+
+ Exit:
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return res;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_signal_t
+osm_lid_mgr_process_sm(
+  IN osm_lid_mgr_t*        const p_mgr )
+{
+  osm_signal_t          signal = OSM_SIGNAL_DONE_PENDING;
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_lid_mgr_process_sm );
+
+  CL_ASSERT( p_mgr->p_subn->sm_port_guid );
+
+  CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
+
+  /* initialize the port_lid_tbl and empty ranges list following the
+     persistent db */
+  __osm_lid_mgr_init_sweep( p_mgr );
+
+  if (p_mgr->p_subn->opt.pfn_ui_pre_lid_assign)
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+             "osm_lid_mgr_process_sm: "
+             "Invoking UI function pfn_ui_pre_lid_assign\n" );
+    p_mgr->p_subn->opt.pfn_ui_pre_lid_assign(
+      p_mgr->p_subn->opt.ui_pre_lid_assign_ctx );
+  }
+
+  /* Set the send_set_reqs of the p_mgr to FALSE, and
+     we'll see if any set requests were sent. If not -
+     can signal OSM_SIGNAL_DONE */
+  p_mgr->send_set_reqs = FALSE;
+  if ( __osm_lid_mgr_process_our_sm_node( p_mgr ) == FALSE )
+    /* The initialization failed */
+    signal = OSM_SIGNAL_DONE;
+
+  if ( p_mgr->send_set_reqs == FALSE )
+    signal = OSM_SIGNAL_DONE;
+
+  CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return( signal );
+}
+
+/**********************************************************************
+ 1 go through all ports in the subnet.
+ 1.1 call __osm_lid_mgr_get_port_min_lid
+ 1.2 if a change is required send the port info
+ 2 if any change send the signal PENDING...
+**********************************************************************/
+osm_signal_t
+osm_lid_mgr_process_subnet(
+  IN osm_lid_mgr_t*        const p_mgr )
+{
+  osm_signal_t    signal;
+  cl_qmap_t      *p_port_guid_tbl;
+  osm_port_t     *p_port;
+  ib_net64_t      port_guid;
+  uint16_t        min_lid_ho, max_lid_ho;
+  osm_physp_t    *p_physp;
+  int             lid_changed;
+
+  CL_ASSERT( p_mgr );
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_lid_mgr_process_subnet );
+
+  CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
+
+  CL_ASSERT( p_mgr->p_subn->sm_port_guid );
+
+  /* Set the send_set_reqs of the p_mgr to FALSE, and
+     we'll see if any set requests were sent. If not -
+     can signal OSM_SIGNAL_DONE */
+  p_mgr->send_set_reqs = FALSE;
+
+  p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+  for( p_port = (osm_port_t*)cl_qmap_head( p_port_guid_tbl );
+       p_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl );
+       p_port = (osm_port_t*)cl_qmap_next( &p_port->map_item ) )
+  {
+    port_guid = osm_port_get_guid( p_port );
+
+    /*
+      Our own port is a special case in that we want to
+      assign a LID to ourselves first, since we have to
+      advertise that LID value to the other ports.
+
+      For that reason, our node is treated separately and
+      we will not add it to any of these lists.
+    */
+    if( port_guid == p_mgr->p_subn->sm_port_guid )
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "osm_lid_mgr_process_subnet: "
+               "Skipping our own port 0x%016" PRIx64 "\n",
+               cl_ntoh64( port_guid ) );
+    }
+    else
+    {
+      /*
+        get the port lid range - we need to send it on first active sweep or
+        if there was a change (the result of the __osm_lid_mgr_get_port_lid)
+      */
+      lid_changed =
+        __osm_lid_mgr_get_port_lid(p_mgr, p_port, &min_lid_ho, &max_lid_ho);
+
+      /* we can call the function to update the port info as it known to 
+         look for any field change and will only send an updated if required */
+      osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+               "osm_lid_mgr_process_subnet: "
+               "Assigned port 0x%016" PRIx64
+               ", LID [0x%X,0x%X]\n", cl_ntoh64( port_guid ),
+               min_lid_ho, max_lid_ho );
+      
+      p_physp = osm_port_get_default_phys_ptr( p_port );
+      /* the proc returns the fact it sent a set port info */
+      if (__osm_lid_mgr_set_physp_pi( p_mgr, p_port, p_physp, cl_hton16( min_lid_ho )))
+        p_mgr->send_set_reqs = TRUE;
+    }
+  } /* all ports */
+
+  /* store the guid to lid table in persistent db */
+  osm_db_store( p_mgr->p_g2l );
+
+  if ( p_mgr->send_set_reqs == FALSE )
+    signal = OSM_SIGNAL_DONE;
+  else
+    signal = OSM_SIGNAL_DONE_PENDING;
+
+  CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return( signal );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lin_fwd_rcv.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lin_fwd_rcv.c
new file mode 100644 (file)
index 0000000..928cf84
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_lin_fwd_rcv.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_lft_rcv_t.
+ * This object represents the NodeDescription Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_lin_fwd_rcv.h>
+#include <opensm/osm_switch.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lft_rcv_construct(
+  IN osm_lft_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lft_rcv_destroy(
+  IN osm_lft_rcv_t* const p_rcv )
+{
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_lft_rcv_destroy );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lft_rcv_init(
+  IN osm_lft_rcv_t* const p_rcv,
+  IN osm_subn_t* const p_subn,
+  IN osm_log_t* const p_log,
+  IN cl_plock_t* const p_lock )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_lft_rcv_init );
+
+  osm_lft_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lft_rcv_process(
+  IN const osm_lft_rcv_t* const p_rcv,
+  IN osm_madw_t* const p_madw )
+{
+  ib_smp_t *p_smp;
+  uint32_t block_num;
+  osm_switch_t *p_sw;
+  osm_lft_context_t *p_lft_context;
+  uint8_t *p_block;
+  ib_net64_t node_guid;
+  ib_api_status_t status;
+
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_lft_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+  p_block = (uint8_t*)ib_smp_get_payload_ptr( p_smp );
+  block_num = cl_ntoh32( p_smp->attr_mod );
+
+  /*
+    Acquire the switch object for this switch.
+  */
+  p_lft_context = osm_madw_get_lft_context_ptr( p_madw );
+  node_guid = p_lft_context->node_guid;
+
+  CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
+  p_sw = osm_get_switch_by_guid( p_rcv->p_subn, node_guid );
+
+  if( !p_sw )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_lft_rcv_process: ERR 0401: "
+             "LFT received for nonexistent node "
+             "0x%" PRIx64 "\n", cl_ntoh64( node_guid ) );
+  }
+  else
+  {
+    status = osm_switch_set_ft_block( p_sw, p_block, block_num );
+    if( status != IB_SUCCESS )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_lft_rcv_process: ERR 0402: "
+               "Setting forwarding table block failed (%s)"
+               "\n\t\t\t\tSwitch 0x%" PRIx64 "\n",
+               ib_get_err_str( status ),
+               cl_ntoh64( node_guid ) );
+    }
+  }
+
+  CL_PLOCK_RELEASE( p_rcv->p_lock );
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lin_fwd_rcv_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lin_fwd_rcv_ctrl.c
new file mode 100644 (file)
index 0000000..d84328d
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_lin_fwd_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_lft_rcv_ctrl_t.
+ * This object represents the LFT Receive controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_lin_fwd_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_lft_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_lft_rcv_process( ((osm_lft_rcv_ctrl_t*)context)->p_rcv,
+                       (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lft_rcv_ctrl_construct(
+  IN osm_lft_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lft_rcv_ctrl_destroy(
+  IN osm_lft_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lft_rcv_ctrl_init(
+  IN osm_lft_rcv_ctrl_t* const p_ctrl,
+  IN osm_lft_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_lft_rcv_ctrl_init );
+
+  osm_lft_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_LFT,
+    __osm_lft_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_lft_rcv_ctrl_init: ERR 1601: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lin_fwd_tbl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_lin_fwd_tbl.c
new file mode 100644 (file)
index 0000000..fe0bfbd
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_lin_fwd_tbl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_lin_fwd_tbl_t.
+ * This object represents an linear forwarding table.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_math.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_lin_fwd_tbl.h>
+
+
+inline size_t
+__osm_lin_tbl_compute_obj_size(
+  IN const uint32_t num_ports )
+{
+  return( sizeof(osm_lin_fwd_tbl_t) + (num_ports - 1) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_lin_fwd_tbl_t*
+osm_lin_tbl_new(
+  IN uint16_t const size )
+{
+  osm_lin_fwd_tbl_t* p_tbl;
+
+  /*
+    The capacity reported by the switch includes LID 0,
+    so add 1 to the end of the range here for this assert.
+  */
+  CL_ASSERT( size <= IB_LID_UCAST_END_HO + 1 );
+  p_tbl = (osm_lin_fwd_tbl_t*)malloc(
+    __osm_lin_tbl_compute_obj_size( size ) );
+
+  /*
+    Initialize the table to OSM_NO_PATH, which means "invalid port"
+  */
+  memset( p_tbl, OSM_NO_PATH, __osm_lin_tbl_compute_obj_size( size ) );
+  if( p_tbl != NULL )
+  {
+    p_tbl->size = (uint16_t)size;
+  }
+  return( p_tbl );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lin_tbl_delete(
+  IN osm_lin_fwd_tbl_t** const pp_tbl )
+{
+  free( *pp_tbl );
+  *pp_tbl = NULL;
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_link_mgr.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_link_mgr.c
new file mode 100644 (file)
index 0000000..60de51d
--- /dev/null
@@ -0,0 +1,514 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_link_mgr.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_link_mgr_t.
+ * This file implements the Link Manager object.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.15 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_link_mgr.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_link_mgr_construct(
+  IN osm_link_mgr_t* const p_mgr )
+{
+  memset( p_mgr, 0, sizeof(*p_mgr) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_link_mgr_destroy(
+  IN osm_link_mgr_t* const p_mgr )
+{
+  OSM_LOG_ENTER( p_mgr->p_log, osm_link_mgr_destroy );
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_link_mgr_init(
+  IN osm_link_mgr_t* const p_mgr,
+  IN osm_req_t* const p_req,
+  IN osm_subn_t* const p_subn,
+  IN osm_log_t* const p_log,
+  IN cl_plock_t* const p_lock )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_link_mgr_init );
+
+  CL_ASSERT( p_req );
+  CL_ASSERT( p_subn );
+  CL_ASSERT( p_lock );
+
+  osm_link_mgr_construct( p_mgr );
+
+  p_mgr->p_log = p_log;
+  p_mgr->p_subn = p_subn;
+  p_mgr->p_lock = p_lock;
+  p_mgr->p_req = p_req;
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_link_mgr_set_physp_pi(
+  IN osm_link_mgr_t*       const p_mgr,
+  IN osm_physp_t*          const p_physp,
+  IN uint8_t               const port_state )
+{
+  uint8_t                  payload[IB_SMP_DATA_SIZE];
+  ib_port_info_t*          const p_pi = (ib_port_info_t*)payload;
+  const ib_port_info_t*    p_old_pi;
+  osm_madw_context_t       context;
+  osm_node_t*              p_node;
+  ib_api_status_t          status;
+  uint8_t                  port_num;
+  uint8_t                  mtu;
+  uint8_t                  op_vls;
+  boolean_t                esp0 = FALSE;
+  boolean_t                send_set = FALSE;
+  osm_physp_t             *p_remote_physp;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_link_mgr_set_physp_pi );
+
+  CL_ASSERT( p_physp );
+  CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+  p_node = osm_physp_get_node_ptr( p_physp );
+
+  port_num = osm_physp_get_port_num( p_physp );
+
+  if( port_num == 0 )
+  {
+    ib_switch_info_t* p_sw_info;
+
+    /*
+      HCA's don't have a port 0, and for switch port 0,
+      we need to check if this is enhanced port 0 or base port 0.
+      For base port 0 the following parameters are not valid. (p824, table 145)
+    */
+    if (!p_node->sw)
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_link_mgr_set_physp_pi: ERR 4201: "
+               "Cannot find switch by guid: 0x%" PRIx64 "\n",
+               cl_ntoh64( p_node->node_info.node_guid ) );
+      goto Exit;
+    }
+     
+    p_sw_info = osm_switch_get_si_ptr(p_node->sw);
+    if (ib_switch_info_is_enhanced_port0( p_sw_info ) == FALSE)
+    {
+      /* This means the switch doesn't support enhanced port zero. 
+         Can skip it. */
+      if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+      {
+        osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+                 "__osm_link_mgr_set_physp_pi: "
+                 "Skipping port 0, GUID 0x%016" PRIx64 "\n",
+                 cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) );
+      }
+      goto Exit;
+    }
+    esp0 = TRUE;
+  }
+
+  /*
+    PAST THIS POINT WE ARE HANDLING EITHER A NON PORT 0 OR ENHANCED PORT 0
+  */
+
+  p_old_pi = osm_physp_get_port_info_ptr( p_physp );
+
+  memset( payload, 0, IB_SMP_DATA_SIZE );
+
+  /* Correction by FUJITSU */
+  memcpy( payload, p_old_pi, sizeof(ib_port_info_t) );
+
+  /*
+    Correction following a bug injected by the previous
+    FUJITSU line:
+
+    Should never write back a value that is bigger then 3 in
+    the PortPhysicalState field - so can not simply copy!
+
+    Actually we want to write there:
+    port physical state - no change,
+    link down default state = polling
+    port state - no change
+  */
+  p_pi->state_info2 = 0x02;
+  ib_port_info_set_port_state( p_pi, IB_LINK_NO_CHANGE );
+  if ( ib_port_info_get_link_down_def_state(p_pi) != 
+       ib_port_info_get_link_down_def_state(p_old_pi) )
+    send_set = TRUE;
+
+  /* we only change port fields if we do not change state */
+  if (port_state == IB_LINK_NO_CHANGE)
+  {
+    /* The following fields are relevant only for CA port or Enh. SP0 */
+    if( osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH ||
+        port_num == 0 )
+    {
+      p_pi->m_key = p_mgr->p_subn->opt.m_key;
+      if (memcmp( &p_pi->m_key, &p_old_pi->m_key, sizeof(p_pi->m_key) ))
+        send_set = TRUE;
+
+      p_pi->subnet_prefix = p_mgr->p_subn->opt.subnet_prefix;
+      if (memcmp( &p_pi->subnet_prefix, &p_old_pi->subnet_prefix, 
+                  sizeof(p_pi->subnet_prefix) ))
+        send_set = TRUE;
+
+      p_pi->base_lid = osm_physp_get_base_lid( p_physp );
+      if (memcmp( &p_pi->base_lid, &p_old_pi->base_lid, 
+                  sizeof(p_pi->base_lid) ))
+        send_set = TRUE;
+
+      /* we are initializing the ports with our local sm_base_lid */
+      p_pi->master_sm_base_lid = p_mgr->p_subn->sm_base_lid;
+      if (memcmp( &p_pi->master_sm_base_lid, &p_old_pi->master_sm_base_lid, 
+                  sizeof(p_pi->master_sm_base_lid) ))
+        send_set = TRUE;
+
+      p_pi->m_key_lease_period = p_mgr->p_subn->opt.m_key_lease_period;
+      if (memcmp( &p_pi->m_key_lease_period, &p_old_pi->m_key_lease_period, 
+                  sizeof(p_pi->m_key_lease_period) ))
+        send_set = TRUE;
+
+      if (esp0 == FALSE)
+        p_pi->mkey_lmc = p_mgr->p_subn->opt.lmc;
+      else
+      {
+        if (p_mgr->p_subn->opt.lmc_esp0)
+          p_pi->mkey_lmc = p_mgr->p_subn->opt.lmc;
+        else
+          p_pi->mkey_lmc = 0;
+      }
+      if (memcmp( &p_pi->mkey_lmc, &p_old_pi->mkey_lmc, sizeof(p_pi->mkey_lmc) ))
+        send_set = TRUE;
+
+      ib_port_info_set_timeout( p_pi, p_mgr->p_subn->opt.subnet_timeout );
+      if (ib_port_info_get_timeout( p_pi ) != ib_port_info_get_timeout( p_old_pi ))
+        send_set = TRUE;
+    }
+
+    /*
+      Several timeout mechanisms:
+    */
+    p_remote_physp = osm_physp_get_remote( p_physp );
+    if (port_num != 0 && p_remote_physp && 
+        osm_physp_is_valid(p_remote_physp)) {
+      if (osm_node_get_type(osm_physp_get_node_ptr(p_physp)) ==
+          IB_NODE_TYPE_ROUTER)
+      {
+        ib_port_info_set_hoq_lifetime(
+          p_pi, p_mgr->p_subn->opt.leaf_head_of_queue_lifetime);
+      }
+      else if (osm_node_get_type(osm_physp_get_node_ptr(p_physp)) ==
+               IB_NODE_TYPE_SWITCH)
+     {
+       /* Is remote end CA or router (a leaf port) ? */
+       if (osm_node_get_type(osm_physp_get_node_ptr(p_remote_physp)) != 
+            IB_NODE_TYPE_SWITCH)
+       {
+         ib_port_info_set_hoq_lifetime(
+           p_pi, p_mgr->p_subn->opt.leaf_head_of_queue_lifetime);
+         ib_port_info_set_vl_stall_count(
+           p_pi, p_mgr->p_subn->opt.leaf_vl_stall_count);
+       }
+       else
+       {
+         ib_port_info_set_hoq_lifetime(
+           p_pi, p_mgr->p_subn->opt.head_of_queue_lifetime);
+         ib_port_info_set_vl_stall_count(
+           p_pi, p_mgr->p_subn->opt.vl_stall_count);
+       }
+     }
+     if ( ib_port_info_get_hoq_lifetime(p_pi) !=
+          ib_port_info_get_hoq_lifetime(p_old_pi) ||
+          ib_port_info_get_vl_stall_count(p_pi) !=
+          ib_port_info_get_vl_stall_count(p_old_pi) )
+       send_set = TRUE;
+    }
+
+    ib_port_info_set_phy_and_overrun_err_thd(
+      p_pi,
+      p_mgr->p_subn->opt.local_phy_errors_threshold,
+      p_mgr->p_subn->opt.overrun_errors_threshold);
+    if (memcmp( &p_pi->error_threshold, &p_old_pi->error_threshold, 
+                sizeof(p_pi->error_threshold) ))
+      send_set = TRUE;
+
+    /*
+      Set the easy common parameters for all port types,
+      then determine the neighbor MTU.
+    */
+    p_pi->link_width_enabled = p_old_pi->link_width_supported;
+    if (memcmp( &p_pi->link_width_enabled, &p_old_pi->link_width_enabled, 
+                sizeof(p_pi->link_width_enabled) ))
+      send_set = TRUE;
+
+    if ( p_mgr->p_subn->opt.force_link_speed )
+      ib_port_info_set_link_speed_enabled( p_pi, IB_LINK_SPEED_ACTIVE_2_5 );
+    else if (ib_port_info_get_link_speed_enabled( p_old_pi ) != ib_port_info_get_link_speed_sup( p_pi ))
+      ib_port_info_set_link_speed_enabled( p_pi, IB_PORT_LINK_SPEED_ENABLED_MASK );
+    else
+      ib_port_info_set_link_speed_enabled( p_pi, ib_port_info_get_link_speed_enabled( p_old_pi ));
+    if (memcmp( &p_pi->link_speed, &p_old_pi->link_speed,
+                sizeof(p_pi->link_speed) ))
+      send_set = TRUE;
+
+    /* calc new op_vls and mtu */
+    op_vls =
+      osm_physp_calc_link_op_vls( p_mgr->p_log, p_mgr->p_subn, p_physp );
+    mtu = osm_physp_calc_link_mtu( p_mgr->p_log, p_physp );
+
+    ib_port_info_set_neighbor_mtu( p_pi, mtu );
+    if ( ib_port_info_get_neighbor_mtu(p_pi) !=
+         ib_port_info_get_neighbor_mtu(p_old_pi) )
+      send_set = TRUE;
+
+    ib_port_info_set_op_vls( p_pi, op_vls );
+    if ( ib_port_info_get_op_vls(p_pi) != 
+         ib_port_info_get_op_vls(p_old_pi) )
+      send_set = TRUE;
+
+    /* also the context can flag the need to check for errors. */
+    context.pi_context.ignore_errors = FALSE;
+  }
+  else
+  {
+    /*
+      Since the only change we try to do is to modify the port
+      state we can ignore the errors that might be caused by a
+      race in setting the state and the actual state the port is
+      in.
+    */
+    context.pi_context.ignore_errors = FALSE;
+  }
+
+  ib_port_info_set_port_state( p_pi, port_state );
+  if (port_state != IB_LINK_NO_CHANGE &&
+      ib_port_info_get_port_state(p_pi) != 
+      ib_port_info_get_port_state(p_old_pi) )
+  {
+    send_set = TRUE;
+    if (port_state == IB_LINK_ACTIVE)
+      context.pi_context.active_transition = TRUE;
+    else
+      context.pi_context.active_transition = FALSE;
+  }
+
+  context.pi_context.node_guid = osm_node_get_node_guid( p_node );
+  context.pi_context.port_guid = osm_physp_get_port_guid( p_physp );
+  context.pi_context.set_method = TRUE;
+  context.pi_context.update_master_sm_base_lid = FALSE;
+  context.pi_context.light_sweep = FALSE;
+
+  /* We need to send the PortInfoSet request with the new sm_lid
+     in the following cases:
+     1. There is a change in the values (send_set == TRUE)
+     2. This is an hca port or a switch port zero and got_set_resp is FALSE 
+        (in this case we sent a PortInfoSet in the osm_lid_mgr, but for some
+        reason we didn't get a response) - try and re-send.
+     3. This is a switch port and:
+        a. first_time_master_sweep flag on the subnet is TRUE. This means the
+           SM just became master, and it then needs to send at PortInfoSet to
+           every port (and this is the first time we can send a PortInfoSet to
+           switch external ports).
+        b. got_set_resp on the physical port is FALSE. This means we haven't
+           seen this port before - need to send PortInfoSet to it.
+  */
+  if (send_set || 
+      (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH && p_physp->got_set_resp == FALSE) ||
+      (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && port_num == 0 && 
+       p_physp->got_set_resp == FALSE) ||
+      (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && port_num != 0 &&
+       (p_mgr->p_subn->first_time_master_sweep == TRUE || p_physp->got_set_resp == FALSE)))
+  {
+    p_mgr->send_set_reqs = TRUE;
+    status = osm_req_set( p_mgr->p_req,
+                          osm_physp_get_dr_path_ptr( p_physp ),
+                          payload,
+                          sizeof(payload),
+                          IB_MAD_ATTR_PORT_INFO,
+                          cl_hton32(port_num),
+                          CL_DISP_MSGID_NONE,
+                          &context );
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static osm_signal_t
+__osm_link_mgr_process_port(
+  IN osm_link_mgr_t* const p_mgr,
+  IN osm_port_t* const p_port,
+  IN const uint8_t link_state )
+{
+  uint32_t i;
+  uint32_t num_physp;
+  osm_physp_t *p_physp;
+  uint8_t current_state;
+  osm_signal_t signal = OSM_SIGNAL_DONE;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_link_mgr_process_port );
+
+  if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+             "__osm_link_mgr_process_port: "
+             "Port 0x%" PRIx64 " going to %s\n",
+             cl_ntoh64( osm_port_get_guid( p_port ) ),
+             ib_get_port_state_str( link_state ) );
+  }
+
+  /*
+    Set the PortInfo for every Physical Port associated
+    with this Port.  Start iterating with port 1, since the linkstate
+    is not applicable to the management port on switches.
+  */
+  num_physp = osm_port_get_num_physp( p_port );
+  for( i = 0; i < num_physp; i ++ )
+  {
+    /*
+      Don't bother doing anything if this Physical Port is not valid.
+      or if the state of the port is already better then the
+      specified state.
+    */
+    p_physp = osm_port_get_phys_ptr( p_port, (uint8_t)i );
+    if( p_physp && osm_physp_is_valid( p_physp ) )
+    {
+      current_state = osm_physp_get_port_state( p_physp );
+
+      if( current_state == IB_LINK_DOWN )
+        continue;
+
+      /*
+        Normally we only send state update if state is lower
+        then required state. However, we need to send update if
+        no state change required.
+      */
+      if( (link_state == IB_LINK_NO_CHANGE) ||
+          (current_state < link_state) )
+      {
+        p_mgr->send_set_reqs = FALSE;
+        __osm_link_mgr_set_physp_pi(
+          p_mgr,
+          p_physp,
+          link_state );
+
+        if ( p_mgr->send_set_reqs == TRUE )
+          signal = OSM_SIGNAL_DONE_PENDING;
+      }
+      else
+      {
+        if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+        {
+          osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+                   "__osm_link_mgr_process_port: "
+                   "Physical port 0x%X already %s. Skipping\n",
+                   osm_physp_get_port_num( p_physp ),
+                   ib_get_port_state_str( current_state ) );
+        }
+      }
+    }
+  }
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return( signal );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_signal_t
+osm_link_mgr_process(
+  IN osm_link_mgr_t* const p_mgr,
+  IN const uint8_t link_state )
+{
+  cl_qmap_t *p_port_guid_tbl;
+  osm_port_t *p_port;
+  osm_signal_t signal = OSM_SIGNAL_DONE;
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_link_mgr_process );
+
+  p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+  CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
+
+  for( p_port = (osm_port_t*)cl_qmap_head( p_port_guid_tbl );
+       p_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl );
+       p_port = (osm_port_t*)cl_qmap_next( &p_port->map_item ) )
+  {
+    if( __osm_link_mgr_process_port( p_mgr, p_port, link_state ) ==
+        OSM_SIGNAL_DONE_PENDING )
+      signal = OSM_SIGNAL_DONE_PENDING;
+  }
+
+  CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return( signal );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_matrix.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_matrix.c
new file mode 100644 (file)
index 0000000..f655ad6
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_matrix.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_lid_matrix_t.
+ * This file implements the LID Matrix object.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_matrix.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lid_matrix_destroy(
+  IN osm_lid_matrix_t* const p_lmx )
+{
+  cl_vector_destroy( &p_lmx->lid_vec );
+}
+
+/**********************************************************************
+ Initializer function called by cl_vector
+**********************************************************************/
+cl_status_t
+__osm_lid_matrix_vec_init(
+  IN void* const p_elem,
+  IN void* context )
+{
+  osm_lid_matrix_t* const p_lmx = (osm_lid_matrix_t*)context;
+
+  memset( p_elem, OSM_NO_PATH, p_lmx->num_ports + 1);
+  return( CL_SUCCESS );
+}
+
+/**********************************************************************
+ Initializer function called by cl_vector
+**********************************************************************/
+void
+__osm_lid_matrix_vec_clear(
+  IN const size_t index,
+  IN void* const p_elem,
+  IN void* context )
+{
+  osm_lid_matrix_t* const p_lmx = (osm_lid_matrix_t*)context;
+
+  UNUSED_PARAM( index );
+  memset( p_elem, OSM_NO_PATH, p_lmx->num_ports + 1);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lid_matrix_clear(
+  IN osm_lid_matrix_t* const p_lmx )
+{
+  cl_vector_apply_func( &p_lmx->lid_vec,
+                        __osm_lid_matrix_vec_clear, p_lmx );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lid_matrix_init(
+  IN osm_lid_matrix_t* const p_lmx,
+  IN const uint8_t num_ports )
+{
+  cl_vector_t *p_vec;
+  cl_status_t status;
+
+  CL_ASSERT( p_lmx );
+  CL_ASSERT( num_ports );
+
+  p_lmx->num_ports = num_ports;
+
+  p_vec = &p_lmx->lid_vec;
+  /*
+    Initialize the vector for the number of ports plus an
+    extra entry to hold the "least-hops" count for that LID.
+  */
+  status = cl_vector_init( p_vec,
+                           0,             /* min_size, */
+                           1,             /* grow_size */
+                           sizeof(uint8_t)*(num_ports + 1), /*  element size */
+                           __osm_lid_matrix_vec_init, /*  init function */
+                           NULL,           /*  destory func */
+                           p_lmx          /*  context */
+                           );
+
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+cl_status_t
+osm_lid_matrix_set(
+  IN osm_lid_matrix_t* const p_lmx,
+  IN const uint16_t lid_ho,
+  IN const uint8_t port_num,
+  IN const uint8_t val )
+{
+  uint8_t *p_port_array;
+  cl_status_t status;
+
+  CL_ASSERT( port_num < p_lmx->num_ports );
+  status = cl_vector_set_min_size( &p_lmx->lid_vec, lid_ho + 1 );
+  if( status == CL_SUCCESS )
+  {
+    p_port_array = (uint8_t *)cl_vector_get_ptr( &p_lmx->lid_vec, lid_ho );
+    p_port_array[port_num] = val;
+    if( p_port_array[p_lmx->num_ports] > val )
+      p_port_array[p_lmx->num_ports] = val;
+  }
+  return( status );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_fwd_rcv.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_fwd_rcv.c
new file mode 100644 (file)
index 0000000..570a5bb
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_mcast_fwd_rcv.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_mft_rcv_t.
+ * This object represents the Multicast Forwarding Table Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_mcast_fwd_rcv.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_subnet.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mft_rcv_construct(
+  IN osm_mft_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mft_rcv_destroy(
+  IN osm_mft_rcv_t* const p_rcv )
+{
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_mft_rcv_destroy );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mft_rcv_init(
+  IN osm_mft_rcv_t* const p_rcv,
+  IN osm_subn_t* const p_subn,
+  IN osm_log_t* const p_log,
+  IN cl_plock_t* const p_lock )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_mft_rcv_init );
+
+  osm_mft_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mft_rcv_process(
+  IN const osm_mft_rcv_t* const p_rcv,
+  IN osm_madw_t* const p_madw )
+{
+  ib_smp_t *p_smp;
+  uint32_t block_num;
+  uint8_t position;
+  osm_switch_t *p_sw;
+  osm_mft_context_t *p_mft_context;
+  uint16_t *p_block;
+  ib_net64_t node_guid;
+  ib_api_status_t status;
+
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_mft_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+  p_block = (uint16_t*)ib_smp_get_payload_ptr( p_smp );
+  block_num = cl_ntoh32( p_smp->attr_mod ) & IB_MCAST_BLOCK_ID_MASK_HO;
+  position = (uint8_t)((cl_ntoh32( p_smp->attr_mod ) &
+                        IB_MCAST_POSITION_MASK_HO) >> IB_MCAST_POSITION_SHIFT);
+
+  /*
+    Acquire the switch object for this switch.
+  */
+  p_mft_context = osm_madw_get_mft_context_ptr( p_madw );
+  node_guid = p_mft_context->node_guid;
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "osm_mft_rcv_process: "
+             "Setting MFT block %u, position %u"
+             "\n\t\t\t\tSwitch 0x%016" PRIx64 ", TID 0x%" PRIx64 "\n",
+             block_num, position, cl_ntoh64( node_guid ),
+             cl_ntoh64( p_smp->trans_id ) );
+  }
+
+  CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
+  p_sw = osm_get_switch_by_guid( p_rcv->p_subn, node_guid );
+
+  if( !p_sw )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_mft_rcv_process: ERR 0801: "
+             "MFT received for nonexistent node "
+             "0x%016" PRIx64 "\n", cl_ntoh64( node_guid ) );
+  }
+  else
+  {
+    status = osm_switch_set_mft_block( p_sw, p_block,
+                                       (uint16_t)block_num, position );
+    if( status != IB_SUCCESS )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_mft_rcv_process: ERR 0802: "
+               "Setting MFT block failed (%s)"
+               "\n\t\t\t\tSwitch 0x%016" PRIx64
+               ", block %u, position %u\n",
+               ib_get_err_str( status ),
+               cl_ntoh64( node_guid ),
+               block_num, position );
+    }
+  }
+
+  CL_PLOCK_RELEASE( p_rcv->p_lock );
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_fwd_rcv_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_fwd_rcv_ctrl.c
new file mode 100644 (file)
index 0000000..f28ac9b
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_mcast_fwd_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_mft_rcv_ctrl_t.
+ * This object represents the LFT Receive controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_mcast_fwd_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_mft_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_mft_rcv_process( ((osm_mft_rcv_ctrl_t*)context)->p_rcv,
+                       (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mft_rcv_ctrl_construct(
+  IN osm_mft_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mft_rcv_ctrl_destroy(
+  IN osm_mft_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mft_rcv_ctrl_init(
+  IN osm_mft_rcv_ctrl_t* const p_ctrl,
+  IN osm_mft_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_mft_rcv_ctrl_init );
+
+  osm_mft_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_MFT,
+    __osm_mft_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_mft_rcv_ctrl_init: ERR 0901: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_mgr.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_mgr.c
new file mode 100644 (file)
index 0000000..a3b3882
--- /dev/null
@@ -0,0 +1,1726 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_mcast_mgr.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_mcast_mgr_t.
+ * This file implements the Multicast Manager object.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.9 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <iba/ib_types.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_mcast_mgr.h>
+#include <opensm/osm_multicast.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+
+#define LINE_LENGTH 256
+
+/**********************************************************************
+ **********************************************************************/
+typedef struct _osm_mcast_work_obj
+{
+  cl_list_item_t     list_item;
+  osm_port_t*        p_port;
+} osm_mcast_work_obj_t;
+
+/**********************************************************************
+ **********************************************************************/
+static osm_mcast_work_obj_t*
+__osm_mcast_work_obj_new(
+  IN const osm_port_t*     const p_port )
+{
+  /*
+    TO DO - get these objects from a lockpool.
+  */
+  osm_mcast_work_obj_t*    p_obj;
+
+  /*
+    clean allocated memory to avoid assertion when trying to insert to
+    qlist.
+    see cl_qlist_insert_tail(): CL_ASSERT(p_list_item->p_list != p_list)
+  */
+  p_obj = malloc( sizeof( *p_obj ) );
+  if( p_obj )
+  {
+    memset( p_obj, 0, sizeof( *p_obj ) );
+    p_obj->p_port = (osm_port_t*)p_port;
+  }
+
+  return( p_obj );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mcast_work_obj_delete(
+  IN osm_mcast_work_obj_t* p_wobj )
+{
+  free( p_wobj );
+}
+
+/**********************************************************************
+   Recursively remove nodes from the tree
+**********************************************************************/
+static void
+__osm_mcast_mgr_purge_tree_node(
+  IN osm_mtree_node_t*     p_mtn )
+{
+  uint8_t                  i;
+
+  for( i = 0; i < p_mtn->max_children; i++ )
+  {
+    if( p_mtn->child_array[i] &&
+        (p_mtn->child_array[i] != OSM_MTREE_LEAF) )
+      __osm_mcast_mgr_purge_tree_node( p_mtn->child_array[i] );
+
+    p_mtn->child_array[i] = NULL;
+
+  }
+
+  free( p_mtn );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mcast_mgr_purge_tree(
+  IN osm_mcast_mgr_t*         const p_mgr,
+  IN osm_mgrp_t*           const p_mgrp )
+{
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_purge_tree );
+
+  if( p_mgrp->p_root )
+    __osm_mcast_mgr_purge_tree_node( p_mgrp->p_root );
+
+  p_mgrp->p_root = NULL;
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static float
+osm_mcast_mgr_compute_avg_hops(
+  osm_mcast_mgr_t*         const p_mgr,
+  const osm_mgrp_t*        const p_mgrp,
+  const osm_switch_t*         const p_sw )
+{
+  float avg_hops = 0;
+  uint32_t hops = 0;
+  uint32_t num_ports = 0;
+  uint16_t base_lid_ho;
+  const osm_port_t* p_port;
+  const osm_mcm_port_t* p_mcm_port;
+  const cl_qmap_t* p_mcm_tbl;
+  const cl_qmap_t* p_port_tbl;
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_compute_avg_hops );
+
+  p_mcm_tbl = &p_mgrp->mcm_port_tbl;
+  p_port_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+  /*
+    For each member of the multicast group, compute the
+    number of hops to its base LID.
+  */
+  for( p_mcm_port = (osm_mcm_port_t*)cl_qmap_head( p_mcm_tbl );
+       p_mcm_port != (osm_mcm_port_t*)cl_qmap_end( p_mcm_tbl );
+       p_mcm_port = (osm_mcm_port_t*)cl_qmap_next(&p_mcm_port->map_item))
+  {
+    /*
+      Acquire the port object for this port guid, then create
+      the new worker object to build the list.
+    */
+    p_port = (osm_port_t*)cl_qmap_get( p_port_tbl,
+                                       ib_gid_get_guid( &p_mcm_port->port_gid ) );
+
+    if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) )
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "osm_mcast_mgr_compute_avg_hops: ERR 0A18: "
+               "No port object for port 0x%016" PRIx64 "\n",
+               cl_ntoh64( ib_gid_get_guid( &p_mcm_port->port_gid ) ) );
+      continue;
+    }
+
+    base_lid_ho = cl_ntoh16( osm_port_get_base_lid( p_port ) );
+    hops += osm_switch_get_least_hops( p_sw, base_lid_ho );
+    num_ports++;
+  }
+
+  /*
+    We should be here if there aren't any ports in the group.
+  */
+  CL_ASSERT( num_ports );
+
+  if( num_ports != 0 )
+  {
+    avg_hops = (float)(hops / num_ports);
+  }
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return( avg_hops );
+}
+
+/**********************************************************************
+ Calculate the maximal "min hops" from the given switch to any
+ of the group HCAs
+ **********************************************************************/
+static float
+osm_mcast_mgr_compute_max_hops(
+  osm_mcast_mgr_t*         const p_mgr,
+  const osm_mgrp_t*        const p_mgrp,
+  const osm_switch_t*      const p_sw )
+{
+  uint32_t max_hops = 0;
+  uint32_t hops = 0;
+  uint16_t base_lid_ho;
+  const osm_port_t* p_port;
+  const osm_mcm_port_t* p_mcm_port;
+  const cl_qmap_t* p_mcm_tbl;
+  const cl_qmap_t* p_port_tbl;
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_compute_max_hops );
+
+  p_mcm_tbl = &p_mgrp->mcm_port_tbl;
+  p_port_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+  /*
+    For each member of the multicast group, compute the
+    number of hops to its base LID.
+  */
+  for( p_mcm_port = (osm_mcm_port_t*)cl_qmap_head( p_mcm_tbl );
+       p_mcm_port != (osm_mcm_port_t*)cl_qmap_end( p_mcm_tbl );
+       p_mcm_port = (osm_mcm_port_t*)cl_qmap_next(&p_mcm_port->map_item))
+  {
+    /*
+      Acquire the port object for this port guid, then create
+      the new worker object to build the list.
+    */
+    p_port = (osm_port_t*)cl_qmap_get(
+      p_port_tbl,
+      ib_gid_get_guid( &p_mcm_port->port_gid ) );
+
+    if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) )
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "osm_mcast_mgr_compute_max_hops: ERR 0A1A: "
+               "No port object for port 0x%016" PRIx64 "\n",
+               cl_ntoh64( ib_gid_get_guid( &p_mcm_port->port_gid ) ) );
+      continue;
+    }
+
+    base_lid_ho = cl_ntoh16( osm_port_get_base_lid( p_port ) );
+    hops = osm_switch_get_least_hops( p_sw, base_lid_ho );
+    if (hops > max_hops) max_hops = hops;
+  }
+
+  if( max_hops == 0 )
+  {
+    /*
+      We should be here if there aren't any ports in the group.
+    */
+    max_hops = 10001; /* see later - we use it to realize no hops */
+  }
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return(float)(max_hops);
+}
+
+/**********************************************************************
+   This function attempts to locate the optimal switch for the
+   center of the spanning tree.  The current algorithm chooses
+   a switch with the lowest average hop count to the members
+   of the multicast group.
+**********************************************************************/
+static osm_switch_t*
+__osm_mcast_mgr_find_optimal_switch(
+  osm_mcast_mgr_t*         const p_mgr,
+  const osm_mgrp_t*        const p_mgrp )
+{
+  cl_qmap_t*               p_sw_tbl;
+  const osm_switch_t*         p_sw;
+  const osm_switch_t*         p_best_sw = NULL;
+  float                 hops = 0;
+  float                 best_hops = 10000;   /* any big # will do */
+  uint64_t              sw_guid_ho;
+#ifdef OSM_VENDOR_INTF_ANAFA  
+       boolean_t             use_avg_hops = TRUE; /* anafa2 - bug hca on switch */ /* use max hops for root */
+#else
+       boolean_t             use_avg_hops = FALSE;  /* use max hops for root */
+#endif
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_find_optimal_switch );
+
+  p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+  CL_ASSERT( !osm_mgrp_is_empty( p_mgrp ) );
+
+  for( p_sw = (osm_switch_t*)cl_qmap_head( p_sw_tbl );
+       p_sw != (osm_switch_t*)cl_qmap_end( p_sw_tbl );
+       p_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item ) )
+  {
+    if( !osm_switch_supports_mcast( p_sw ) )
+      continue;
+
+    if (use_avg_hops) 
+      hops = osm_mcast_mgr_compute_avg_hops( p_mgr, p_mgrp, p_sw );
+    else
+      hops = osm_mcast_mgr_compute_max_hops( p_mgr, p_mgrp, p_sw );
+
+    if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+    {
+      sw_guid_ho = cl_ntoh64( osm_node_get_node_guid(
+                                osm_switch_get_node_ptr( p_sw ) ) );
+
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "__osm_mcast_mgr_find_optimal_switch: "
+               "Switch 0x%016" PRIx64 ", hops = %f\n",
+               sw_guid_ho, hops );
+    }
+
+    if( hops < best_hops )
+    {
+      p_best_sw = p_sw;
+      best_hops = hops;
+    }
+  }
+
+  if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+  {
+    if( p_best_sw )
+    {
+      sw_guid_ho = cl_ntoh64( osm_node_get_node_guid(
+                                osm_switch_get_node_ptr( p_best_sw ) ) );
+
+      osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+               "__osm_mcast_mgr_find_optimal_switch: "
+               "Best switch is 0x%" PRIx64 ", hops = %f\n",
+               sw_guid_ho, best_hops );
+    }
+    else
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+               "__osm_mcast_mgr_find_optimal_switch: "
+               "No multicast capable switches detected\n" );
+    }
+  }
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return( (osm_switch_t*)p_best_sw );
+}
+
+/**********************************************************************
+   This function returns the existing or optimal root swtich for the tree.
+**********************************************************************/
+static osm_switch_t*
+__osm_mcast_mgr_find_root_switch(
+  osm_mcast_mgr_t* const p_mgr,
+  const osm_mgrp_t* const p_mgrp )
+{
+  const osm_switch_t* p_sw = NULL;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_find_root_switch );
+
+  /*
+    We always look for the best multicast tree root switch.
+    Otherwise since we always start with a a single join
+    the root will be always on the first switch attached to it.
+    - Very bad ...
+  */
+  p_sw = __osm_mcast_mgr_find_optimal_switch( p_mgr, p_mgrp );
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return( (osm_switch_t*)p_sw );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcast_mgr_construct(
+  IN osm_mcast_mgr_t* const p_mgr )
+{
+  memset( p_mgr, 0, sizeof(*p_mgr) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcast_mgr_destroy(
+  IN osm_mcast_mgr_t* const p_mgr )
+{
+  CL_ASSERT( p_mgr );
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_destroy );
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mcast_mgr_init(
+  IN osm_mcast_mgr_t*         const p_mgr,
+  IN osm_req_t*            const p_req,
+  IN osm_subn_t*           const p_subn,
+  IN osm_log_t*            const p_log,
+  IN cl_plock_t*           const p_lock )
+{
+  ib_api_status_t          status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_mcast_mgr_init );
+
+  CL_ASSERT( p_req );
+  CL_ASSERT( p_subn );
+  CL_ASSERT( p_lock );
+
+  osm_mcast_mgr_construct( p_mgr );
+
+  p_mgr->p_log = p_log;
+  p_mgr->p_subn = p_subn;
+  p_mgr->p_lock = p_lock;
+  p_mgr->p_req = p_req;
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static osm_signal_t
+__osm_mcast_mgr_set_tbl(
+  IN osm_mcast_mgr_t*         const p_mgr,
+  IN osm_switch_t*         const p_sw )
+{
+  osm_node_t*              p_node;
+  osm_dr_path_t*           p_path;
+  osm_madw_context_t       mad_context;
+  ib_api_status_t          status;
+  uint32_t              block_id_ho = 0;
+  int16_t                  block_num = 0;
+  uint32_t              position = 0;
+  uint32_t              max_position;
+  osm_mcast_tbl_t*         p_tbl;
+  ib_net16_t               block[IB_MCAST_BLOCK_SIZE];
+  osm_signal_t          signal = OSM_SIGNAL_DONE;
+
+  CL_ASSERT( p_mgr );
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_set_tbl );
+
+  CL_ASSERT( p_sw );
+
+  p_node = osm_switch_get_node_ptr( p_sw );
+
+  CL_ASSERT( p_node );
+
+  p_path = osm_node_get_any_dr_path_ptr( p_node );
+
+  CL_ASSERT( p_path );
+
+  /*
+    Send multicast forwarding table blocks to the switch
+    as long as the switch indicates it has blocks needing
+    configuration.
+  */
+
+  mad_context.mft_context.node_guid = osm_node_get_node_guid( p_node );
+  mad_context.mft_context.set_method = TRUE;
+
+  p_tbl = osm_switch_get_mcast_tbl_ptr( p_sw );
+  max_position = p_tbl->max_position;
+
+  while( osm_mcast_tbl_get_block( p_tbl, block_num,
+                                  (uint8_t)position, block ) )
+  {
+    if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "__osm_mcast_mgr_set_tbl: "
+               "Writing MFT block 0x%X\n", block_id_ho );
+    }
+
+    block_id_ho = block_num + (position << 28);
+
+    status = osm_req_set( p_mgr->p_req,
+                          p_path,
+                          (void*)block,
+                          sizeof(block),
+                          IB_MAD_ATTR_MCAST_FWD_TBL,
+                          cl_hton32( block_id_ho ),
+                          CL_DISP_MSGID_NONE,
+                          &mad_context );
+
+    if( status != IB_SUCCESS )
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_mcast_mgr_set_tbl: ERR 0A02: "
+               "Sending multicast fwd. tbl. block failed (%s)\n",
+               ib_get_err_str( status ) );
+    }
+
+    signal = OSM_SIGNAL_DONE_PENDING;
+
+    if( ++position > max_position )
+    {
+      position = 0;
+      block_num++;
+    }
+  }
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return( signal );
+}
+
+/**********************************************************************
+  This is part of the recursive function to compute the paths in the
+  spanning tree that eminate from this switch.  On input, the p_list
+  contains the group members that must be routed from this switch.
+**********************************************************************/
+static void
+__osm_mcast_mgr_subdivide(
+  osm_mcast_mgr_t*         const p_mgr,
+  osm_mgrp_t*              const p_mgrp,
+  osm_switch_t*            const p_sw,
+  cl_qlist_t*              const p_list,
+  cl_qlist_t*              const list_array,
+  uint8_t                  const array_size )
+{
+  uint8_t                  port_num;
+  uint16_t              mlid_ho;
+  uint16_t              lid_ho;
+  boolean_t             ignore_existing;
+  osm_mcast_work_obj_t*    p_wobj;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_subdivide );
+
+  mlid_ho = cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) );
+
+  /* 
+     For Multicast Groups, we want not to count on previous 
+     configurations - since we can easily generate a storm 
+     by loops.
+  */
+  ignore_existing = TRUE;
+
+  /*
+    Subdivide the set of ports into non-overlapping subsets
+    that will be routed to other switches.
+  */
+  while( (p_wobj = (osm_mcast_work_obj_t*)cl_qlist_remove_head( p_list )) !=
+         (osm_mcast_work_obj_t*)cl_qlist_end( p_list ) )
+  {
+    lid_ho = cl_ntoh16( osm_port_get_base_lid( p_wobj->p_port ) );
+
+    port_num = osm_switch_recommend_mcast_path(
+      p_sw, lid_ho, mlid_ho, ignore_existing );
+
+    if( port_num == OSM_NO_PATH )
+    {
+      /*
+        This typically occurs if the switch does not support
+        multicast and the multicast tree must branch at this
+        switch.
+      */
+      uint64_t node_guid_ho = cl_ntoh64( osm_node_get_node_guid(
+                                           osm_switch_get_node_ptr( p_sw ) ) );
+
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_mcast_mgr_subdivide: ERR 0A03: "
+               "Error routing MLID 0x%X through switch 0x%" PRIx64 "\n"
+               "\t\t\t\tNo multicast paths from this switch for port "
+               "with LID 0x%X\n",
+               mlid_ho, node_guid_ho, lid_ho );
+
+      __osm_mcast_work_obj_delete( p_wobj );
+      continue;
+    }
+
+    if( port_num > array_size )
+    {
+      uint64_t node_guid_ho = cl_ntoh64( osm_node_get_node_guid(
+                                           osm_switch_get_node_ptr( p_sw ) ) );
+
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_mcast_mgr_subdivide: ERR 0A04: "
+               "Error routing MLID 0x%X through switch 0x%" PRIx64 "\n"
+               "\t\t\t\tNo multicast paths from this switch to port "
+               "with LID 0x%X\n",
+               mlid_ho, node_guid_ho, lid_ho );
+
+      __osm_mcast_work_obj_delete( p_wobj );
+
+      /* This is means OpenSM has a bug. */
+      CL_ASSERT( FALSE );
+      continue;
+    }
+
+    cl_qlist_insert_tail( &list_array[port_num], &p_wobj->list_item );
+  }
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mcast_mgr_purge_list(
+  osm_mcast_mgr_t*         const p_mgr,
+  cl_qlist_t*              const p_list )
+{
+  osm_mcast_work_obj_t*    p_wobj;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_purge_list );
+
+  while( (p_wobj = (osm_mcast_work_obj_t*)cl_qlist_remove_head( p_list ) )
+         != (osm_mcast_work_obj_t*)cl_qlist_end( p_list ) )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "__osm_mcast_mgr_purge_list: ERR 0A06: "
+             "Unable to route for port 0x%" PRIx64 "\n",
+             osm_port_get_guid( p_wobj->p_port ) );
+    __osm_mcast_work_obj_delete( p_wobj );
+  }
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+  This is the recursive function to compute the paths in the spanning
+  tree that emanate from this switch.  On input, the p_list contains
+  the group members that must be routed from this switch.
+
+  The function returns the newly created mtree node element.
+**********************************************************************/
+static osm_mtree_node_t*
+__osm_mcast_mgr_branch(
+  osm_mcast_mgr_t*         const p_mgr,
+  osm_mgrp_t*              const p_mgrp,
+  osm_switch_t*            const p_sw,
+  cl_qlist_t*              const p_list,
+  uint8_t                  depth,
+  uint8_t                  const upstream_port,
+  uint8_t*              const p_max_depth )
+{
+  uint8_t                  max_children;
+  osm_mtree_node_t*        p_mtn = NULL;
+  cl_qlist_t*              list_array = NULL;
+  uint8_t                  i;
+  ib_net64_t               node_guid;
+  uint64_t              node_guid_ho;
+  osm_mcast_work_obj_t*    p_wobj;
+  cl_qlist_t*              p_port_list;
+  size_t                count;
+  uint16_t              mlid_ho;
+  osm_mcast_tbl_t*         p_tbl;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_branch );
+
+  CL_ASSERT( p_sw );
+  CL_ASSERT( p_list );
+  CL_ASSERT( p_max_depth );
+
+  node_guid = osm_node_get_node_guid(  osm_switch_get_node_ptr( p_sw ) );
+  node_guid_ho = cl_ntoh64( node_guid );
+  mlid_ho = cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) );
+
+  if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+             "__osm_mcast_mgr_branch: "
+             "Routing MLID 0x%X through switch 0x%" PRIx64 "\n"
+             "\t\t\t\t%u nodes at depth %u\n",
+             mlid_ho,
+             node_guid_ho,
+             cl_qlist_count( p_list ), depth );
+  }
+
+  CL_ASSERT( cl_qlist_count( p_list ) > 0 );
+
+  depth++;
+
+  if( depth > *p_max_depth )
+  {
+    CL_ASSERT( depth == *p_max_depth + 1 );
+    *p_max_depth = depth;
+  }
+
+  if( osm_switch_supports_mcast( p_sw ) == FALSE )
+  {
+    /*
+      This switch doesn't do multicast.  Clean-up.
+    */
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "__osm_mcast_mgr_branch: ERR 0A14: "
+             "Switch 0x%" PRIx64 " does not support multicast\n",
+             node_guid_ho );
+
+    /*
+      Deallocate all the work objects on this branch of the tree.
+    */
+    __osm_mcast_mgr_purge_list( p_mgr, p_list );
+    goto Exit;
+  }
+
+  p_mtn = osm_mtree_node_new( p_sw );
+  if( p_mtn == NULL )
+  {
+    /*
+      We are unable to continue routing down this
+      leg of the tree.  Clean-up.
+    */
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "__osm_mcast_mgr_branch: ERR 0A15: "
+             "Insufficient memory to build multicast tree\n" );
+
+    /*
+      Deallocate all the work objects on this branch of the tree.
+    */
+    __osm_mcast_mgr_purge_list( p_mgr, p_list );
+    goto Exit;
+  }
+
+  max_children = osm_mtree_node_get_max_children( p_mtn );
+
+  CL_ASSERT( max_children > 1 );
+
+  /*
+    Prepare an empty list for each port in the switch.
+    TO DO - this list array could probably be moved
+    inside the switch element to save on malloc thrashing.
+  */
+  list_array = malloc( sizeof(cl_qlist_t) * max_children );
+  if( list_array == NULL )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "__osm_mcast_mgr_branch: ERR 0A16: "
+             "Unable to allocate list array\n" );
+    __osm_mcast_mgr_purge_list( p_mgr, p_list );
+    goto Exit;
+  }
+
+  memset( list_array, 0, sizeof(cl_qlist_t) * max_children );
+
+  for( i = 0; i < max_children; i++ )
+    cl_qlist_init( &list_array[i] );
+
+  __osm_mcast_mgr_subdivide( p_mgr, p_mgrp, p_sw, p_list, list_array,
+                             max_children );
+
+  p_tbl = osm_switch_get_mcast_tbl_ptr( p_sw );
+
+  /*
+    Add the upstream port to the forwarding table unless
+    we're at the root of the spanning tree.
+  */
+  if( depth > 1 )
+  {
+    if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "__osm_mcast_mgr_branch: "
+               "Adding upstream port 0x%X\n", upstream_port );
+    }
+
+    CL_ASSERT( upstream_port );
+    osm_mcast_tbl_set( p_tbl, mlid_ho, upstream_port );
+  }
+
+  /*
+    For each port that was allocated some routes,
+    recurse into this function to continue building the tree
+    if the node on the other end of that port is another switch.
+    Otherwise, the node is an endpoint, and we've found a leaf
+    of the tree.  Mark leaves with our special pointer value.
+  */
+
+  for( i = 0; i < max_children; i++ )
+  {
+    const osm_physp_t   *p_physp;
+    const osm_physp_t   *p_remote_physp;
+    const osm_node_t    *p_node;
+    const osm_node_t    *p_remote_node;
+
+    p_port_list = &list_array[i];
+
+    count = cl_qlist_count( p_port_list );
+
+    /*
+      There should be no children routed through the upstream port!
+    */
+    CL_ASSERT( ( upstream_port == 0 ) || ( i != upstream_port) ||
+               ( (i == upstream_port) && (count == 0)) );
+
+    if( count == 0)
+      continue;      /* No routes down this port. */
+
+    if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "__osm_mcast_mgr_branch: "
+               "Routing %zu destination(s) via switch port 0x%X\n",
+               count, i );
+    }
+
+    /*
+      This port routes frames for this mcast group.  Therefore,
+      set the appropriate bit in the multicast forwarding
+      table for this switch.
+    */
+    osm_mcast_tbl_set( p_tbl, mlid_ho, i );
+    if (i == 0) 
+      /* This means we are adding the switch to the MC group.
+         We do not need to continue looking at the remote port, just 
+         needed to add the port to the table */
+      continue;
+
+    p_node = osm_switch_get_node_ptr( p_sw );
+    p_remote_node = osm_node_get_remote_node( p_node, i, NULL );
+
+    if( osm_node_get_type( p_remote_node ) == IB_NODE_TYPE_SWITCH )
+    {
+      /*
+        Acquire a pointer to the remote switch then recurse.
+      */
+      CL_ASSERT( p_remote_node->sw );
+
+      p_physp = osm_node_get_physp_ptr( p_node, i );
+      CL_ASSERT( p_physp );
+      CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+      p_remote_physp = osm_physp_get_remote( p_physp );
+      CL_ASSERT( p_remote_physp );
+      CL_ASSERT( osm_physp_is_valid( p_remote_physp ) );
+
+      p_mtn->child_array[i] = __osm_mcast_mgr_branch(
+        p_mgr, p_mgrp, p_remote_node->sw,
+        p_port_list, depth,
+        osm_physp_get_port_num( p_remote_physp),
+        p_max_depth );
+    }
+    else
+    {
+      /*
+        The neighbor node is not a switch, so this
+        must be a leaf.
+      */
+      CL_ASSERT( count == 1 );
+
+      p_mtn->child_array[i] = OSM_MTREE_LEAF;
+      p_wobj = (osm_mcast_work_obj_t*)cl_qlist_remove_head(
+        p_port_list );
+
+      CL_ASSERT( cl_is_qlist_empty( p_port_list ) );
+
+      if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+      {
+        osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+                 "__osm_mcast_mgr_branch: "
+                 "Found leaf for port 0x%016" PRIx64 "\n"
+                 "\t\t\t\ton switch port 0x%X\n",
+                 cl_ntoh64( osm_port_get_guid( p_wobj->p_port ) ), i );
+      }
+
+      __osm_mcast_work_obj_delete( p_wobj );
+    }
+  }
+
+  free( list_array );
+ Exit:
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return( p_mtn );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_mcast_mgr_build_spanning_tree(
+  osm_mcast_mgr_t*         const p_mgr,
+  osm_mgrp_t*              const p_mgrp )
+{
+  const cl_qmap_t*         p_mcm_tbl;
+  const cl_qmap_t*         p_port_tbl;
+  const osm_port_t*        p_port;
+  const osm_mcm_port_t*    p_mcm_port;
+  uint32_t              num_ports;
+  cl_qlist_t               port_list;
+  osm_switch_t*            p_sw;
+  osm_mcast_work_obj_t*    p_wobj;
+  ib_api_status_t          status = IB_SUCCESS;
+  uint8_t                  max_depth = 0;
+  uint32_t              count;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_build_spanning_tree );
+
+  cl_qlist_init( &port_list );
+
+  /*
+    TO DO - for now, just blow away the old tree.
+    In the future we'll need to construct the tree based
+    on multicast forwarding table information if the user wants to
+    preserve existing multicast routes.
+  */
+  __osm_mcast_mgr_purge_tree( p_mgr, p_mgrp );
+
+  p_mcm_tbl = &p_mgrp->mcm_port_tbl;
+  p_port_tbl = &p_mgr->p_subn->port_guid_tbl;
+  num_ports = cl_qmap_count( p_mcm_tbl );
+  if( num_ports == 0 )
+  {
+    if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+               "__osm_mcast_mgr_build_spanning_tree: "
+               "MLID 0x%X has no members--nothing to do\n",
+               cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) ) );
+    }
+    goto Exit;
+  }
+
+  /*
+    This function builds the single spanning tree recursively.
+    At each stage, the ports to be reached are divided into
+    non-overlapping subsets of member ports that can be reached through
+    a given switch port.  Construction then moves down each
+    branch, and the process starts again with each branch computing
+    for its own subset of the member ports.
+
+    The maximum recursion depth is at worst the maximum hop count in the
+    subnet, which is spec limited to 64.
+  */
+
+  /*
+    Locate the switch around which to create the spanning
+    tree for this multicast group.
+  */
+  p_sw = __osm_mcast_mgr_find_root_switch( p_mgr, p_mgrp );
+  if( p_sw == NULL )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "__osm_mcast_mgr_build_spanning_tree: ERR 0A08: "
+             "Unable to locate a suitable switch for group 0x%X\n",
+             cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) ));
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /*
+    Build the first "subset" containing all member ports.
+  */
+  for( p_mcm_port = (osm_mcm_port_t*)cl_qmap_head( p_mcm_tbl );
+       p_mcm_port != (osm_mcm_port_t*)cl_qmap_end( p_mcm_tbl );
+       p_mcm_port = (osm_mcm_port_t*)cl_qmap_next(&p_mcm_port->map_item))
+  {
+    /*
+      Acquire the port object for this port guid, then create
+      the new worker object to build the list.
+    */
+    p_port = (osm_port_t*)cl_qmap_get( p_port_tbl,
+                                       ib_gid_get_guid( &p_mcm_port->port_gid ) );
+
+    if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) )
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_mcast_mgr_build_spanning_tree: ERR 0A09: "
+               "No port object for port 0x%016" PRIx64 "\n",
+               cl_ntoh64( ib_gid_get_guid( &p_mcm_port->port_gid ) ) );
+      continue;
+    }
+
+    p_wobj = __osm_mcast_work_obj_new( p_port );
+    if( p_wobj == NULL )
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_mcast_mgr_build_spanning_tree: ERR 0A10: "
+               "Insufficient memory to route port 0x%016" PRIx64 "\n",
+               cl_ntoh64( osm_port_get_guid( p_port ) ) );
+      continue;
+    }
+
+    cl_qlist_insert_tail( &port_list, &p_wobj->list_item );
+  }
+
+  count = cl_qlist_count( &port_list );
+  p_mgrp->p_root = __osm_mcast_mgr_branch( p_mgr, p_mgrp, p_sw,
+                                           &port_list, 0, 0, &max_depth );
+
+  osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+           "__osm_mcast_mgr_build_spanning_tree: "
+           "Configured MLID 0x%X for %u ports, max tree depth = %u\n",
+           cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) ),
+           count, max_depth );
+
+ Exit:
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return( status );
+}
+
+#if 0
+/* unused */
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcast_mgr_set_table(
+  IN osm_mcast_mgr_t*         const p_mgr,
+  IN const osm_mgrp_t*     const p_mgrp,
+  IN const osm_mtree_node_t*  const p_mtn )
+{
+  uint8_t i;
+  uint8_t max_children;
+  osm_mtree_node_t* p_child_mtn;
+  uint16_t mlid_ho;
+  osm_mcast_tbl_t* p_tbl;
+  osm_switch_t* p_sw;
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_set_table );
+
+  mlid_ho = cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) );
+  p_sw = osm_mtree_node_get_switch_ptr( p_mtn );
+
+  CL_ASSERT( p_sw );
+
+  if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+             "osm_mcast_mgr_set_table: "
+             "Configuring MLID 0x%X on switch 0x%" PRIx64 "\n",
+             mlid_ho, osm_node_get_node_guid(
+               osm_switch_get_node_ptr( p_sw ) ) );
+  }
+
+  /*
+    For every child of this tree node, set the corresponding
+    bit in the switch's mcast table.
+  */
+  p_tbl = osm_switch_get_mcast_tbl_ptr( p_sw );
+  max_children = osm_mtree_node_get_max_children( p_mtn );
+
+  CL_ASSERT( max_children <= osm_switch_get_num_ports( p_sw ) );
+
+  osm_mcast_tbl_clear_mlid( p_tbl, mlid_ho );
+
+  for( i = 0; i < max_children; i++ )
+  {
+    p_child_mtn = osm_mtree_node_get_child( p_mtn, i );
+    if( p_child_mtn == NULL )
+      continue;
+
+    osm_mcast_tbl_set( p_tbl, mlid_ho, i );
+  }
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+#endif
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mcast_mgr_clear(
+  IN osm_mcast_mgr_t*         const p_mgr,
+  IN osm_mgrp_t*           const p_mgrp )
+{
+  osm_switch_t*            p_sw;
+  cl_qmap_t*               p_sw_tbl;
+  osm_mcast_tbl_t*         p_mcast_tbl;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_clear );
+
+  /*
+    Walk the switches and clear the routing entries for
+    this MLID.
+  */
+  p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl;
+  p_sw = (osm_switch_t*)cl_qmap_head( p_sw_tbl );
+  while( p_sw != (osm_switch_t*)cl_qmap_end( p_sw_tbl ) )
+  {
+    p_mcast_tbl = osm_switch_get_mcast_tbl_ptr( p_sw );
+    osm_mcast_tbl_clear_mlid( p_mcast_tbl, cl_ntoh16(p_mgrp->mlid) );
+    p_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item );
+  }
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+#if 0
+/* TO DO - make this real -- at least update spanning tree */
+/**********************************************************************
+   Lock must be held on entry.
+**********************************************************************/
+ib_api_status_t
+osm_mcast_mgr_process_single(
+  IN osm_mcast_mgr_t*      const p_mgr,
+  IN ib_net16_t            const mlid,
+  IN ib_net64_t            const port_guid,
+  IN uint8_t               const join_state )
+{
+  uint8_t                  port_num;
+  uint16_t                 mlid_ho;
+  osm_switch_t*            p_sw;
+  ib_net64_t               sw_guid;
+  osm_port_t*              p_port;
+  osm_physp_t*             p_physp;
+  osm_physp_t*             p_remote_physp;
+  osm_node_t*              p_remote_node;
+  cl_qmap_t*               p_port_tbl;
+  osm_mcast_tbl_t*         p_mcast_tbl;
+  ib_api_status_t          status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_process_single );
+
+  CL_ASSERT( mlid );
+  CL_ASSERT( port_guid );
+
+  p_port_tbl = &p_mgr->p_subn->port_guid_tbl;
+  mlid_ho = cl_ntoh16( mlid );
+
+  if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+             "osm_mcast_mgr_process_single: "
+             "Attempting to add port 0x%" PRIx64 " to MLID 0x%X, "
+             "\n\t\t\t\tjoin state = 0x%X\n",
+             cl_ntoh64( port_guid ), mlid_ho, join_state );
+  }
+
+  /*
+    Acquire the Port object.
+  */
+  p_port = (osm_port_t*)cl_qmap_get( p_port_tbl, port_guid );
+  if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "osm_mcast_mgr_process_single: ERR 0A01: "
+             "Unable to acquire port object for 0x%" PRIx64 "\n",
+             cl_ntoh64( port_guid ) );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  p_physp = osm_port_get_default_phys_ptr( p_port );
+  if( p_physp == NULL )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "osm_mcast_mgr_process_single: ERR 0A05: "
+             "Unable to acquire phsyical port object for 0x%" PRIx64 "\n",
+             cl_ntoh64( port_guid ) );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  if( !osm_physp_is_valid( p_physp ) )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "osm_mcast_mgr_process_single: ERR 0A07: "
+             "Unable to acquire valid physical port object "
+             "for 0x%" PRIx64 "\n",
+             cl_ntoh64( port_guid ) );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  p_remote_physp = osm_physp_get_remote( p_physp );
+  if( p_remote_physp == NULL )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "osm_mcast_mgr_process_single: ERR 0A11: "
+             "Unable to acquire remote phsyical port object "
+             "for 0x%" PRIx64 "\n",
+             cl_ntoh64( port_guid ) );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  if( !osm_physp_is_valid( p_remote_physp ) )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "osm_mcast_mgr_process_single: ERR 0A21: "
+             "Unable to acquire valid remote physical port object "
+             "for 0x%" PRIx64 "\n",
+             cl_ntoh64( port_guid ) );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  p_remote_node = osm_physp_get_node_ptr( p_remote_physp );
+
+  CL_ASSERT( p_remote_node );
+
+  sw_guid = osm_node_get_node_guid( p_remote_node );
+
+  if( osm_node_get_type( p_remote_node ) != IB_NODE_TYPE_SWITCH )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "osm_mcast_mgr_process_single: ERR 0A22: "
+             "Remote node not a switch node 0x%" PRIx64 "\n",
+             cl_ntoh64( sw_guid ) );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  p_sw = p_remote_node->sw;
+  if( !p_sw )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "osm_mcast_mgr_process_single: ERR 0A12: "
+             "No switch object 0x%" PRIx64 "\n",
+             cl_ntoh64( sw_guid ) );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  if( osm_switch_is_in_mcast_tree( p_sw, mlid_ho ) )
+  {
+    /*
+      We're in luck.  The switch attached to this port
+      is already in the multicast group, so we can just
+      add the specified port as a new leaf of the tree.
+    */
+    if( join_state & (IB_JOIN_STATE_FULL | IB_JOIN_STATE_NON ) )
+    {
+      /*
+        This node wants to receive multicast frames.
+        Get the switch port number to which the new member port
+        is attached, then configure this single mcast table.
+      */
+      port_num = osm_physp_get_port_num( p_remote_physp );
+      CL_ASSERT( port_num );
+
+      p_mcast_tbl = osm_switch_get_mcast_tbl_ptr( p_sw );
+      osm_mcast_tbl_set( p_mcast_tbl, mlid_ho, port_num );
+    }
+    else
+    {
+      if( join_state & IB_JOIN_STATE_SEND_ONLY )
+      {
+        if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+        {
+          osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+                   "osm_mcast_mgr_process_single: "
+                   "Success.  Nothing to do for send"
+                   "only member\n" );
+        }
+      }
+      else
+      {
+        osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+                 "osm_mcast_mgr_process_single: ERR 0A13: "
+                 "Unknown join state 0x%X\n", join_state );
+        status = IB_ERROR;
+        goto Exit;
+      }
+    }
+  }
+  else
+  {
+    if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "osm_mcast_mgr_process_single: "
+               "Unable to add port\n" );
+    }
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return( status );
+}
+#endif
+
+/**********************************************************************
+   lock must already be held on entry
+**********************************************************************/
+static ib_api_status_t
+osm_mcast_mgr_process_tree(
+  IN osm_mcast_mgr_t*      const p_mgr,
+  IN osm_mgrp_t*           const p_mgrp,
+  IN osm_mcast_req_type_t        req_type,
+  ib_net64_t                     port_guid )
+{
+  ib_api_status_t          status = IB_SUCCESS;
+  ib_net16_t               mlid;
+  boolean_t                ui_mcast_fdb_assign_func_defined;
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_process_tree );
+
+  mlid = osm_mgrp_get_mlid( p_mgrp );
+
+  if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+             "osm_mcast_mgr_process_tree: "
+             "Processing multicast group 0x%X\n", cl_ntoh16( mlid ));
+  }
+
+  /*
+    If there are no switches in the subnet, then we have nothing to do.
+  */
+  if( cl_qmap_count( &p_mgr->p_subn->sw_guid_tbl ) == 0 )
+  {
+    if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "osm_mcast_mgr_process_tree: "
+               "No switches in subnet. Nothing to do\n" );
+    }
+    goto Exit;
+  }
+
+  if (p_mgr->p_subn->opt.pfn_ui_mcast_fdb_assign)
+    ui_mcast_fdb_assign_func_defined = TRUE;
+  else
+    ui_mcast_fdb_assign_func_defined = FALSE;
+
+  /*
+    Clear the multicast tables to start clean, then build
+    the spanning tree which sets the mcast table bits for each
+    port in the group.
+    We will clean the multicast tables if a ui_mcast function isn't
+    defined, or if such function is defined, but we got here
+    through a MC_CREATE request - this means we are creating a new
+    multicast group - clean all old data.
+  */
+  if ( ui_mcast_fdb_assign_func_defined == FALSE ||
+       req_type == OSM_MCAST_REQ_TYPE_CREATE ) 
+    __osm_mcast_mgr_clear( p_mgr, p_mgrp );
+
+  /* If a UI function is defined, then we will call it here. 
+     If not - the use the regular build spanning tree function */
+  if ( ui_mcast_fdb_assign_func_defined == FALSE )
+  {
+    status = __osm_mcast_mgr_build_spanning_tree( p_mgr, p_mgrp );
+    if( status != IB_SUCCESS )
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "osm_mcast_mgr_process_tree: ERR 0A17: "
+               "Unable to create spanning tree (%s)\n",
+               ib_get_err_str( status ) );
+      goto Exit;
+    }
+  }
+  else
+  {
+    if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "osm_mcast_mgr_process_tree: "
+               "Invoking UI function pfn_ui_mcast_fdb_assign\n");
+    }
+    
+    p_mgr->p_subn->opt.pfn_ui_mcast_fdb_assign(
+      p_mgr->p_subn->opt.ui_mcast_fdb_assign_ctx,
+      mlid, req_type, port_guid );
+  }    
+  
+ Exit:
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+mcast_mgr_dump_sw_routes(
+  IN const osm_mcast_mgr_t*   const p_mgr,
+  IN const osm_switch_t*      const p_sw,
+  IN FILE *file )
+{
+  osm_mcast_tbl_t*      p_tbl;
+  int16_t               mlid_ho = 0;
+  int16_t               mlid_start_ho;
+  uint8_t               position = 0;
+  int16_t               block_num = 0;
+  boolean_t             first_mlid;
+  boolean_t             first_port;
+  const osm_node_t*     p_node;
+  uint16_t              i, j;
+  uint16_t              mask_entry;
+  char                  sw_hdr[256];
+  char                  mlid_hdr[32];
+
+  OSM_LOG_ENTER( p_mgr->p_log, mcast_mgr_dump_sw_routes );
+  
+  if( !osm_log_is_active( p_mgr->p_log, OSM_LOG_ROUTING ) )
+    goto Exit;
+
+  p_node = osm_switch_get_node_ptr( p_sw );
+
+  p_tbl = osm_switch_get_mcast_tbl_ptr( p_sw );
+
+  sprintf( sw_hdr, "\nSwitch 0x%016" PRIx64 "\n"
+           "LID    : Out Port(s)\n",
+           cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+  first_mlid = TRUE;
+  while ( block_num <= p_tbl->max_block_in_use )
+  {
+    mlid_start_ho = (uint16_t)(block_num * IB_MCAST_BLOCK_SIZE);
+    for (i = 0 ; i < IB_MCAST_BLOCK_SIZE ; i++)
+    {
+      mlid_ho = mlid_start_ho + i;
+      position = 0;
+      first_port = TRUE;
+      sprintf( mlid_hdr, "0x%04X :", mlid_ho + IB_LID_MCAST_START_HO );
+      while ( position <= p_tbl->max_position )
+      {
+        mask_entry = cl_ntoh16((*p_tbl->p_mask_tbl)[mlid_ho][position]);
+        if (mask_entry == 0)
+        {
+          position++;
+          continue;
+        }
+        for (j = 0 ; j < 16 ; j++)
+        {
+          if ( (1 << j) & mask_entry )
+          {
+            if (first_mlid)
+            {
+              fprintf( file,"%s", sw_hdr );
+              first_mlid = FALSE;
+            }
+            if (first_port)
+            {
+              fprintf( file,"%s", mlid_hdr );
+              first_port = FALSE;
+            }
+            fprintf( file, " 0x%03X ", j+(position*16) );
+          }
+        }
+        position++;
+      }
+      if (first_port == FALSE)
+      {
+        fprintf( file, "\n" );
+      }
+    }
+    block_num++;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+struct mcast_mgr_dump_context {
+       osm_mcast_mgr_t *p_mgr;
+       FILE *file;
+};
+
+static void
+mcast_mgr_dump_table(cl_map_item_t *p_map_item, void *context)
+{
+       osm_switch_t *p_sw = (osm_switch_t *)p_map_item;
+       struct mcast_mgr_dump_context *cxt = context;
+
+       mcast_mgr_dump_sw_routes(cxt->p_mgr, p_sw, cxt->file);
+}
+
+static void
+mcast_mgr_dump_mcast_routes(osm_mcast_mgr_t *p_mgr)
+{
+       char file_name[1024];
+       struct mcast_mgr_dump_context dump_context;
+       FILE  *file;
+
+       if (!osm_log_is_active(p_mgr->p_log, OSM_LOG_ROUTING))
+               return;
+
+       snprintf(file_name, sizeof(file_name), "%s/%s",
+                p_mgr->p_subn->opt.dump_files_dir, "osm.mcfdbs");
+       file = fopen(file_name, "w");
+       if (!file) {
+               osm_log(p_mgr->p_log, OSM_LOG_ERROR,
+                       "mcast_dump_mcast_routes: ERR 0A18: "
+                       "cannot create mcfdb file \'%s\': %s\n",
+                       file_name, strerror(errno));
+               return;
+       }
+
+       dump_context.p_mgr = p_mgr;
+       dump_context.file = file;
+
+       cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl,
+                          mcast_mgr_dump_table, &dump_context);
+
+       fclose(file);
+}
+
+/**********************************************************************
+ Process the entire group.
+
+ NOTE : The lock should be held externally!
+ **********************************************************************/
+static osm_signal_t
+osm_mcast_mgr_process_mgrp(
+  IN osm_mcast_mgr_t*      const p_mgr,
+  IN osm_mgrp_t*           const p_mgrp,
+  IN osm_mcast_req_type_t        req_type,
+  IN ib_net64_t                  port_guid )
+{
+  osm_signal_t          signal = OSM_SIGNAL_DONE;
+  ib_api_status_t       status;
+  osm_switch_t*         p_sw;
+  cl_qmap_t*            p_sw_tbl;
+  boolean_t             pending_transactions = FALSE;
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_process_mgrp );
+
+  p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+  status = osm_mcast_mgr_process_tree( p_mgr, p_mgrp, req_type, port_guid );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "osm_mcast_mgr_process_mgrp: ERR 0A19: "
+             "Unable to create spanning tree (%s)\n",
+             ib_get_err_str( status ) );
+
+    goto Exit;
+  }
+
+  /*
+    Walk the switches and download the tables for each.
+  */
+  p_sw = (osm_switch_t*)cl_qmap_head( p_sw_tbl );
+  while( p_sw != (osm_switch_t*)cl_qmap_end( p_sw_tbl ) )
+  {
+    signal = __osm_mcast_mgr_set_tbl( p_mgr, p_sw );
+    if( signal == OSM_SIGNAL_DONE_PENDING )
+      pending_transactions = TRUE;
+
+    p_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item );
+  }
+
+  mcast_mgr_dump_mcast_routes( p_mgr );
+
+ Exit:
+  OSM_LOG_EXIT( p_mgr->p_log );
+
+  if( pending_transactions == TRUE )
+    return( OSM_SIGNAL_DONE_PENDING );
+  else
+    return( OSM_SIGNAL_DONE );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_signal_t
+osm_mcast_mgr_process(
+  IN osm_mcast_mgr_t*         const p_mgr )
+{
+  osm_signal_t          signal;
+  osm_switch_t*            p_sw;
+  cl_qmap_t*               p_sw_tbl;
+  cl_qmap_t*               p_mcast_tbl;
+  osm_mgrp_t*              p_mgrp;
+  ib_api_status_t          status;
+  boolean_t             pending_transactions = FALSE;
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_process );
+
+  p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+  p_mcast_tbl = &p_mgr->p_subn->mgrp_mlid_tbl;
+  /*
+    While holding the lock, iterate over all the established
+    multicast groups, servicing each in turn.
+
+    Then, download the multicast tables to the switches.
+  */
+  CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
+
+  p_mgrp = (osm_mgrp_t*)cl_qmap_head( p_mcast_tbl );
+  while( p_mgrp != (osm_mgrp_t*)cl_qmap_end( p_mcast_tbl ) )
+  {
+    /* We reached here due to some change that caused a heavy sweep
+       of the subnet. Not due to a specific multicast request.
+       So the request type is subnet_change and the port guid is 0. */
+    status = osm_mcast_mgr_process_tree( p_mgr, p_mgrp,
+                                         OSM_MCAST_REQ_TYPE_SUBNET_CHANGE, 0);
+    if( status != IB_SUCCESS )
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "osm_mcast_mgr_process: ERR 0A20: "
+               "Unable to create spanning tree (%s)\n",
+               ib_get_err_str( status ) );
+    }
+
+    p_mgrp = (osm_mgrp_t*)cl_qmap_next( &p_mgrp->map_item );
+  }
+
+  /*
+    Walk the switches and download the tables for each.
+  */
+  p_sw = (osm_switch_t*)cl_qmap_head( p_sw_tbl );
+  while( p_sw != (osm_switch_t*)cl_qmap_end( p_sw_tbl ) )
+  {
+    signal = __osm_mcast_mgr_set_tbl( p_mgr, p_sw );
+    if( signal == OSM_SIGNAL_DONE_PENDING )
+      pending_transactions = TRUE;
+
+    p_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item );
+  }
+
+  mcast_mgr_dump_mcast_routes( p_mgr );
+
+  CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+
+  if( pending_transactions == TRUE )
+    return( OSM_SIGNAL_DONE_PENDING );
+  else
+    return( OSM_SIGNAL_DONE );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static
+osm_mgrp_t *
+__get_mgrp_by_mlid(
+  IN osm_mcast_mgr_t* const p_mgr,
+  IN ib_net16_t const mlid)
+{
+  cl_map_item_t *map_item;
+
+  map_item = cl_qmap_get(&p_mgr->p_subn->mgrp_mlid_tbl, mlid);
+  if(map_item == cl_qmap_end(&p_mgr->p_subn->mgrp_mlid_tbl))
+  {
+    return NULL;
+  }
+  return (osm_mgrp_t *)map_item;
+}
+
+/**********************************************************************
+  This is the function that is invoked during idle time to handle the 
+  process request. Context1 is simply the osm_mcast_mgr_t*, Context2
+  hold the mlid, port guid and action (join/leave/delete) required.
+ **********************************************************************/
+osm_signal_t
+osm_mcast_mgr_process_mgrp_cb(
+  IN void*              const Context1,
+  IN void*              const Context2 )
+{
+  osm_mcast_mgr_t* p_mgr = (osm_mcast_mgr_t*)Context1;
+  osm_mgrp_t* p_mgrp;
+  ib_net16_t  mlid;
+  osm_signal_t signal = OSM_SIGNAL_DONE;
+  osm_mcast_mgr_ctxt_t* p_ctxt = (osm_mcast_mgr_ctxt_t*)Context2;
+  osm_mcast_req_type_t req_type = p_ctxt->req_type;
+  ib_net64_t port_guid = p_ctxt->port_guid;
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_process_mgrp_cb );
+  /* nice copy no warning on size diff */
+  memcpy(&mlid, &p_ctxt->mlid, sizeof(mlid));
+
+  /* we can destroy the context now */
+  free(p_ctxt);
+
+  /* we need a lock to make sure the p_mgrp is not change other ways */
+  CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
+  p_mgrp = __get_mgrp_by_mlid( p_mgr, mlid);
+
+  /* since we delayed the execution we prefer to pass the
+     mlid as the mgrp identifier and then find it or abort */
+
+  if (p_mgrp)
+  {
+
+    /* if there was no change from the last time we processed the group
+       we can skip doing anything
+    */
+    if ( p_mgrp->last_change_id == p_mgrp->last_tree_id)
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "osm_mcast_mgr_process_mgrp_cb: "
+               "Skip processing mgrp with lid:0x%X change id:%u\n",
+               cl_ntoh16(mlid), p_mgrp->last_change_id );
+    }
+    else
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "osm_mcast_mgr_process_mgrp_cb: "
+               "Processing mgrp with lid:0x%X change id:%u\n",
+               cl_ntoh16(mlid), p_mgrp->last_change_id );
+
+      signal =
+        osm_mcast_mgr_process_mgrp( p_mgr, p_mgrp, req_type, port_guid );
+      p_mgrp->last_tree_id = p_mgrp->last_change_id;
+    }
+
+    /* Remove MGRP only if osm_mcm_port_t count is 0 and
+     * Not a well known group
+     */
+    if((0x0 == cl_qmap_count(&p_mgrp->mcm_port_tbl)) &&
+       (p_mgrp->well_known == FALSE))
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "osm_mcast_mgr_process_mgrp_cb: "
+               "Destroying mgrp with lid:0x%X\n",
+               cl_ntoh16(mlid) );
+
+     /* Send a Report to any InformInfo registered for
+         Trap 67 : MCGroup delete */
+      osm_mgrp_send_delete_notice( p_mgr->p_subn, p_mgr->p_log, p_mgrp );
+
+      cl_qmap_remove_item(&p_mgr->p_subn->mgrp_mlid_tbl,
+                          (cl_map_item_t *)p_mgrp );
+
+      osm_mgrp_destroy(p_mgrp);
+    }
+  }
+
+  CL_PLOCK_RELEASE( p_mgr->p_lock );
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return signal;
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_tbl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcast_tbl.c
new file mode 100644 (file)
index 0000000..e60229c
--- /dev/null
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_mcast_tbl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_mcast_tbl_t.
+ * This object represents an multicast forwarding table.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_math.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_mcast_tbl.h>
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mcast_tbl_init(
+  IN osm_mcast_tbl_t* const p_tbl,
+  IN uint8_t const num_ports,
+  IN uint16_t const capacity )
+{
+  CL_ASSERT( p_tbl );
+  CL_ASSERT( num_ports );
+
+  memset( p_tbl, 0, sizeof(*p_tbl) );
+
+  p_tbl->max_block_in_use = -1;
+
+  if( capacity == 0 )
+  {
+    /*
+      This switch apparently doesn't support multicast.
+      Everything is initialized to zero already, so return.
+    */
+    return( IB_SUCCESS );
+  }
+
+  p_tbl->num_entries = capacity;
+  p_tbl->num_ports = num_ports;
+  p_tbl->max_position = (uint8_t)((ROUNDUP( num_ports, IB_MCAST_MASK_SIZE) /
+                                   IB_MCAST_MASK_SIZE) - 1);
+
+  p_tbl->max_block = (uint16_t)((ROUNDUP( p_tbl->num_entries,
+                                          IB_MCAST_BLOCK_SIZE ) / IB_MCAST_BLOCK_SIZE) - 1);
+
+  p_tbl->max_mlid_ho = (uint16_t)(IB_LID_MCAST_START_HO + capacity);
+
+  /*
+    The number of bytes needed in the mask table is:
+    The (maximum bit mask 'position' + 1) times the
+    number of bytes in each bit mask times the
+    number of MLIDs supported by the table.
+
+    We must always allocate the array with the maximum position
+    since it is (and must be) defined that way the table structure
+    in order to create a pointer to a two dimensional array.
+  */
+  p_tbl->p_mask_tbl = malloc( p_tbl->num_entries *
+                              (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_MASK_SIZE / 8 );
+
+  if( p_tbl->p_mask_tbl == NULL )
+    return( IB_INSUFFICIENT_MEMORY );
+
+  memset(p_tbl->p_mask_tbl, 0,
+         p_tbl->num_entries * (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_MASK_SIZE / 8 );
+  return( IB_SUCCESS );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcast_tbl_destroy(
+  IN osm_mcast_tbl_t* const p_tbl )
+{
+  free( p_tbl->p_mask_tbl );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcast_tbl_set(
+  IN osm_mcast_tbl_t* const p_tbl,
+  IN const uint16_t mlid_ho,
+  IN const uint8_t port )
+{
+  uintn_t mlid_offset;
+  uintn_t mask_offset;
+  uintn_t bit_mask;
+  int16_t block_num;
+
+  CL_ASSERT( p_tbl );
+  CL_ASSERT( mlid_ho >= IB_LID_MCAST_START_HO );
+  CL_ASSERT( mlid_ho <= p_tbl->max_mlid_ho );
+  CL_ASSERT( p_tbl->p_mask_tbl );
+
+  mlid_offset = mlid_ho - IB_LID_MCAST_START_HO;
+  mask_offset = port / IB_MCAST_MASK_SIZE;
+  bit_mask = cl_ntoh16( (uint16_t)( 1 << (port % IB_MCAST_MASK_SIZE) ) );
+  (*p_tbl->p_mask_tbl)[mlid_offset][mask_offset] |= bit_mask;
+
+  block_num = (int16_t)(mlid_offset / IB_MCAST_BLOCK_SIZE);
+
+  if( block_num > p_tbl->max_block_in_use )
+    p_tbl->max_block_in_use = (uint16_t)block_num;
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_mcast_tbl_is_port(
+  IN const osm_mcast_tbl_t* const p_tbl,
+  IN const uint16_t mlid_ho,
+  IN const uint8_t port_num )
+{
+  uintn_t mlid_offset;
+  uintn_t mask_offset;
+  uintn_t bit_mask;
+
+  CL_ASSERT( p_tbl );
+
+  if( p_tbl->p_mask_tbl )
+  {
+    CL_ASSERT( port_num <= (p_tbl->max_position + 1) * IB_MCAST_MASK_SIZE );
+    CL_ASSERT( mlid_ho >= IB_LID_MCAST_START_HO );
+    CL_ASSERT( mlid_ho <= p_tbl->max_mlid_ho );
+
+    mlid_offset = mlid_ho - IB_LID_MCAST_START_HO;
+    mask_offset = port_num / IB_MCAST_MASK_SIZE;
+    bit_mask = cl_ntoh16(
+      (uint16_t)( 1 << (port_num % IB_MCAST_MASK_SIZE) ) );
+    return( ((*p_tbl->p_mask_tbl)[mlid_offset][mask_offset] & bit_mask) ==
+            bit_mask );
+  }
+
+  return( FALSE );
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_mcast_tbl_is_any_port(
+  IN const osm_mcast_tbl_t* const p_tbl,
+  IN const uint16_t mlid_ho )
+{
+  uintn_t mlid_offset;
+  uint8_t position;
+  uint16_t result = 0;
+
+  CL_ASSERT( p_tbl );
+
+  if( p_tbl->p_mask_tbl )
+  {
+    CL_ASSERT( mlid_ho >= IB_LID_MCAST_START_HO );
+    CL_ASSERT( mlid_ho <= p_tbl->max_mlid_ho );
+
+    mlid_offset = mlid_ho - IB_LID_MCAST_START_HO;
+
+    for( position = 0; position <= p_tbl->max_position; position++ )
+      result |= (*p_tbl->p_mask_tbl)[mlid_offset][position];
+  }
+
+  return( result != 0 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mcast_tbl_set_block(
+  IN osm_mcast_tbl_t* const p_tbl,
+  IN const ib_net16_t* const p_block,
+  IN const int16_t block_num,
+  IN const uint8_t position )
+{
+  uint32_t i;
+  uint16_t mlid_start_ho;
+
+  CL_ASSERT( p_tbl );
+  CL_ASSERT( p_block );
+
+  if( block_num > p_tbl->max_block )
+    return( IB_INVALID_PARAMETER );
+
+  if( position > p_tbl->max_position )
+    return( IB_INVALID_PARAMETER );
+
+  mlid_start_ho = (uint16_t)(block_num * IB_MCAST_BLOCK_SIZE);
+
+  if( mlid_start_ho + IB_MCAST_BLOCK_SIZE > p_tbl->max_mlid_ho )
+    return( IB_INVALID_PARAMETER );
+
+  for( i = 0; i < IB_MCAST_BLOCK_SIZE; i++ )
+    (*p_tbl->p_mask_tbl)[mlid_start_ho + i][position] = p_block[i];
+
+  if( block_num > p_tbl->max_block_in_use )
+    p_tbl->max_block_in_use = (uint16_t)block_num;
+
+  return( IB_SUCCESS );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcast_tbl_clear_mlid(
+  IN osm_mcast_tbl_t* const p_tbl,
+  IN const uint16_t mlid_ho )
+{
+  uint8_t i;
+  uintn_t mlid_offset;
+
+  CL_ASSERT( p_tbl );
+  CL_ASSERT( mlid_ho >= IB_LID_MCAST_START_HO );
+
+  if( p_tbl->p_mask_tbl && (mlid_ho <= p_tbl->max_mlid_ho) )
+  {
+    mlid_offset = mlid_ho - IB_LID_MCAST_START_HO;
+    for( i = 0; i <= p_tbl->max_position; i++ )
+      (*p_tbl->p_mask_tbl)[mlid_offset][i] = 0;
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_mcast_tbl_get_block(
+  IN osm_mcast_tbl_t*      const p_tbl,
+  IN int16_t               const block_num,
+  IN uint8_t               const position,
+  OUT ib_net16_t*          const p_block )
+{
+  uint32_t i;
+  uint16_t mlid_start_ho;
+
+  CL_ASSERT( p_tbl );
+  CL_ASSERT( p_block );
+
+  if( block_num > p_tbl->max_block_in_use )
+    return( FALSE );
+
+  if( position > p_tbl->max_position )
+  {
+    /*
+      Caller shouldn't do this for efficiency's sake...
+    */
+    memset( p_block, 0, IB_SMP_DATA_SIZE );
+    return( TRUE );
+  }
+
+  mlid_start_ho = (uint16_t)(block_num * IB_MCAST_BLOCK_SIZE);
+
+  if( mlid_start_ho + IB_MCAST_BLOCK_SIZE > p_tbl->max_mlid_ho )
+    return( IB_INVALID_PARAMETER );
+
+  for( i = 0; i < IB_MCAST_BLOCK_SIZE; i++ )
+    p_block[i] = (*p_tbl->p_mask_tbl)[mlid_start_ho + i][position];
+
+  return( TRUE );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcm_info.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcm_info.c
new file mode 100644 (file)
index 0000000..770aa04
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_mcm_info.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Declaration of osm_mcm_info_t.
+ * This object represents a Multicast Forwarding Information object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <opensm/osm_mcm_info.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcm_info_destroy(
+  IN osm_mcm_info_t* const p_mcm )
+{
+  CL_ASSERT( p_mcm );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcm_info_init(
+  IN osm_mcm_info_t* const p_mcm,
+  IN const ib_net16_t mlid )
+{
+  CL_ASSERT( p_mcm );
+  p_mcm->mlid = mlid;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_mcm_info_t*
+osm_mcm_info_new(
+  IN const ib_net16_t mlid )
+{
+  osm_mcm_info_t* p_mcm;
+
+  p_mcm = (osm_mcm_info_t*)malloc( sizeof(*p_mcm) );
+  if( p_mcm )
+  {
+    memset(p_mcm, 0, sizeof(*p_mcm) );
+    osm_mcm_info_init( p_mcm, mlid );
+  }
+
+  return( p_mcm );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcm_info_delete(
+  IN osm_mcm_info_t* const p_mcm )
+{
+  osm_mcm_info_destroy( p_mcm );
+  free( p_mcm );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcm_port.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mcm_port.c
new file mode 100644 (file)
index 0000000..5996ac9
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_mcm_port.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_mcm_port_t.
+ * This object represents the membership of a port in a multicast group.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <opensm/osm_mcm_port.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcm_port_construct(
+  IN osm_mcm_port_t* const p_mcm )
+{
+  memset( p_mcm, 0, sizeof(*p_mcm) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcm_port_destroy(
+  IN osm_mcm_port_t* const p_mcm )
+{
+  /*
+    Nothing to do?
+  */
+  UNUSED_PARAM( p_mcm );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcm_port_init(
+  IN osm_mcm_port_t* const p_mcm,
+  IN const ib_gid_t* const p_port_gid,
+  IN const uint8_t   scope_state,
+  IN const boolean_t proxy_join )
+{
+  CL_ASSERT( p_mcm );
+  CL_ASSERT( p_port_gid );
+  CL_ASSERT( scope_state );
+
+  osm_mcm_port_construct( p_mcm );
+  p_mcm->port_gid = *p_port_gid;
+  p_mcm->scope_state = scope_state;
+  p_mcm->proxy_join = proxy_join;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_mcm_port_t*
+osm_mcm_port_new(
+  IN const ib_gid_t* const p_port_gid,
+  IN const uint8_t   scope_state,
+  IN const boolean_t proxy_join )
+{
+  osm_mcm_port_t* p_mcm;
+
+  p_mcm = malloc( sizeof(*p_mcm) );
+  if( p_mcm )
+  {
+    osm_mcm_port_init( p_mcm, p_port_gid,
+                       scope_state, proxy_join );
+  }
+
+  return( p_mcm );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcm_port_delete(
+  IN osm_mcm_port_t* const p_mcm )
+{
+  CL_ASSERT( p_mcm );
+
+  osm_mcm_port_destroy( p_mcm );
+  free( p_mcm );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mtree.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_mtree.c
new file mode 100644 (file)
index 0000000..16283a0
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_mtree.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_mtree_node_t.
+ * This file implements the Multicast Tree object.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_mtree.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mtree_node_init(
+  IN osm_mtree_node_t*     const p_mtn,
+  IN const osm_switch_t*      const p_sw )
+{
+  uint32_t              i;
+
+  CL_ASSERT( p_mtn );
+  CL_ASSERT( p_sw );
+
+  osm_mtree_node_construct( p_mtn );
+
+  p_mtn->p_sw = (osm_switch_t*)p_sw;
+  p_mtn->max_children = osm_switch_get_num_ports( p_sw );
+
+  for( i = 0; i < p_mtn->max_children; i++ )
+    p_mtn->child_array[i] = NULL;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_mtree_node_t*
+osm_mtree_node_new(
+  IN const osm_switch_t* const p_sw )
+{
+  osm_mtree_node_t *p_mtn;
+
+  p_mtn = malloc( sizeof(osm_mtree_node_t) +
+                  sizeof(void*) * (osm_switch_get_num_ports( p_sw ) - 1) );
+
+  if( p_mtn != NULL )
+    osm_mtree_node_init( p_mtn, p_sw );
+
+  return( p_mtn );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mtree_destroy(
+  IN osm_mtree_node_t *p_mtn )
+{
+  uint32_t i;
+
+  if (p_mtn == NULL)
+    return;
+
+  if ( p_mtn->child_array != NULL ) 
+    for (i = 0 ; i< p_mtn->max_children; i++ )
+      if ( (p_mtn->child_array[i] != NULL) && 
+           (p_mtn->child_array[i] != OSM_MTREE_LEAF) )
+        osm_mtree_destroy(p_mtn->child_array[i]);
+  
+  free( p_mtn );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_mtree_dump(
+  IN osm_mtree_node_t *p_mtn )
+{
+  uint32_t i;
+
+  if (p_mtn == NULL)
+    return;
+
+  printf("GUID:0x%016" PRIx64 " max_children:%u\n",
+         cl_ntoh64(p_mtn->p_sw->p_node->node_info.node_guid),
+         p_mtn->max_children );
+  if ( p_mtn->child_array != NULL ) 
+  {
+    for (i = 0 ; i< p_mtn->max_children; i++ )
+    {
+      printf("i=%d\n", i);
+      if ( (p_mtn->child_array[i] != NULL) && (p_mtn->child_array[i] != OSM_MTREE_LEAF) )
+        __osm_mtree_dump(p_mtn->child_array[i]);
+    }
+  }
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_multicast.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_multicast.c
new file mode 100644 (file)
index 0000000..858685d
--- /dev/null
@@ -0,0 +1,403 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_multicast.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of multicast functions.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <opensm/osm_multicast.h>
+#include <opensm/osm_mcm_port.h>
+#include <opensm/osm_mtree.h>
+#include <opensm/osm_inform.h>
+
+/**********************************************************************
+ **********************************************************************/
+/* osm_mcast_req_type_t values converted to test for easier printing. */ 
+const char* osm_mcast_req_type_str[] =
+{
+  "OSM_MCAST_REQ_TYPE_CREATE",
+  "OSM_MCAST_REQ_TYPE_JOIN",
+  "OSM_MCAST_REQ_TYPE_LEAVE",
+  "OSM_MCAST_REQ_TYPE_SUBNET_CHANGE"
+};
+
+const char*
+osm_get_mcast_req_type_str(
+  IN osm_mcast_req_type_t  req_type )
+{
+  if ( req_type > OSM_MCAST_REQ_TYPE_SUBNET_CHANGE )
+    req_type = OSM_MCAST_REQ_TYPE_SUBNET_CHANGE;
+  return( osm_mcast_req_type_str[req_type] );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mgrp_construct(
+  IN osm_mgrp_t* const p_mgrp )
+{
+  memset( p_mgrp, 0, sizeof(*p_mgrp) );
+  cl_qmap_init( &p_mgrp->mcm_port_tbl );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mgrp_destroy(
+  IN osm_mgrp_t* const p_mgrp )
+{
+  osm_mcm_port_t *p_mcm_port;
+  osm_mcm_port_t *p_next_mcm_port;
+
+  CL_ASSERT(p_mgrp);
+
+  p_next_mcm_port = (osm_mcm_port_t*)cl_qmap_head( &p_mgrp->mcm_port_tbl );
+  while( p_next_mcm_port != (osm_mcm_port_t*)cl_qmap_end( &p_mgrp->mcm_port_tbl ) )
+  {
+    p_mcm_port = p_next_mcm_port;
+    p_next_mcm_port = (osm_mcm_port_t*)cl_qmap_next( &p_mcm_port->map_item );
+    osm_mcm_port_delete( p_mcm_port );
+  }
+  /* destroy the mtree_node structure */
+  osm_mtree_destroy(p_mgrp->p_root);
+
+  free(p_mgrp);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mgrp_init(
+  IN osm_mgrp_t* const p_mgrp,
+  IN const ib_net16_t mlid )
+{
+  CL_ASSERT( p_mgrp );
+  CL_ASSERT( cl_ntoh16( mlid ) >= IB_LID_MCAST_START_HO );
+
+  osm_mgrp_construct( p_mgrp );
+  p_mgrp->mlid = mlid;
+  p_mgrp->last_change_id = 0;
+  p_mgrp->last_tree_id = 0;
+  p_mgrp->to_be_deleted = FALSE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_mgrp_t*
+osm_mgrp_new(
+  IN const ib_net16_t mlid )
+{
+  osm_mgrp_t* p_mgrp;
+
+  p_mgrp = (osm_mgrp_t*)malloc( sizeof(*p_mgrp) );
+  if( p_mgrp )
+    osm_mgrp_init( p_mgrp, mlid );
+
+  return( p_mgrp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_mcm_port_t*
+osm_mgrp_add_port(
+  IN osm_mgrp_t* const p_mgrp,
+  IN const ib_gid_t* const p_port_gid,
+  IN const uint8_t join_state,
+  IN boolean_t     proxy_join )
+{
+  ib_net64_t port_guid;
+  osm_mcm_port_t *p_mcm_port;
+  cl_map_item_t *prev_item;
+  uint8_t prev_join_state;
+  uint8_t prev_scope;
+
+  p_mcm_port = osm_mcm_port_new( p_port_gid, join_state, proxy_join );
+  if( p_mcm_port )
+  {
+    port_guid = p_port_gid->unicast.interface_id;
+
+    /*
+      prev_item = cl_qmap_insert(...)
+      Pointer to the item in the map with the specified key.  If insertion
+      was successful, this is the pointer to the item.  If an item with the
+      specified key already exists in the map, the pointer to that item is
+      returned.
+    */
+    prev_item = cl_qmap_insert( &p_mgrp->mcm_port_tbl,
+                                port_guid, &p_mcm_port->map_item );
+
+    /* if already exists - revert the insertion and only update join state */
+    if( prev_item != &p_mcm_port->map_item )
+    {
+
+      osm_mcm_port_delete( p_mcm_port );
+      p_mcm_port =(osm_mcm_port_t *) prev_item;
+
+      /*
+         o15.0.1.11
+         Join state of the end port should be the or of the
+         previous setting with the current one
+       */
+      ib_member_get_scope_state(p_mcm_port->scope_state, &prev_scope, &prev_join_state);
+      p_mcm_port->scope_state =
+        ib_member_set_scope_state(prev_scope, prev_join_state | join_state);
+
+    }
+    else
+    {
+      /* track the fact we modified the group ports */
+      p_mgrp->last_change_id++;
+    }
+  }
+
+  return( p_mcm_port );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mgrp_remove_port(
+  IN osm_subn_t* const p_subn,
+  IN osm_log_t* const p_log,
+  IN osm_mgrp_t* const p_mgrp,
+  IN const ib_net64_t port_guid )
+{
+  cl_map_item_t *p_map_item;
+
+  CL_ASSERT(p_mgrp);
+
+  p_map_item = cl_qmap_get( &p_mgrp->mcm_port_tbl, port_guid );
+
+  if( p_map_item != cl_qmap_end( &p_mgrp->mcm_port_tbl ) )
+  {
+    cl_qmap_remove_item( &p_mgrp->mcm_port_tbl,
+                         p_map_item );
+    osm_mcm_port_delete((osm_mcm_port_t*)p_map_item);
+
+    /* track the fact we modified the group */
+    p_mgrp->last_change_id++;
+  }
+
+  /* 
+     no more ports so the group will be deleted after re-route 
+     but only if it is not a well known group and not already deleted
+   */
+  if ((cl_is_qmap_empty( &p_mgrp->mcm_port_tbl )) && 
+      (p_mgrp->well_known == FALSE) &&
+      (p_mgrp->to_be_deleted  == FALSE))
+  {
+    p_mgrp->to_be_deleted = TRUE;
+    
+    /* Send a Report to any InformInfo registered for
+       Trap 67 : MCGroup delete */
+    osm_mgrp_send_delete_notice( p_subn, p_log, p_mgrp );
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_mgrp_is_port_present(
+  IN const osm_mgrp_t* const p_mgrp,
+  IN const ib_net64_t port_guid,
+  OUT osm_mcm_port_t ** const pp_mcm_port )
+{
+  cl_map_item_t *p_map_item;
+
+  CL_ASSERT(p_mgrp);
+
+  p_map_item = cl_qmap_get(&p_mgrp->mcm_port_tbl,
+                           port_guid);
+
+  if (p_map_item != cl_qmap_end(&p_mgrp->mcm_port_tbl))
+  {
+    if (pp_mcm_port)
+      *pp_mcm_port = (osm_mcm_port_t *)p_map_item;
+    return TRUE;
+  }
+  if (pp_mcm_port)
+    *pp_mcm_port = NULL;
+  return FALSE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mgrp_apply_func_sub(
+  const osm_mgrp_t* const p_mgrp,
+  const osm_mtree_node_t* const p_mtn,
+  osm_mgrp_func_t p_func,
+  void* context )
+{
+  uint8_t i = 0;
+  uint8_t max_children;
+  osm_mtree_node_t* p_child_mtn;
+
+  /*
+    Call the user, then recurse.
+  */
+  p_func( p_mgrp, p_mtn, context );
+
+  max_children = osm_mtree_node_get_max_children( p_mtn );
+  for( i = 0; i < max_children; i++ )
+  {
+    p_child_mtn = osm_mtree_node_get_child( p_mtn, i );
+    if( p_child_mtn )
+      __osm_mgrp_apply_func_sub( p_mgrp, p_child_mtn, p_func, context );
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mgrp_apply_func(
+  const osm_mgrp_t* const p_mgrp,
+  osm_mgrp_func_t p_func,
+  void* context )
+{
+  osm_mtree_node_t* p_mtn;
+
+  CL_ASSERT( p_mgrp );
+  CL_ASSERT( p_func );
+
+  p_mtn = p_mgrp->p_root;
+
+  if( p_mtn )
+    __osm_mgrp_apply_func_sub( p_mgrp, p_mtn, p_func, context );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mgrp_send_delete_notice(
+   IN osm_subn_t* const p_subn,
+   IN osm_log_t* const p_log,
+   IN osm_mgrp_t *p_mgrp )
+{
+  ib_mad_notice_attr_t    notice;
+  ib_api_status_t         status;
+
+  OSM_LOG_ENTER( p_log, osm_mgrp_send_delete_notice );
+
+  /* prepare the needed info */
+
+  /* details of the notice */
+  notice.generic_type = 0x83; /* is generic subn mgt type */
+  ib_notice_set_prod_type_ho(&notice, 4); /* A Class Manager generator */
+  notice.g_or_v.generic.trap_num = CL_HTON16(67); /* delete of mcg */
+  /* The sm_base_lid is saved in network order already. */
+  notice.issuer_lid = p_subn->sm_base_lid;
+  /* following o14-12.1.11 and table 120 p726 */
+  /* we need to provide the MGID */
+  memcpy(&(notice.data_details.ntc_64_67.gid),
+         &(p_mgrp->mcmember_rec.mgid),
+         sizeof(ib_gid_t));
+
+  /* According to page 653 - the issuer gid in this case of trap
+     is the SM gid, since the SM is the initiator of this trap. */
+  notice.issuer_gid.unicast.prefix = p_subn->opt.subnet_prefix;
+  notice.issuer_gid.unicast.interface_id = p_subn->sm_port_guid;
+
+  status = osm_report_notice(p_log, p_subn, &notice);
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_mgrp_send_delete_notice: ERR 7601: "
+             "Error sending trap reports (%s)\n",
+             ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mgrp_send_create_notice(
+   IN osm_subn_t* const p_subn,
+   IN osm_log_t* const p_log,
+   IN osm_mgrp_t *p_mgrp )
+{
+  ib_mad_notice_attr_t    notice;
+  ib_api_status_t         status;
+
+  OSM_LOG_ENTER( p_log, osm_mgrp_send_create_notice );
+
+  /* prepare the needed info */
+
+  /* details of the notice */
+  notice.generic_type = 0x83; /* Generic SubnMgt type */
+  ib_notice_set_prod_type_ho(&notice, 4); /* A Class Manager generator */
+  notice.g_or_v.generic.trap_num = CL_HTON16(66); /* create of mcg */
+  /* The sm_base_lid is saved in network order already. */
+  notice.issuer_lid = p_subn->sm_base_lid;
+  /* following o14-12.1.11 and table 120 p726 */
+  /* we need to provide the MGID */
+  memcpy(&(notice.data_details.ntc_64_67.gid),
+         &(p_mgrp->mcmember_rec.mgid),
+         sizeof(ib_gid_t));
+
+  /* According to page 653 - the issuer gid in this case of trap
+     is the SM gid, since the SM is the initiator of this trap. */
+  notice.issuer_gid.unicast.prefix = p_subn->opt.subnet_prefix;
+  notice.issuer_gid.unicast.interface_id = p_subn->sm_port_guid;
+
+  status = osm_report_notice(p_log, p_subn, &notice);
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_mgrp_send_create_notice: ERR 7602: "
+             "Error sending trap reports (%s)\n",
+             ib_get_err_str( status ) );
+    goto Exit;
+  }
+  
+ Exit:
+  OSM_LOG_EXIT( p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node.c
new file mode 100644 (file)
index 0000000..72a77c7
--- /dev/null
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_node.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_node_t.
+ * This object represents an Infiniband Node.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_madw.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_node_init_physp(
+  IN osm_node_t* const p_node,
+  IN const osm_madw_t* const p_madw )
+{
+  osm_physp_t        *p_physp;
+  ib_net64_t         port_guid;
+  ib_smp_t        *p_smp;
+  ib_node_info_t     *p_ni;
+  uint8_t            port_num;
+
+  CL_ASSERT( p_node );
+  CL_ASSERT( p_madw );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+
+  CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_NODE_INFO );
+
+  p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp );
+  port_guid = p_ni->port_guid;
+  port_num = ib_node_info_get_local_port_num( p_ni );
+
+  CL_ASSERT( port_num < p_node->physp_tbl_size );
+
+  p_physp = osm_node_get_physp_ptr( p_node, port_num );
+
+  osm_physp_init( p_physp, port_guid, port_num, p_node,
+                  osm_madw_get_bind_handle( p_madw ),
+                  p_smp->hop_count, p_smp->initial_path );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_node_t*
+osm_node_new(
+  IN const osm_madw_t* const p_madw )
+{
+  osm_node_t         *p_node;
+  ib_smp_t        *p_smp;
+  ib_node_info_t     *p_ni;
+  uint8_t            i;
+  uint32_t        size;
+
+  CL_ASSERT( p_madw );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+
+  CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_NODE_INFO );
+
+  p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp );
+
+  /*
+    The node object already contains one physical port object.
+    Therefore, subtract 1 from the number of physical ports
+    used by the switch.  This is not done for CA's since they
+    need to occupy 1 more physp than they physically have since
+    we still reserve room for a "port 0".
+  */
+  size = p_ni->num_ports;
+
+  p_node = malloc( sizeof(*p_node) + sizeof(osm_physp_t) * size );
+  if( p_node != NULL )
+  {
+    memset( p_node, 0, sizeof(*p_node) + sizeof(osm_physp_t) * size );
+    p_node->node_info = *p_ni;
+    p_node->physp_tbl_size = size + 1;
+
+    /*
+      Construct Physical Port objects owned by this Node.
+      Then, initialize the Physical Port through with we
+      discovered this port.
+      For switches, all ports have the same GUID.
+      For HCA's each port has a different GUID, so we only
+      know the GUID for the port that responded to our
+      Get(NodeInfo).
+    */
+    for( i = 0; i < p_node->physp_tbl_size; i++ )
+      osm_physp_construct( osm_node_get_physp_ptr( p_node, i ) );
+
+    osm_node_init_physp( p_node, p_madw );
+  }
+
+  return( p_node );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_node_destroy(
+  IN osm_node_t *p_node )
+{
+  uint16_t i;
+
+  /* Cleanup all PhysPorts */
+  if( p_node != NULL )
+  {
+    /*
+      Cleanup all physports 
+    */
+    for( i = 0; i < p_node->physp_tbl_size; i++ )
+    {
+      osm_physp_t *p_physp = osm_node_get_physp_ptr( p_node, i );
+      if (p_physp) 
+        osm_physp_destroy( p_physp );
+    }
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_node_delete(
+  IN OUT osm_node_t** const p_node )
+{
+  osm_node_destroy( *p_node );
+  free( *p_node );
+  *p_node = NULL;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_node_link(
+  IN osm_node_t* const p_node,
+  IN const uint8_t port_num,
+  IN osm_node_t* const p_remote_node,
+  IN const uint8_t remote_port_num )
+{
+  osm_physp_t *p_physp;
+  osm_physp_t *p_remote_physp;
+
+  CL_ASSERT( port_num < p_node->physp_tbl_size );
+  CL_ASSERT( remote_port_num < p_remote_node->physp_tbl_size );
+
+  p_physp = osm_node_get_physp_ptr( p_node, port_num );
+  p_remote_physp =  osm_node_get_physp_ptr( p_remote_node,
+                                            remote_port_num );
+
+  if (p_physp->p_remote_physp)
+    p_physp->p_remote_physp->p_remote_physp = NULL;
+  if (p_remote_physp->p_remote_physp)
+    p_remote_physp->p_remote_physp->p_remote_physp = NULL;
+
+  osm_physp_link( p_physp, p_remote_physp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_node_unlink(
+  IN osm_node_t* const p_node,
+  IN const uint8_t port_num,
+  IN osm_node_t* const p_remote_node,
+  IN const uint8_t remote_port_num )
+{
+  osm_physp_t *p_physp;
+  osm_physp_t *p_remote_physp;
+
+  CL_ASSERT( port_num < p_node->physp_tbl_size );
+  CL_ASSERT( remote_port_num < p_remote_node->physp_tbl_size );
+
+  if( osm_node_link_exists( p_node, port_num,
+                            p_remote_node, remote_port_num ) )
+  {
+
+    p_physp = osm_node_get_physp_ptr( p_node, port_num );
+    p_remote_physp =  osm_node_get_physp_ptr( p_remote_node,
+                                              remote_port_num );
+
+    osm_physp_unlink( p_physp, p_remote_physp );
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_node_link_exists(
+  IN osm_node_t* const p_node,
+  IN const uint8_t port_num,
+  IN osm_node_t* const p_remote_node,
+  IN const uint8_t remote_port_num )
+{
+  osm_physp_t *p_physp;
+  osm_physp_t *p_remote_physp;
+
+  CL_ASSERT( port_num < p_node->physp_tbl_size );
+  CL_ASSERT( remote_port_num < p_remote_node->physp_tbl_size );
+
+  p_physp = osm_node_get_physp_ptr( p_node, port_num );
+  p_remote_physp =  osm_node_get_physp_ptr( p_remote_node,
+                                            remote_port_num );
+
+  return( osm_physp_link_exists( p_physp, p_remote_physp ) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_node_link_has_valid_ports(
+  IN osm_node_t* const p_node,
+  IN const uint8_t port_num,
+  IN osm_node_t* const p_remote_node,
+  IN const uint8_t remote_port_num )
+{
+  osm_physp_t *p_physp;
+  osm_physp_t *p_remote_physp;
+
+  CL_ASSERT( port_num < p_node->physp_tbl_size );
+  CL_ASSERT( remote_port_num < p_remote_node->physp_tbl_size );
+
+  p_physp = osm_node_get_physp_ptr( p_node, port_num );
+  p_remote_physp =  osm_node_get_physp_ptr( p_remote_node,
+                                            remote_port_num );
+
+  return( osm_physp_is_valid( p_physp ) &&
+          osm_physp_is_valid( p_remote_physp ) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_node_has_any_link(
+  IN osm_node_t* const p_node,
+  IN const uint8_t port_num )
+{
+  osm_physp_t *p_physp;
+  CL_ASSERT( port_num < p_node->physp_tbl_size );
+  p_physp = osm_node_get_physp_ptr( p_node, port_num );
+  return( osm_physp_has_any_link( p_physp ) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_node_t*
+osm_node_get_remote_node(
+  IN const osm_node_t* const p_node,
+  IN const uint8_t port_num,
+  OUT uint8_t *p_remote_port_num )
+{
+  osm_physp_t *p_physp;
+  osm_physp_t *p_remote_physp;
+
+  p_physp = osm_node_get_physp_ptr( p_node, port_num );
+
+  if( !osm_physp_has_any_link( p_physp ) )
+    return( NULL );
+
+  p_remote_physp = osm_physp_get_remote( p_physp );
+  if( p_remote_port_num )
+    *p_remote_port_num = osm_physp_get_port_num( p_remote_physp );
+
+  return( osm_physp_get_node_ptr( p_remote_physp ) );
+}
+
+/**********************************************************************
+ The lock must be held before calling this function.
+**********************************************************************/
+ib_net16_t
+osm_node_get_remote_base_lid(
+  IN const osm_node_t* const p_node,
+  IN const uint32_t port_num )
+{
+  osm_physp_t *p_physp;
+  osm_physp_t *p_remote_physp;
+  CL_ASSERT( port_num < p_node->physp_tbl_size );
+
+  p_physp = osm_node_get_physp_ptr( p_node, port_num );
+  if( osm_physp_is_valid( p_physp ) )
+  {
+    p_remote_physp = osm_physp_get_remote( p_physp );
+    return( osm_physp_get_base_lid( p_remote_physp ) );
+  }
+
+  return( 0 );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_desc_rcv.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_desc_rcv.c
new file mode 100644 (file)
index 0000000..f21c481
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_node_desc_rcv.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_nd_rcv_t.
+ * This object represents the NodeDescription Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_node_desc_rcv.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_subnet.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_nd_rcv_process_nd(
+  IN const osm_nd_rcv_t* const p_rcv,
+  IN osm_node_t* const p_node,
+  IN const ib_node_desc_t* const p_nd )
+{
+  char desc[IB_NODE_DESCRIPTION_SIZE + 1];
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_nd_rcv_process_nd );
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+  {
+    memcpy( desc, p_nd, sizeof(*p_nd) );
+    /* Guarantee null termination before printing. */
+    desc[IB_NODE_DESCRIPTION_SIZE] = '\0';
+
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "__osm_nd_rcv_process_nd: "
+             "Node 0x%" PRIx64 "\n\t\t\t\tDescription = %s\n",
+             cl_ntoh64( osm_node_get_node_guid( p_node )), desc );
+  }
+
+  memcpy( &p_node->node_desc.description, p_nd, sizeof(*p_nd) );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nd_rcv_construct(
+  IN osm_nd_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nd_rcv_destroy(
+  IN osm_nd_rcv_t* const p_rcv )
+{
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_nd_rcv_destroy );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_nd_rcv_init(
+  IN osm_nd_rcv_t* const p_rcv,
+  IN osm_subn_t* const p_subn,
+  IN osm_log_t* const p_log,
+  IN cl_plock_t* const p_lock )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_nd_rcv_init );
+
+  osm_nd_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nd_rcv_process(
+  IN const osm_nd_rcv_t* const p_rcv,
+  IN osm_madw_t* const p_madw )
+{
+  cl_qmap_t *p_guid_tbl;
+  ib_node_desc_t *p_nd;
+  ib_smp_t *p_smp;
+  osm_node_t *p_node;
+  ib_net64_t node_guid;
+
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_nd_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_guid_tbl = &p_rcv->p_subn->node_guid_tbl;
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+  p_nd = (ib_node_desc_t*)ib_smp_get_payload_ptr( p_smp );
+
+  /*
+    Acquire the node object and add the node description.
+  */
+
+  node_guid = osm_madw_get_nd_context_ptr( p_madw )->node_guid;
+  CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
+  p_node = (osm_node_t*)cl_qmap_get( p_guid_tbl, node_guid );
+
+  if( p_node == (osm_node_t*)cl_qmap_end( p_guid_tbl) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_nd_rcv_process: ERR 0B01: "
+             "NodeDescription received for nonexistent node "
+             "0x%" PRIx64 "\n", cl_ntoh64(node_guid) );
+  }
+  else
+  {
+    __osm_nd_rcv_process_nd( p_rcv, p_node, p_nd );
+  }
+
+  CL_PLOCK_RELEASE( p_rcv->p_lock );
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_desc_rcv_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_desc_rcv_ctrl.c
new file mode 100644 (file)
index 0000000..1a185c7
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_node_desc_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_nd_rcv_ctrl_t.
+ * This object represents the NodeDescription request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_node_desc_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_nd_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_nd_rcv_process( ((osm_nd_rcv_ctrl_t*)context)->p_rcv,
+                      (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nd_rcv_ctrl_construct(
+  IN osm_nd_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nd_rcv_ctrl_destroy(
+  IN osm_nd_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_nd_rcv_ctrl_init(
+  IN osm_nd_rcv_ctrl_t* const p_ctrl,
+  IN osm_nd_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_nd_rcv_ctrl_init );
+
+  osm_nd_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_NODE_DESC,
+    __osm_nd_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_nd_rcv_ctrl_init: ERR 0C01: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_info_rcv.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_info_rcv.c
new file mode 100644 (file)
index 0000000..038f519
--- /dev/null
@@ -0,0 +1,1090 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_node_info_rcv.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_ni_rcv_t.
+ * This object represents the NodeInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.9 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_node_info_rcv.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_router.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_set_links(
+  IN const osm_ni_rcv_t* const p_rcv,
+  osm_node_t* p_node,
+  const uint8_t port_num,
+  const osm_ni_context_t* const p_ni_context )
+{
+  cl_qmap_t *p_guid_tbl;
+  osm_node_t *p_neighbor_node;
+  osm_node_t *p_old_neighbor_node;
+  uint8_t old_neighbor_port_num;
+  osm_physp_t *p_physp, *p_old_physp;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_set_links );
+
+  /*
+    A special case exists in which the node we're trying to
+    link is our own node.  In this case, the guid value in
+    the ni_context will be zero.
+  */
+  if( p_ni_context->node_guid != 0 )
+  {
+    p_guid_tbl = &p_rcv->p_subn->node_guid_tbl;
+    p_neighbor_node = (osm_node_t*)cl_qmap_get( p_guid_tbl,
+                                                p_ni_context->node_guid );
+    if( p_neighbor_node == (osm_node_t*)cl_qmap_end( p_guid_tbl ) )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_ni_rcv_set_links: ERR 0D10: "
+               "Unexpected removal of neighbor node "
+               "0x%" PRIx64 "\n",
+               cl_ntoh64( p_ni_context->node_guid ) );
+    }
+    else
+    {
+      /*
+        We have seen this neighbor node before, but we might
+        not have seen this port on the neighbor node before.
+        We should not set links to an uninitialized port on the
+        neighbor, so check validity up front.  If it's not
+        valid, do nothing, since we'll see this link again
+        when we probe the neighbor.
+      */
+      if( osm_node_link_has_valid_ports( p_node, port_num,
+                                         p_neighbor_node, p_ni_context->port_num ) )
+      {
+        if( osm_node_link_exists( p_node, port_num,
+                                  p_neighbor_node, p_ni_context->port_num ) )
+        {
+          osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+                   "__osm_ni_rcv_set_links: "
+                   "Link already exists\n" );
+        }
+        else
+        {
+          if( osm_node_has_any_link( p_node, port_num ) && 
+              p_rcv->p_subn->force_immediate_heavy_sweep == FALSE )
+          {
+            /*
+              Uh oh...
+              This means that we found 2 nodes with the same guid,
+              or a 12x link with lane reversal that is not configured correctly.
+              If the force_immediate_heavy_sweep == TRUE, then this might be a case
+              of port being moved (causing trap 128), and thus rediscovered. 
+              In this case, just continue. There will be another heavy sweep 
+              immediately after, when the subnet is stable again.
+            */
+            char line[BUF_SIZE];
+            char dr_new_path[BUF_SIZE];
+            char dr_old_path[BUF_SIZE];
+            uint32_t i;
+            osm_dr_path_t *p_path = NULL, *p_old_path = NULL;
+
+            p_physp = osm_node_get_physp_ptr( p_node, port_num );
+            sprintf( dr_new_path, "no_path_available" );
+            if (p_physp)
+            {
+              p_path = osm_physp_get_dr_path_ptr( p_physp );
+              if ( p_path )
+              {
+                sprintf( dr_new_path, "new path:" );
+                for (i = 0; i <= p_path->hop_count; i++ )
+                {
+                  sprintf( line, "[%X]", p_path->path[i] );
+                  strcat( dr_new_path, line );
+                }
+              }
+            }
+
+            p_old_neighbor_node = osm_node_get_remote_node(
+              p_node, port_num, &old_neighbor_port_num );
+            p_old_physp = osm_node_get_physp_ptr(
+              p_old_neighbor_node,
+              old_neighbor_port_num);
+            sprintf( dr_old_path, "no_path_available" );
+            if (p_old_physp)
+            {
+              p_old_path = osm_physp_get_dr_path_ptr( p_old_physp );
+              if ( p_old_path )
+              {
+                sprintf( dr_old_path, "old_path:" );
+                for (i = 0; i <= p_old_path->hop_count; i++ )
+                {
+                  sprintf( line, "[%X]", p_old_path->path[i] );
+                  strcat( dr_old_path, line );
+                }
+              }
+            }
+
+            osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                     "__osm_ni_rcv_set_links: ERR 0D01: "
+                     "Found duplicated guids or 12x link "
+                     "with lane reversal badly configured.\n"
+                     "Overriding existing link to:"
+                     "node 0x%" PRIx64 ", port number 0x%X connected to:\n"
+                     "\t\t\t\told node 0x%" PRIx64 ", "
+                     "port number 0x%X %s\n"
+                     "\t\t\t\tnew node 0x%" PRIx64 ", "
+                     "port number 0x%X %s\n",
+                     cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+                     port_num,
+                     cl_ntoh64( osm_node_get_node_guid(
+                                  p_old_neighbor_node ) ),
+                     old_neighbor_port_num ,
+                     dr_old_path,
+                     cl_ntoh64( p_ni_context->node_guid ),
+                     p_ni_context->port_num,
+                     dr_new_path
+                     );
+
+            osm_log( p_rcv->p_log, OSM_LOG_SYS,
+                     "FATAL: duplicated guids or 12x lane reversal\n");
+
+            if ( p_rcv->p_subn->opt.exit_on_fatal == TRUE )
+           {
+               osm_log( p_rcv->p_log, OSM_LOG_SYS, "Exiting\n");
+               exit( 1 );
+           }
+          }
+
+          /* 
+             When there are only two nodes with exact same guids (connected back
+             to back) - the previous check for duplicated guid will not catch
+             them. But the link will be from the port to itself...
+             Enhanced Port 0 is an exception to this
+          */
+          if ((osm_node_get_node_guid( p_node ) == p_ni_context->node_guid) &&
+              (port_num == p_ni_context->port_num) &&
+              (port_num != 0))
+          {
+            osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                     "__osm_ni_rcv_set_links: ERR 0D18: "
+                     "Duplicate GUID found by link from a port to itself:"
+                     "node 0x%" PRIx64 ", port number 0x%X\n",
+                     cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+                     port_num );
+            p_physp = osm_node_get_physp_ptr( p_node, port_num );
+            if (p_physp)
+              osm_dump_dr_path(p_rcv->p_log,
+                               osm_physp_get_dr_path_ptr(p_physp),
+                               OSM_LOG_ERROR);
+
+            osm_log( p_rcv->p_log, OSM_LOG_SYS,
+                     "Errors on subnet. Duplicate GUID found "
+                     "by link from a port to itself. "
+                     "See osm log for more details\n");
+
+            if ( p_rcv->p_subn->opt.exit_on_fatal == TRUE )
+              exit( 1 );
+          }
+          else
+          {
+            
+            if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+                       "__osm_ni_rcv_set_links: "
+                       "Creating new link between: "
+                       "\n\t\t\t\tnode 0x%" PRIx64 ", "
+                       "port number 0x%X and"
+                       "\n\t\t\t\tnode 0x%" PRIx64 ", "
+                       "port number 0x%X\n",
+                       cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+                       port_num,
+                       cl_ntoh64( p_ni_context->node_guid ),
+                       p_ni_context->port_num );
+            }
+            
+            CL_ASSERT( osm_node_get_node_guid( p_neighbor_node ) ==
+                       p_ni_context->node_guid );
+            
+            osm_node_link( p_node, port_num, p_neighbor_node,
+                           p_ni_context->port_num );
+          }
+        }
+      }
+    }
+  }
+  else
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_ni_rcv_set_links: "
+             "Nothing to link for our own node 0x%" PRIx64 "\n",
+             cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_process_new_node(
+  IN const osm_ni_rcv_t* const p_rcv,
+  IN osm_node_t* const p_node,
+  IN const osm_madw_t* const p_madw )
+{
+  ib_api_status_t status = IB_SUCCESS;
+  osm_madw_context_t context;
+  osm_physp_t *p_physp;
+  ib_node_info_t *p_ni;
+  ib_smp_t *p_smp;
+  uint8_t port_num;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_new_node );
+
+  CL_ASSERT( p_node );
+  CL_ASSERT( p_madw );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+  p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp );
+  port_num = ib_node_info_get_local_port_num( p_ni );
+
+  /*
+    Request PortInfo & NodeDescription attributes for the port
+    that responded to the NodeInfo attribute.
+    Because this is a channel adapter or router, we are
+    not allowed to request PortInfo for the other ports.
+    Set the context union properly, so the recipient
+    knows which node & port are relevant.
+  */
+  p_physp = osm_node_get_physp_ptr( p_node, port_num );
+
+  CL_ASSERT( p_physp );
+  CL_ASSERT( osm_physp_is_valid( p_physp ) );
+  CL_ASSERT( osm_madw_get_bind_handle( p_madw ) ==
+             osm_dr_path_get_bind_handle(
+               osm_physp_get_dr_path_ptr( p_physp ) ) );
+
+  context.pi_context.node_guid = p_ni->node_guid;
+  context.pi_context.port_guid = p_ni->port_guid;
+  context.pi_context.set_method = FALSE;
+  context.pi_context.update_master_sm_base_lid = FALSE;
+  context.pi_context.ignore_errors = FALSE;
+  context.pi_context.light_sweep = FALSE;
+  context.pi_context.active_transition = FALSE;
+
+  status = osm_req_get( p_rcv->p_gen_req,
+                        osm_physp_get_dr_path_ptr( p_physp ),
+                        IB_MAD_ATTR_PORT_INFO,
+                        cl_hton32( port_num ),
+                        CL_DISP_MSGID_NONE,
+                        &context );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_ni_rcv_process_new_node: ERR 0D02: "
+             "Failure initiating PortInfo request (%s)\n",
+             ib_get_err_str(status));
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_get_node_desc(
+  IN const osm_ni_rcv_t* const p_rcv,
+  IN osm_node_t* const p_node,
+  IN const osm_madw_t* const p_madw )
+{
+  ib_api_status_t status = IB_SUCCESS;
+  osm_madw_context_t context;
+  osm_physp_t *p_physp;
+  ib_node_info_t *p_ni;
+  ib_smp_t *p_smp;
+  uint8_t port_num;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_get_node_desc );
+
+  CL_ASSERT( p_node );
+  CL_ASSERT( p_madw );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+  p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp );
+  port_num = ib_node_info_get_local_port_num( p_ni );
+
+  /*
+    Request PortInfo & NodeDescription attributes for the port
+    that responded to the NodeInfo attribute.
+    Because this is a channel adapter or router, we are
+    not allowed to request PortInfo for the other ports.
+    Set the context union properly, so the recipient
+    knows which node & port are relevant.
+  */
+  p_physp = osm_node_get_physp_ptr( p_node, port_num );
+
+  CL_ASSERT( p_physp );
+  CL_ASSERT( osm_physp_is_valid( p_physp ) );
+  CL_ASSERT( osm_madw_get_bind_handle( p_madw ) ==
+             osm_dr_path_get_bind_handle(
+               osm_physp_get_dr_path_ptr( p_physp ) ) );
+
+  context.nd_context.node_guid = osm_node_get_node_guid( p_node );
+
+  status = osm_req_get( p_rcv->p_gen_req,
+                        osm_physp_get_dr_path_ptr( p_physp ),
+                        IB_MAD_ATTR_NODE_DESC,
+                        0,
+                        CL_DISP_MSGID_NONE,
+                        &context );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_ni_rcv_get_node_desc: ERR 0D03: "
+             "Failure initiating NodeDescription request (%s)\n",
+             ib_get_err_str(status));
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_process_new_ca_or_router(
+  IN const osm_ni_rcv_t* const p_rcv,
+  IN osm_node_t* const p_node,
+  IN const osm_madw_t* const p_madw )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_new_ca_or_router );
+
+  __osm_ni_rcv_process_new_node( p_rcv, p_node, p_madw );
+
+  /*
+    A node guid of 0 is the corner case that indicates
+    we discovered our own node.  Initialize the subnet
+    object with the SM's own port guid.
+  */
+  if( osm_madw_get_ni_context_ptr( p_madw )->node_guid == 0 )
+  {
+    p_rcv->p_subn->sm_port_guid = p_node->node_info.port_guid;
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_process_existing_ca_or_router(
+  IN const osm_ni_rcv_t* const p_rcv,
+  IN osm_node_t* const p_node,
+  IN const osm_madw_t* const p_madw )
+{
+  ib_node_info_t *p_ni;
+  ib_smp_t *p_smp;
+  osm_port_t *p_port;
+  osm_port_t *p_port_check;
+  cl_qmap_t *p_guid_tbl;
+  osm_madw_context_t context;
+  uint8_t port_num;
+  osm_physp_t *p_physp;
+  ib_api_status_t status;
+  osm_dr_path_t *p_dr_path;
+  osm_bind_handle_t h_bind;
+  cl_status_t cl_status;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_existing_ca_or_router );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+  p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp );
+  port_num = ib_node_info_get_local_port_num( p_ni );
+  p_guid_tbl = &p_rcv->p_subn->port_guid_tbl;
+  h_bind = osm_madw_get_bind_handle( p_madw );
+
+  /*
+    Determine if we have encountered this node through a
+    previously undiscovered port.  If so, build the new
+    port object.
+  */
+  p_port = (osm_port_t*)cl_qmap_get( p_guid_tbl, p_ni->port_guid );
+
+  if( p_port == (osm_port_t*)cl_qmap_end( p_guid_tbl ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "__osm_ni_rcv_process_existing_ca_or_router: "
+             "Creating new port object with GUID 0x%" PRIx64 "\n",
+             cl_ntoh64( p_ni->port_guid ) );
+
+    osm_node_init_physp( p_node, p_madw );
+
+    p_port = osm_port_new( p_ni, p_node );
+    if( p_port == NULL )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_ni_rcv_process_existing_ca_or_router: ERR 0D04: "
+               "Unable to create new port object\n" );
+      goto Exit;
+    }
+
+    /*
+      Add the new port object to the database.
+    */
+    p_port_check = (osm_port_t*)cl_qmap_insert( p_guid_tbl,
+                                                p_ni->port_guid, &p_port->map_item );
+    if( p_port_check != p_port )
+    {
+      /*
+        We should never be here!
+        Somehow, this port GUID already exists in the table.
+      */
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_ni_rcv_process_existing_ca_or_router: ERR 0D12: "
+               "Port 0x%" PRIx64 " already in the database!\n",
+               cl_ntoh64( p_ni->port_guid ) );
+
+      osm_port_delete( &p_port );
+      goto Exit;
+    }
+
+    /* If we are a master, then this means the port is new on the subnet.
+       Add it to the new_ports_list - need to send trap 64 on these ports.
+       The condition that we are master is true, since if we are in discovering
+       state (meaning we woke up from standby or we are just initializing),
+       then these ports may be new to us, but are not new on the subnet.
+       If we are master, then the subnet as we know it is the updated one,
+       and any new ports we encounter should cause trap 64. C14-72.1.1 */
+    if ( p_rcv->p_subn->sm_state == IB_SMINFO_STATE_MASTER )
+    {
+      cl_status = cl_list_insert_tail( &p_rcv->p_subn->new_ports_list, p_port );
+      if( cl_status != CL_SUCCESS )
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                 "__osm_ni_rcv_process_existing_ca_or_router: ERR 0D08: "
+                 "Error %s adding to list\n",
+                 CL_STATUS_MSG( cl_status ) );
+        osm_port_delete( &p_port );
+        goto Exit;
+      }
+      else
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+                 "__osm_ni_rcv_process_existing_ca_or_router: "
+                 "Adding port GUID:0x%016" PRIx64 " to new_ports_list\n",
+                 cl_ntoh64(osm_node_get_node_guid( p_port->p_node )) );
+      }
+    }
+
+    p_physp = osm_node_get_physp_ptr( p_node, port_num );
+  }
+  else
+  {
+    p_physp = osm_node_get_physp_ptr( p_node, port_num );
+
+    CL_ASSERT( p_physp );
+
+    if ( !osm_physp_is_valid( p_physp ) )
+    {
+        osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                 "__osm_ni_rcv_process_existing_ca_or_router: ERR 0D19: "
+                 "Invalid physical port. Aborting discovery\n");
+        goto Exit;
+    }
+
+    /*
+      Update the DR Path to the port,
+      in case the old one is no longer available.
+    */
+    p_dr_path = osm_physp_get_dr_path_ptr( p_physp );
+
+    osm_dr_path_init( p_dr_path, h_bind, p_smp->hop_count,
+                      p_smp->initial_path );
+  }
+
+  context.pi_context.node_guid = p_ni->node_guid;
+  context.pi_context.port_guid = p_ni->port_guid;
+  context.pi_context.set_method = FALSE;
+  context.pi_context.update_master_sm_base_lid = FALSE;
+  context.pi_context.ignore_errors = FALSE;
+  context.pi_context.light_sweep = FALSE;
+
+  status = osm_req_get( p_rcv->p_gen_req,
+                        osm_physp_get_dr_path_ptr( p_physp ),
+                        IB_MAD_ATTR_PORT_INFO,
+                        cl_hton32( port_num ),
+                        CL_DISP_MSGID_NONE,
+                        &context );
+
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_ni_rcv_process_existing_ca_or_router: ERR 0D13: "
+             "Failure initiating PortInfo request (%s)\n",
+             ib_get_err_str(status));
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ni_rcv_process_switch(
+  IN const osm_ni_rcv_t* const p_rcv,
+  IN osm_node_t* const p_node,
+  IN const osm_madw_t* const p_madw )
+{
+  ib_api_status_t status = IB_SUCCESS;
+  osm_madw_context_t context;
+  osm_dr_path_t dr_path;
+  ib_smp_t *p_smp;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_switch );
+
+  CL_ASSERT( p_node );
+  CL_ASSERT( p_madw );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+
+  osm_dr_path_init( &dr_path,
+                    osm_madw_get_bind_handle( p_madw ),
+                    p_smp->hop_count,
+                    p_smp->initial_path );
+
+  context.si_context.node_guid = osm_node_get_node_guid( p_node );
+  context.si_context.set_method = FALSE;
+  context.si_context.light_sweep = FALSE;
+
+  /* Request a SwitchInfo attribute */
+  status = osm_req_get( p_rcv->p_gen_req,
+                        &dr_path,
+                        IB_MAD_ATTR_SWITCH_INFO,
+                        0,
+                        CL_DISP_MSGID_NONE,
+                        &context );
+  if( status != IB_SUCCESS )
+  {
+    /* continue despite error */
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_ni_rcv_process_switch: ERR 0D06: "
+             "Failure initiating SwitchInfo request (%s)\n",
+             ib_get_err_str( status ) );
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_process_existing_switch(
+  IN const osm_ni_rcv_t* const p_rcv,
+  IN osm_node_t* const p_node,
+  IN const osm_madw_t* const p_madw )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_existing_switch );
+
+  /*
+    If this switch has already been probed during this sweep,
+    then don't bother reprobing it.
+    There is one exception - if the node has been visited, but
+    for some reason we don't have the switch object (this can happen
+    if the SwitchInfo mad didn't reach the SM) then we want
+    to retry to probe the switch.
+  */
+  if( osm_node_discovery_count_get( p_node ) == 1 )
+    __osm_ni_rcv_process_switch( p_rcv, p_node, p_madw );
+  else
+  {
+    /* Make sure we have SwitchInfo on this node */
+    if( !p_node->sw || osm_switch_discovery_count_get( p_node->sw ) == 0 )
+    {
+      /* we don't have the SwitchInfo - retry to get it */
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+               "__osm_ni_rcv_process_existing_switch: "
+               "Retry to get SwitchInfo on node GUID:0x%"
+               PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(p_node)) );
+      __osm_ni_rcv_process_switch( p_rcv, p_node, p_madw );
+    }
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_process_new_switch(
+  IN const osm_ni_rcv_t* const p_rcv,
+  IN osm_node_t* const p_node,
+  IN const osm_madw_t* const p_madw )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_new_switch );
+
+  __osm_ni_rcv_process_switch( p_rcv, p_node, p_madw );
+
+  /*
+    A node guid of 0 is the corner case that indicates
+    we discovered our own node.  Initialize the subnet
+    object with the SM's own port guid.
+  */
+  if( osm_madw_get_ni_context_ptr( p_madw )->node_guid == 0 )
+  {
+    p_rcv->p_subn->sm_port_guid = p_node->node_info.port_guid;
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must NOT be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_process_new(
+  IN const osm_ni_rcv_t* const p_rcv,
+  IN const osm_madw_t* const p_madw )
+{
+  osm_node_t *p_node;
+  osm_node_t *p_node_check;
+  osm_port_t *p_port;
+  osm_port_t *p_port_check;
+  osm_router_t *p_rtr = NULL;
+  osm_router_t *p_rtr_check;
+  cl_qmap_t *p_node_guid_tbl;
+  cl_qmap_t *p_port_guid_tbl;
+  cl_qmap_t *p_rtr_guid_tbl;
+  ib_node_info_t *p_ni;
+  ib_smp_t *p_smp;
+  osm_ni_context_t *p_ni_context;
+  uint8_t port_num;
+  cl_status_t status;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_new );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+  p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp );
+  p_ni_context = osm_madw_get_ni_context_ptr( p_madw );
+  port_num = ib_node_info_get_local_port_num( p_ni );
+
+  osm_dump_smp_dr_path( p_rcv->p_log, p_smp, OSM_LOG_VERBOSE );
+
+  osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+           "__osm_ni_rcv_process_new: "
+           "Discovered new %s node,"
+           "\n\t\t\t\tGUID 0x%" PRIx64 ", TID 0x%" PRIx64 "\n",
+           ib_get_node_type_str( p_ni->node_type ),
+           cl_ntoh64( p_ni->node_guid ),
+           cl_ntoh64( p_smp->trans_id ) );
+
+  p_node = osm_node_new( p_madw );
+  if( p_node == NULL )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_ni_rcv_process_new: ERR 0D07: "
+             "Unable to create new node object\n" );
+    goto Exit;
+  }
+
+  /*
+    Create a new port object to represent this node's physical
+    ports in the port table.
+  */
+  p_port = osm_port_new( p_ni, p_node );
+  if( p_port == NULL )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_ni_rcv_process_new: ERR 0D14: "
+             "Unable to create new port object\n" );
+    osm_node_delete( &p_node );
+    goto Exit;
+  }
+
+  /* If there were RouterInfo or other router attribute,
+     this would be elsewhere */
+  if ( p_ni->node_type == IB_NODE_TYPE_ROUTER )
+  {
+    p_rtr = osm_router_new( p_port );
+    if ( p_rtr == NULL )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_ni_rcv_process_new: ERR 0D1A: "
+               "Unable to create new router object\n" );
+    }
+  }
+
+  /*
+    Add the new port object to the database.
+  */
+  p_port_guid_tbl = &p_rcv->p_subn->port_guid_tbl;
+  p_port_check = (osm_port_t*)cl_qmap_insert( p_port_guid_tbl,
+                                              p_ni->port_guid,
+                                              &p_port->map_item );
+  if( p_port_check != p_port )
+  {
+    /*
+      We should never be here!
+      Somehow, this port GUID already exists in the table.
+    */
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_ni_rcv_process_new: ERR 0D15: "
+             "Duplicate Port GUID 0x%" PRIx64 "! Found by the two directed routes:\n",
+             cl_ntoh64( p_ni->port_guid ) );
+    osm_dump_dr_path(p_rcv->p_log,
+                     osm_physp_get_dr_path_ptr(
+                       osm_port_get_default_phys_ptr ( p_port) ),
+                     OSM_LOG_ERROR);
+    osm_dump_dr_path(p_rcv->p_log,
+                     osm_physp_get_dr_path_ptr(
+                       osm_port_get_default_phys_ptr ( p_port_check) ),
+                     OSM_LOG_ERROR);
+    if ( p_rtr )
+      osm_router_delete( &p_rtr );
+    osm_port_delete( &p_port );
+    osm_node_delete( &p_node );
+    goto Exit;
+  }
+
+  /* If we are a master, then this means the port is new on the subnet.
+     Add it to the new_ports_list - need to send trap 64 on these ports.
+     The condition that we are master is true, since if we are in discovering
+     state (meaning we woke up from standby or we are just initializing),
+     then these ports may be new to us, but are not new on the subnet.
+     If we are master, then the subnet as we know it is the updated one,
+     and any new ports we encounter should cause trap 64. C14-72.1.1 */
+  if ( p_rcv->p_subn->sm_state == IB_SMINFO_STATE_MASTER )
+  {
+    status = cl_list_insert_tail( &p_rcv->p_subn->new_ports_list, p_port );
+    if( status != CL_SUCCESS )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_ni_rcv_process_new: ERR 0D05: "
+               "Error %s adding to new_ports_list\n",
+               CL_STATUS_MSG( status ) );
+      if ( p_rtr )
+        osm_router_delete( &p_rtr );
+      osm_port_delete( &p_port );
+      osm_node_delete( &p_node );
+      goto Exit;
+    }
+    else
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+               "__osm_ni_rcv_process_new: "
+               "Adding port GUID:0x%016" PRIx64 " to new_ports_list\n",
+               cl_ntoh64( osm_node_get_node_guid( p_port->p_node ) ) );
+    }
+  }
+
+  if ( p_rtr && p_ni->node_type == IB_NODE_TYPE_ROUTER )
+  {
+    p_rtr_guid_tbl = &p_rcv->p_subn->rtr_guid_tbl;
+    p_rtr_check = (osm_router_t*)cl_qmap_insert( p_rtr_guid_tbl,
+                                                 p_ni->port_guid,
+                                                 &p_rtr->map_item );
+    if( p_rtr_check != p_rtr )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_ni_rcv_process_new: ERR 0D1B: "
+               "Unable to add port GUID:0x%016" PRIx64 " to router table\n",
+               cl_ntoh64( p_ni->port_guid ) );
+    }
+  }
+
+  p_node_guid_tbl = &p_rcv->p_subn->node_guid_tbl;
+  p_node_check = (osm_node_t*)cl_qmap_insert( p_node_guid_tbl,
+                                              p_ni->node_guid,
+                                              &p_node->map_item );
+  if( p_node_check != p_node )
+  {
+    /*
+      This node must have been inserted by another thread.
+      This is unexpected, but is not an error.
+      We can simply clean-up, since the other thread will
+      see this processing through to completion.
+    */
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "__osm_ni_rcv_process_new: "
+             "Discovery race detected at node 0x%" PRIx64 "\n",
+             cl_ntoh64( p_ni->node_guid ) );
+    osm_node_delete( &p_node );
+    p_node = p_node_check;
+    __osm_ni_rcv_set_links( p_rcv, p_node, port_num, p_ni_context );
+    goto Exit;
+  }
+  else
+    __osm_ni_rcv_set_links( p_rcv, p_node, port_num, p_ni_context );
+
+  osm_node_discovery_count_inc( p_node );
+  __osm_ni_rcv_get_node_desc( p_rcv, p_node, p_madw );
+
+  switch( p_ni->node_type )
+  {
+  case IB_NODE_TYPE_CA:
+  case IB_NODE_TYPE_ROUTER:
+    __osm_ni_rcv_process_new_ca_or_router( p_rcv, p_node, p_madw );
+    break;
+  case IB_NODE_TYPE_SWITCH:
+    __osm_ni_rcv_process_new_switch( p_rcv, p_node, p_madw );
+    break;
+  default:
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_ni_rcv_process_new: ERR 0D16: "
+             "Unknown node type %u with GUID 0x%" PRIx64 "\n",
+             p_ni->node_type, cl_ntoh64( p_ni->node_guid ) );
+    break;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_process_existing(
+  IN const osm_ni_rcv_t* const p_rcv,
+  IN osm_node_t* const p_node,
+  IN const osm_madw_t* const p_madw )
+{
+  ib_node_info_t *p_ni;
+  ib_smp_t *p_smp;
+  osm_ni_context_t *p_ni_context;
+  uint8_t port_num;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_existing );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+  p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp );
+  p_ni_context = osm_madw_get_ni_context_ptr( p_madw );
+  port_num = ib_node_info_get_local_port_num( p_ni );
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "__osm_ni_rcv_process_existing: "
+             "Rediscovered %s node 0x%" PRIx64
+             "\n\t\t\t\tTID 0x%" PRIx64
+             ", discovered %u times already\n",
+             ib_get_node_type_str(p_ni->node_type),
+             cl_ntoh64( p_ni->node_guid ),
+             cl_ntoh64( p_smp->trans_id ),
+             osm_node_discovery_count_get( p_node ) );
+  }
+
+  /*
+    If we haven't already encountered this existing node
+    on this particular sweep, then process further.
+  */
+  osm_node_discovery_count_inc( p_node );
+
+  switch( p_ni->node_type )
+  {
+  case IB_NODE_TYPE_CA:
+  case IB_NODE_TYPE_ROUTER:
+    __osm_ni_rcv_process_existing_ca_or_router( p_rcv, p_node, p_madw );
+    break;
+
+  case IB_NODE_TYPE_SWITCH:
+    __osm_ni_rcv_process_existing_switch( p_rcv, p_node, p_madw );
+    break;
+
+  default:
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_ni_rcv_process_existing: ERR 0D09: "
+             "Unknown node type %u with GUID 0x%" PRIx64 "\n",
+             p_ni->node_type, cl_ntoh64( p_ni->node_guid ) );
+    break;
+  }
+
+  __osm_ni_rcv_set_links( p_rcv, p_node, port_num, p_ni_context );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ni_rcv_construct(
+  IN osm_ni_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ni_rcv_destroy(
+  IN osm_ni_rcv_t* const p_rcv )
+{
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_ni_rcv_destroy );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_ni_rcv_init(
+  IN osm_ni_rcv_t* const p_rcv,
+  IN osm_req_t* const p_req,
+  IN osm_subn_t* const p_subn,
+  IN osm_log_t* const p_log,
+  IN osm_state_mgr_t* const p_state_mgr,
+  IN cl_plock_t* const p_lock )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_ni_rcv_init );
+
+  osm_ni_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_gen_req = p_req;
+  p_rcv->p_state_mgr = p_state_mgr;
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ni_rcv_process(
+  IN const osm_ni_rcv_t* const p_rcv,
+  IN osm_madw_t* const p_madw )
+{
+  cl_qmap_t *p_guid_tbl;
+  ib_node_info_t *p_ni;
+  ib_smp_t *p_smp;
+  osm_node_t *p_node;
+  boolean_t  process_new_flag = FALSE;
+
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_ni_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+  p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp );
+
+  CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_NODE_INFO );
+
+  if (p_ni->node_guid == 0)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_ni_rcv_process: ERR 0D16: "
+             "Got Zero Node GUID! Found on the directed route:\n");
+    osm_dump_smp_dr_path(p_rcv->p_log, p_smp, OSM_LOG_ERROR);
+    goto Exit;
+  }
+
+  if (p_ni->port_guid == 0)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_ni_rcv_process: ERR 0D17: "
+             "Got Zero Port GUID! Found on the directed route:\n");
+    osm_dump_smp_dr_path(p_rcv->p_log, p_smp, OSM_LOG_ERROR);
+    goto Exit;
+  }
+
+  p_guid_tbl = &p_rcv->p_subn->node_guid_tbl;
+
+  /*
+    Determine if this node has already been discovered,
+    and process accordingly.
+    During processing of this node, hold the shared lock.
+  */
+
+  CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
+  p_node = (osm_node_t*)cl_qmap_get( p_guid_tbl, p_ni->node_guid );
+
+  osm_dump_node_info( p_rcv->p_log, p_ni, OSM_LOG_DEBUG );
+
+  if( p_node == (osm_node_t*)cl_qmap_end(p_guid_tbl) )
+  {
+    __osm_ni_rcv_process_new( p_rcv, p_madw );
+    process_new_flag = TRUE;
+  }
+  else
+    __osm_ni_rcv_process_existing( p_rcv, p_node, p_madw );
+
+  CL_PLOCK_RELEASE( p_rcv->p_lock );
+  
+  /* 
+   * If we processed a new node - need to signal to the state_mgr that
+   * change detected. BUT - we cannot call the osm_state_mgr_process
+   * from within the lock of p_rcv->p_lock (can cause a deadlock).
+   */
+  if ( process_new_flag )
+    osm_state_mgr_process( p_rcv->p_state_mgr, OSM_SIGNAL_CHANGE_DETECTED );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_info_rcv_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_node_info_rcv_ctrl.c
new file mode 100644 (file)
index 0000000..bf47813
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_node_info_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_ni_rcv_ctrl_t.
+ * This object represents the NodeInfo request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_node_info_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_ni_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_ni_rcv_process( ((osm_ni_rcv_ctrl_t*)context)->p_rcv,
+                      (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ni_rcv_ctrl_construct(
+  IN osm_ni_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ni_rcv_ctrl_destroy(
+  IN osm_ni_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_ni_rcv_ctrl_init(
+  IN osm_ni_rcv_ctrl_t* const p_ctrl,
+  IN osm_ni_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_ni_rcv_ctrl_init );
+
+  osm_ni_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_NODE_INFO,
+    __osm_ni_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_ni_rcv_ctrl_init: ERR 0E01: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_opensm.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_opensm.c
new file mode 100644 (file)
index 0000000..4f0019f
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_opensm.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_opensm_t.
+ * This object represents the opensm super object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_dispatcher.h>
+#include <complib/cl_passivelock.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_version.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_sm.h>
+#include <opensm/osm_vl15intf.h>
+
+struct routing_engine_module {
+       const char *name;
+       int (*setup)(osm_opensm_t *p_osm);
+};
+
+extern int osm_ucast_updn_setup(osm_opensm_t *p_osm);
+extern int osm_ucast_file_setup(osm_opensm_t *p_osm);
+extern int osm_ucast_ftree_setup(osm_opensm_t *p_osm);
+
+static int osm_ucast_null_setup(osm_opensm_t *p_osm);
+
+const static struct routing_engine_module routing_modules[] = {
+       { "null", osm_ucast_null_setup },
+       { "updn", osm_ucast_updn_setup },
+       { "file", osm_ucast_file_setup },
+       { "ftree", osm_ucast_ftree_setup },
+       { NULL, NULL }
+};
+
+static int setup_routing_engine(osm_opensm_t *p_osm, const char *name)
+{
+       const struct routing_engine_module *r;
+
+       for (r = routing_modules; r->name && *r->name; r++) {
+               if(!strcmp(r->name, name)) {
+                       p_osm->routing_engine.name = r->name;
+                       if (r->setup(p_osm)) {
+                               osm_log(&p_osm->log, OSM_LOG_VERBOSE,
+                                       "setup_routing_engine: setup of routing"
+                                       " engine \'%s\' failed\n", name);
+                               return -2;
+                       }
+                       osm_log (&p_osm->log, OSM_LOG_DEBUG,
+                                "setup_routing_engine: "
+                                "\'%s\' routing engine set up\n",
+                                p_osm->routing_engine.name);
+                       return 0;
+               }
+       }
+       return -1;
+}
+
+static int osm_ucast_null_setup(osm_opensm_t *p_osm)
+{
+       osm_log(&p_osm->log, OSM_LOG_VERBOSE,
+               "osm_ucast_null_setup: nothing yet - "
+               "will use default routing engine\n");
+       return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_opensm_construct(
+   IN osm_opensm_t * const p_osm )
+{
+   memset( p_osm, 0, sizeof( *p_osm ) );
+   osm_subn_construct( &p_osm->subn );
+   osm_sm_construct( &p_osm->sm );
+   osm_sa_construct( &p_osm->sa );
+   osm_db_construct( &p_osm->db );
+   osm_mad_pool_construct( &p_osm->mad_pool );
+   osm_vl15_construct( &p_osm->vl15 );
+   osm_log_construct( &p_osm->log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_opensm_destroy(
+   IN osm_opensm_t * const p_osm )
+{
+
+   /* in case of shutdown through exit proc - no ^C */
+   osm_exit_flag = TRUE;
+
+   /* 
+    * First of all - Clear the is_sm bit.
+    */
+   if( p_osm->sm.mad_ctrl.h_bind )
+      osm_vendor_set_sm( p_osm->sm.mad_ctrl.h_bind, FALSE );
+
+   /* shut down the SA
+    * - unbind from QP1 messages
+    */
+   osm_sa_shutdown( &p_osm->sa );
+
+   /* shut down the SM 
+    * - make sure the SM sweeper thread exited
+    * - unbind from QP0 messages
+    */
+   osm_sm_shutdown( &p_osm->sm );
+
+   /* cleanup all messages on VL15 fifo that were not sent yet */
+   osm_vl15_shutdown( &p_osm->vl15, &p_osm->mad_pool );
+
+   /* shut down the dispatcher - so no new messages cross */
+   cl_disp_shutdown( &p_osm->disp );
+
+   /* dump SA DB */
+   osm_sa_db_file_dump(p_osm);
+
+   /* do the destruction in reverse order as init */
+   if (p_osm->routing_engine.delete)
+     p_osm->routing_engine.delete(p_osm->routing_engine.context);
+   osm_sa_destroy( &p_osm->sa );
+   osm_sm_destroy( &p_osm->sm );
+   osm_db_destroy( &p_osm->db );
+   osm_vl15_destroy( &p_osm->vl15, &p_osm->mad_pool );
+   osm_mad_pool_destroy( &p_osm->mad_pool );
+   osm_vendor_delete( &p_osm->p_vendor );
+   osm_subn_destroy( &p_osm->subn );
+   cl_disp_destroy( &p_osm->disp );
+
+   cl_plock_destroy( &p_osm->lock );
+
+   osm_log_destroy( &p_osm->log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_opensm_init(
+   IN osm_opensm_t * const p_osm,
+   IN const osm_subn_opt_t * const p_opt )
+{
+   ib_api_status_t status;
+
+   /* Can't use log macros here, since we're initializing the log. */
+   osm_opensm_construct( p_osm );
+
+   status = osm_log_init_v2( &p_osm->log, p_opt->force_log_flush,
+                             p_opt->log_flags, p_opt->log_file,
+                             p_opt->log_max_size, p_opt->accum_log_file );
+   if( status != IB_SUCCESS )
+      return ( status );
+
+   /* If there is a log level defined - add the OSM_VERSION to it. */
+   osm_log( &p_osm->log,
+            osm_log_get_level( &p_osm->log ) & ( OSM_LOG_SYS ^ 0xFF ), "%s\n",
+            OSM_VERSION );
+   /* Write the OSM_VERSION to the SYS_LOG */
+   osm_log( &p_osm->log, OSM_LOG_SYS, "%s\n", OSM_VERSION );   /* Format Waived */
+
+   osm_log( &p_osm->log, OSM_LOG_FUNCS, "osm_opensm_init: [\n" ); /* Format Waived */
+
+   status = cl_plock_init( &p_osm->lock );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   if( p_opt->single_thread )
+   {
+      osm_log( &p_osm->log, OSM_LOG_INFO,
+               "osm_opensm_init: Forcing single threaded dispatcher.\n" );
+      status = cl_disp_init( &p_osm->disp, 1, "opensm" );
+   }
+   else
+   {
+      /*
+       * Normal behavior is to initialize the dispatcher with
+       * one thread per CPU, as specified by a thread count of '0'.
+       */
+      status = cl_disp_init( &p_osm->disp, 0, "opensm" );
+   }
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_subn_init( &p_osm->subn, p_osm, p_opt );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   p_osm->p_vendor =
+      osm_vendor_new( &p_osm->log, p_opt->transaction_timeout );
+   if( p_osm->p_vendor == NULL )
+   {
+      status = IB_INSUFFICIENT_RESOURCES;
+      goto Exit;
+   }
+
+   status = osm_mad_pool_init( &p_osm->mad_pool, &p_osm->log );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_vl15_init( &p_osm->vl15,
+                           p_osm->p_vendor,
+                           &p_osm->log, &p_osm->stats, p_opt->max_wire_smps,
+                           &p_osm->subn, &p_osm->disp, &p_osm->lock );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   /* the DB is in use by the SM and SA so init before */
+   status = osm_db_init( &p_osm->db, &p_osm->log );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_sm_init( &p_osm->sm,
+                         &p_osm->subn,
+                         &p_osm->db,
+                         p_osm->p_vendor,
+                         &p_osm->mad_pool,
+                         &p_osm->vl15,
+                         &p_osm->log,
+                         &p_osm->stats, &p_osm->disp, &p_osm->lock );
+
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_sa_init( &p_osm->sm,
+                         &p_osm->sa,
+                         &p_osm->subn,
+                         p_osm->p_vendor,
+                         &p_osm->mad_pool,
+                         &p_osm->log,
+                         &p_osm->stats, &p_osm->disp, &p_osm->lock );
+
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   if( p_opt->routing_engine_name &&
+       setup_routing_engine(p_osm, p_opt->routing_engine_name)) {
+      osm_log( &p_osm->log, OSM_LOG_VERBOSE,
+               "osm_opensm_init: cannot find or setup routing engine"
+               " \'%s\'. Default will be used instead\n",
+               p_opt->routing_engine_name);
+      goto Exit;
+   }
+
+ Exit:
+   osm_log( &p_osm->log, OSM_LOG_FUNCS, "osm_opensm_init: ]\n" ); /* Format Waived */
+   return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_opensm_bind(
+   IN osm_opensm_t * const p_osm,
+   IN const ib_net64_t guid )
+{
+   ib_api_status_t status;
+
+   OSM_LOG_ENTER( &p_osm->log, osm_opensm_bind );
+
+   status = osm_sm_bind( &p_osm->sm, guid );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_sa_bind( &p_osm->sa, guid );
+   if( status != IB_SUCCESS )
+      goto Exit;
+ Exit:
+   OSM_LOG_EXIT( &p_osm->log );
+   return ( status );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey.c
new file mode 100644 (file)
index 0000000..f649c80
--- /dev/null
@@ -0,0 +1,547 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_pkey.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of opensm pkey manipulation functions.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.1 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_helper.h>
+
+/**********************************************************************
+ **********************************************************************/
+void osm_pkey_tbl_construct( 
+  IN osm_pkey_tbl_t *p_pkey_tbl)
+{
+  cl_ptr_vector_construct( &p_pkey_tbl->blocks );
+  cl_ptr_vector_construct( &p_pkey_tbl->new_blocks );
+  cl_map_construct( &p_pkey_tbl->keys );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_pkey_tbl_destroy( 
+  IN osm_pkey_tbl_t *p_pkey_tbl)
+{
+  ib_pkey_table_t *p_block;
+  uint16_t num_blocks, i;
+
+  num_blocks = (uint16_t)(cl_ptr_vector_get_size( &p_pkey_tbl->blocks ));
+  for (i = 0; i < num_blocks; i++)
+    if ((p_block = cl_ptr_vector_get( &p_pkey_tbl->blocks, i )))
+      free(p_block);
+  cl_ptr_vector_destroy( &p_pkey_tbl->blocks );
+
+  num_blocks = (uint16_t)(cl_ptr_vector_get_size( &p_pkey_tbl->new_blocks ));
+  for (i = 0; i < num_blocks; i++)
+    if ((p_block = cl_ptr_vector_get( &p_pkey_tbl->new_blocks, i )))
+      free(p_block);
+  cl_ptr_vector_destroy( &p_pkey_tbl->new_blocks );
+
+  cl_map_remove_all( &p_pkey_tbl->keys );
+  cl_map_destroy( &p_pkey_tbl->keys );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pkey_tbl_init(
+  IN osm_pkey_tbl_t *p_pkey_tbl)
+{
+  cl_ptr_vector_init(&p_pkey_tbl->blocks, 0, 1);
+  cl_ptr_vector_init(&p_pkey_tbl->new_blocks, 0, 1);
+  cl_map_init(&p_pkey_tbl->keys, 1);
+  cl_qlist_init(&p_pkey_tbl->pending);
+  p_pkey_tbl->used_blocks = 0;
+  p_pkey_tbl->max_blocks = 0;
+  return(IB_SUCCESS);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_pkey_tbl_init_new_blocks(
+  IN const osm_pkey_tbl_t *p_pkey_tbl)
+{
+  ib_pkey_table_t *p_block;
+  size_t b, num_blocks = cl_ptr_vector_get_size(&p_pkey_tbl->new_blocks);
+
+  for (b = 0; b < num_blocks; b++)
+    if ((p_block = cl_ptr_vector_get(&p_pkey_tbl->new_blocks, b)))
+      memset(p_block, 0, sizeof(*p_block));
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_pkey_tbl_cleanup_pending(
+  IN osm_pkey_tbl_t *p_pkey_tbl)
+{
+  cl_list_item_t    *p_item;
+
+  p_item = cl_qlist_remove_head(&p_pkey_tbl->pending);
+  while (p_item != cl_qlist_end(&p_pkey_tbl->pending))
+  {
+    free((osm_pending_pkey_t *)p_item);
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pkey_tbl_set(
+  IN osm_pkey_tbl_t *p_pkey_tbl,
+  IN uint16_t block, 
+  IN ib_pkey_table_t *p_tbl)
+{
+  uint16_t b, i;
+  ib_pkey_table_t *p_pkey_block;
+  uint16_t        *p_prev_pkey;
+  ib_net16_t       pkey;
+
+  /* make sure the block is allocated */
+  if (cl_ptr_vector_get_size( &p_pkey_tbl->blocks ) > block)
+    p_pkey_block = 
+      (ib_pkey_table_t *)cl_ptr_vector_get( &p_pkey_tbl->blocks, block );
+  else
+    p_pkey_block = NULL;
+    
+  if ( !p_pkey_block )
+  {
+    p_pkey_block = (ib_pkey_table_t *)malloc(sizeof(ib_pkey_table_t));
+    if (p_pkey_block)
+      memset(p_pkey_block, 0, sizeof(ib_pkey_table_t));
+    cl_ptr_vector_set( &p_pkey_tbl->blocks, block, p_pkey_block );
+  }
+
+  /* sets the block values */
+  memcpy( p_pkey_block, p_tbl, sizeof(ib_pkey_table_t) );
+
+  /*
+    NOTE: as the spec does not require uniqueness of PKeys in
+    tables there is no other way but to refresh the entire keys map.
+
+    Moreover, if the same key exists but with full membership it should have
+    precedence on the key with limited membership !
+  */
+  cl_map_remove_all( &p_pkey_tbl->keys );
+
+  for (b = 0; b < cl_ptr_vector_get_size( &p_pkey_tbl->blocks ); b++)
+  {
+
+    p_pkey_block = cl_ptr_vector_get( &p_pkey_tbl->blocks, b );
+    if (! p_pkey_block)
+      continue;
+
+    for (i = 0; i < IB_NUM_PKEY_ELEMENTS_IN_BLOCK; i++)
+    {
+      pkey = p_pkey_block->pkey_entry[i];
+      if (ib_pkey_is_invalid(pkey))
+        continue;
+
+      /* 
+         ignore the PKey Full Member bit in the key but store 
+         the pointer to the table element as the map value
+      */
+      p_prev_pkey = 
+        cl_map_get( &p_pkey_tbl->keys, ib_pkey_get_base(pkey));
+
+      /* we only insert if no previous or it is not full member */
+      if ((p_prev_pkey == NULL) || 
+          (cl_ntoh16(*p_prev_pkey) < cl_ntoh16(pkey)))
+        cl_map_insert( &p_pkey_tbl->keys, 
+                       ib_pkey_get_base(pkey),
+                       &(p_pkey_block->pkey_entry[i])
+                       );
+    }
+  }
+  return(IB_SUCCESS);
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+  Store the given pkey in the "new" blocks array. 
+  Also, make sure the regular block exists.
+*/
+ib_api_status_t
+osm_pkey_tbl_set_new_entry( 
+  IN osm_pkey_tbl_t *p_pkey_tbl,
+  IN uint16_t        block_idx,
+  IN uint8_t         pkey_idx,
+  IN uint16_t        pkey)
+{  
+  ib_pkey_table_t *p_block;
+
+  if (!(p_block = osm_pkey_tbl_new_block_get(p_pkey_tbl, block_idx))) {
+    p_block = (ib_pkey_table_t *)malloc(sizeof(ib_pkey_table_t));
+    if (!p_block)
+      return(IB_ERROR);
+    memset(p_block, 0, sizeof(ib_pkey_table_t));
+    cl_ptr_vector_set(&p_pkey_tbl->new_blocks, block_idx, p_block);
+  }
+
+  p_block->pkey_entry[pkey_idx] = pkey;
+  if (p_pkey_tbl->used_blocks <= block_idx)
+    p_pkey_tbl->used_blocks = block_idx + 1;
+
+  return(IB_SUCCESS);
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_pkey_find_next_free_entry(
+  IN osm_pkey_tbl_t *p_pkey_tbl, 
+  OUT uint16_t      *p_block_idx,
+  OUT uint8_t       *p_pkey_idx)
+{
+  ib_pkey_table_t *p_new_block;
+
+  CL_ASSERT(p_block_idx);
+  CL_ASSERT(p_pkey_idx);
+
+  while (*p_block_idx < p_pkey_tbl->max_blocks)
+  {
+    if (*p_pkey_idx > IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1)
+    {
+       *p_pkey_idx = 0;
+       (*p_block_idx)++;
+       if (*p_block_idx >= p_pkey_tbl->max_blocks) 
+         return FALSE;
+    }
+
+    p_new_block = osm_pkey_tbl_new_block_get(p_pkey_tbl, *p_block_idx);
+
+    if (!p_new_block ||
+       ib_pkey_is_invalid(p_new_block->pkey_entry[*p_pkey_idx]))
+      return TRUE;
+    else
+      (*p_pkey_idx)++;
+  }
+  return FALSE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pkey_tbl_get_block_and_idx(
+  IN osm_pkey_tbl_t *p_pkey_tbl,
+  IN uint16_t    *p_pkey,
+  OUT uint16_t   *p_block_idx,
+  OUT uint8_t    *p_pkey_idx)
+{
+  uint16_t       num_of_blocks;
+  uint16_t       block_index;
+  ib_pkey_table_t *block;
+
+  CL_ASSERT( p_block_idx != NULL );
+  CL_ASSERT( p_pkey_idx != NULL );
+  num_of_blocks = (uint16_t)cl_ptr_vector_get_size( &p_pkey_tbl->blocks );
+  for (block_index = 0; block_index < num_of_blocks; block_index++)
+  {
+    block = osm_pkey_tbl_block_get(p_pkey_tbl, block_index);
+    if ((block->pkey_entry <= p_pkey) &&
+       (p_pkey < block->pkey_entry + IB_NUM_PKEY_ELEMENTS_IN_BLOCK))
+    {
+       *p_block_idx = block_index;
+       *p_pkey_idx = (uint8_t)(p_pkey - block->pkey_entry);
+       return(IB_SUCCESS);
+    }
+  }
+  return(IB_NOT_FOUND);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t 
+__osm_match_pkey (
+  IN const ib_net16_t *pkey1,
+  IN const ib_net16_t *pkey2 )
+{
+
+  /* if both pkeys are not full member - this is not a match */
+  if (!(ib_pkey_is_full_member(*pkey1) || ib_pkey_is_full_member(*pkey2)))
+    return(FALSE);
+
+  /* compare if the bases are the same. if they are - then
+     this is a match */
+  if (ib_pkey_get_base(*pkey1) != ib_pkey_get_base(*pkey2))
+    return(FALSE);
+
+  return(TRUE);
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_physp_share_this_pkey(
+  IN const osm_physp_t*  const p_physp1,
+  IN const osm_physp_t*  const p_physp2,
+  IN const ib_net16_t    pkey )
+{
+  ib_net16_t *pkey1, *pkey2;
+
+  pkey1 = cl_map_get( &(osm_physp_get_pkey_tbl(p_physp1))->keys,
+                 ib_pkey_get_base(pkey));
+  pkey2 = cl_map_get( &(osm_physp_get_pkey_tbl(p_physp2))->keys,
+                 ib_pkey_get_base(pkey));
+  return (pkey1 && pkey2 && __osm_match_pkey(pkey1, pkey2));
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_net16_t
+osm_physp_find_common_pkey(
+  IN const osm_physp_t*  const p_physp1,
+  IN const osm_physp_t*  const p_physp2 )
+{
+  ib_net16_t *pkey1, *pkey2;
+  uint64_t pkey1_base, pkey2_base;
+  const osm_pkey_tbl_t *pkey_tbl1, *pkey_tbl2;
+  cl_map_iterator_t map_iter1, map_iter2;
+
+  pkey_tbl1 = osm_physp_get_pkey_tbl(p_physp1);
+  pkey_tbl2 = osm_physp_get_pkey_tbl(p_physp2);
+
+  map_iter1 = cl_map_head(&pkey_tbl1->keys);
+  map_iter2 = cl_map_head(&pkey_tbl2->keys);
+
+  /* we rely on the fact the map are sorted by pkey */
+  while ( (map_iter1 != cl_map_end( &pkey_tbl1->keys )) && 
+          (map_iter2 != cl_map_end( &pkey_tbl2->keys )))
+  {
+    pkey1 = (ib_net16_t *)cl_map_obj( map_iter1 );
+    pkey2 = (ib_net16_t *)cl_map_obj( map_iter2 );
+
+    if (__osm_match_pkey(pkey1, pkey2))
+      return *pkey1;
+
+    /* advance the lower value if they are not equal */
+    pkey1_base = cl_map_key( map_iter1 );
+    pkey2_base = cl_map_key( map_iter2 );
+    if (pkey2_base == pkey1_base)
+    {
+      map_iter1 = cl_map_next( map_iter1 );
+      map_iter2 = cl_map_next( map_iter2 );
+    } 
+    else if (pkey2_base < pkey1_base)
+      map_iter2 = cl_map_next( map_iter2 );
+    else
+      map_iter1 = cl_map_next( map_iter1 );
+  }
+    
+  return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_physp_share_pkey(
+  IN osm_log_t*          p_log,
+  IN const osm_physp_t*  const p_physp_1,
+  IN const osm_physp_t*  const p_physp_2 )
+{
+  const osm_pkey_tbl_t *pkey_tbl1, *pkey_tbl2;
+  
+  if (p_physp_1 == p_physp_2)
+    return TRUE;
+
+  pkey_tbl1 = osm_physp_get_pkey_tbl(p_physp_1);
+  pkey_tbl2 = osm_physp_get_pkey_tbl(p_physp_2);
+
+  /* 
+     The spec: 10.9.2 does not require each phys port to have PKey Table.
+     So actually if it does not, we need to use the default port instead.
+
+     HACK: meanwhile we will ignore the check
+  */
+  if (cl_is_map_empty(&pkey_tbl1->keys) || cl_is_map_empty(&pkey_tbl2->keys))
+    return TRUE;
+
+  return !ib_pkey_is_invalid(osm_physp_find_common_pkey(p_physp_1, p_physp_2));
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_port_share_pkey(
+  IN osm_log_t*          p_log,
+  IN const osm_port_t*   const p_port_1,
+  IN const osm_port_t*   const p_port_2 ) {
+
+  osm_physp_t *p_physp1, *p_physp2;
+  boolean_t ret;
+
+  OSM_LOG_ENTER( p_log, osm_port_share_pkey );
+
+  if (!p_port_1 || !p_port_2)
+  {
+    ret = FALSE;
+    goto Exit;
+  }
+
+  p_physp1 = osm_port_get_default_phys_ptr(p_port_1);
+  p_physp2 = osm_port_get_default_phys_ptr(p_port_2);
+
+  if (!p_physp1 || !p_physp2)
+  {
+    ret = FALSE;
+    goto Exit;
+  }
+
+  ret = osm_physp_share_pkey(p_log, p_physp1, p_physp2);
+
+Exit:
+  OSM_LOG_EXIT(p_log);
+  return ret;
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_lid_share_pkey(
+  IN osm_log_t*          p_log,
+  IN const osm_subn_t *  const p_subn,
+  IN const ib_net16_t    lid1,
+  IN const uint8_t       port_num1,
+  IN const ib_net16_t    lid2,
+  IN const uint8_t       port_num2 ) {
+
+  osm_physp_t *p_physp1, *p_physp2;
+  osm_port_t *p_port1, *p_port2;
+  osm_node_t *p_node1, *p_node2;
+  const cl_ptr_vector_t* const p_port_lid_tbl = &(p_subn->port_lid_tbl);
+
+  OSM_LOG_ENTER( p_log, osm_lid_share_pkey );
+
+  p_port1 = cl_ptr_vector_get(p_port_lid_tbl, lid1);
+  p_port2 = cl_ptr_vector_get(p_port_lid_tbl, lid2);
+
+  p_node1 = p_port1->p_node;
+  p_node2 = p_port2->p_node;
+
+  if  (osm_node_get_type( p_node1 ) == IB_NODE_TYPE_SWITCH)
+  {
+    p_physp1 = osm_node_get_physp_ptr( p_node1, port_num1 );
+  }
+  else
+  {
+    p_physp1 = osm_port_get_default_phys_ptr(p_port1);
+  }
+
+  if  (osm_node_get_type( p_node2 ) == IB_NODE_TYPE_SWITCH)
+  {
+    p_physp2 = osm_node_get_physp_ptr( p_node2, port_num2 );
+  }
+  else
+  {
+    p_physp2 = osm_port_get_default_phys_ptr(p_port2);
+  }
+
+  return(osm_physp_share_pkey(p_log, p_physp1, p_physp2));
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_physp_has_pkey(
+  IN osm_log_t*               p_log,
+  IN const ib_net16_t         pkey,
+  IN const osm_physp_t* const p_physp ) {
+
+  ib_net16_t *p_pkey, pkey_base;
+  const osm_pkey_tbl_t *pkey_tbl;
+  boolean_t res = FALSE;
+  
+  OSM_LOG_ENTER( p_log, osm_physp_has_pkey );
+  
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "osm_physp_has_pkey: "
+           "Search for PKey: 0x%4x\n",
+           cl_ntoh16(pkey) );
+
+  /* if the pkey given is an invalid pkey - return TRUE. */
+  if(ib_pkey_is_invalid(pkey))
+  {
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osm_physp_has_pkey: "
+             "Given invalid PKey - we treat it loosely and allow it\n");
+    res = TRUE;
+    goto Exit;
+  }
+
+  pkey_base = ib_pkey_get_base(pkey);
+
+  pkey_tbl = osm_physp_get_pkey_tbl(p_physp);
+  
+  p_pkey = cl_map_get( &pkey_tbl->keys, pkey_base);
+  if (p_pkey) 
+  {
+    res = TRUE;
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osm_physp_has_pkey: "
+             "PKey 0x%04x was found\n", cl_ntoh16(pkey));
+  }
+  else 
+  {
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osm_physp_has_pkey: "
+             "PKey 0x%04x was not found\n", cl_ntoh16(pkey));
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return res;
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey_mgr.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey_mgr.c
new file mode 100644 (file)
index 0000000..fb44de8
--- /dev/null
@@ -0,0 +1,596 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_pkey_mgr.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of the P_Key Manager (Partititon Manager).
+ * This is part of the OpenSM.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_pkey_mgr.h>
+#include <opensm/osm_partition.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ **********************************************************************/
+/*
+  The max number of pkey blocks for a physical port is located in
+  a different place for switch external ports (SwitchInfo) and the
+  rest of the ports (NodeInfo).
+*/
+static uint16_t 
+pkey_mgr_get_physp_max_blocks(
+  IN const osm_subn_t *p_subn,
+  IN const osm_physp_t *p_physp )
+{
+  osm_node_t *p_node = osm_physp_get_node_ptr( p_physp );
+  uint16_t num_pkeys = 0;
+
+  if ( !p_node->sw ||
+       ( osm_physp_get_port_num( p_physp ) == 0 ) )
+    num_pkeys = cl_ntoh16( p_node->node_info.partition_cap );
+  else
+    num_pkeys = cl_ntoh16( p_node->sw->switch_info.enforce_cap );
+  return((num_pkeys + 31) / 32);
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ * Insert new pending pkey entry to the specific port pkey table
+ * pending pkeys. New entries are inserted at the back.
+ */
+static void 
+pkey_mgr_process_physical_port(
+  IN osm_log_t *p_log,
+  IN const osm_req_t *p_req,
+  IN const ib_net16_t pkey,
+  IN osm_physp_t *p_physp )
+{
+  osm_node_t *p_node = osm_physp_get_node_ptr( p_physp );
+  osm_pkey_tbl_t *p_pkey_tbl;
+  ib_net16_t *p_orig_pkey;
+  char *stat = NULL;
+  osm_pending_pkey_t *p_pending;
+
+  p_pkey_tbl = osm_physp_get_mod_pkey_tbl( p_physp );
+  p_pending = (osm_pending_pkey_t *)malloc( sizeof( osm_pending_pkey_t ) );
+  if (!p_pending)
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+            "pkey_mgr_process_physical_port: ERR 0502: "
+            "Failed to allocate new pending pkey entry for node "
+            "0x%016" PRIx64 " port %u\n",
+            cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+            osm_physp_get_port_num( p_physp ) );
+    return;
+  }
+  p_pending->pkey = pkey;
+  p_orig_pkey = cl_map_get( &p_pkey_tbl->keys, ib_pkey_get_base( pkey ) );
+  if (!p_orig_pkey)
+  {
+    p_pending->is_new = TRUE;
+    cl_qlist_insert_tail( &p_pkey_tbl->pending, (cl_list_item_t*)p_pending );
+    stat = "inserted";
+  }
+  else
+  {
+    CL_ASSERT( ib_pkey_get_base( *p_orig_pkey ) == ib_pkey_get_base( pkey ) );
+    p_pending->is_new = FALSE;
+    if (osm_pkey_tbl_get_block_and_idx(
+         p_pkey_tbl, p_orig_pkey,
+         &p_pending->block, &p_pending->index ) != IB_SUCCESS)
+    {
+      osm_log( p_log, OSM_LOG_ERROR,
+              "pkey_mgr_process_physical_port: ERR 0503: "
+              "Failed to obtain P_Key 0x%04x block and index for node "
+              "0x%016" PRIx64 " port %u\n",
+              ib_pkey_get_base( pkey ),
+              cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+              osm_physp_get_port_num( p_physp ) );
+      return;
+    }
+    cl_qlist_insert_head( &p_pkey_tbl->pending, (cl_list_item_t*)p_pending );
+    stat = "updated";
+  }
+
+  osm_log( p_log, OSM_LOG_DEBUG,
+          "pkey_mgr_process_physical_port: "
+          "pkey 0x%04x was %s for node 0x%016" PRIx64
+          " port %u\n",
+          cl_ntoh16( pkey ), stat,
+          cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+          osm_physp_get_port_num( p_physp ) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+pkey_mgr_process_partition_table(
+  osm_log_t *p_log,
+  const osm_req_t *p_req,
+  const osm_prtn_t *p_prtn,
+  const boolean_t full )
+{
+  const cl_map_t *p_tbl =
+    full ? &p_prtn->full_guid_tbl : &p_prtn->part_guid_tbl; 
+  cl_map_iterator_t i, i_next;
+  ib_net16_t pkey = p_prtn->pkey;
+  osm_physp_t *p_physp;
+
+  if (full)
+    pkey |= cl_hton16( 0x8000 );
+
+  i_next = cl_map_head( p_tbl );
+  while ( i_next != cl_map_end( p_tbl ) )
+  {
+    i = i_next;
+    i_next = cl_map_next( i );
+    p_physp = cl_map_obj( i );
+    if ( p_physp && osm_physp_is_valid( p_physp ) )
+      pkey_mgr_process_physical_port( p_log, p_req, pkey, p_physp );
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+pkey_mgr_update_pkey_entry(
+  IN const osm_req_t *p_req,
+  IN const osm_physp_t *p_physp,
+  IN const ib_pkey_table_t *block,
+  IN const uint16_t block_index )
+{
+  osm_madw_context_t context;
+  osm_node_t *p_node = osm_physp_get_node_ptr( p_physp );
+  uint32_t attr_mod;
+
+  context.pkey_context.node_guid = osm_node_get_node_guid( p_node );
+  context.pkey_context.port_guid = osm_physp_get_port_guid( p_physp );
+  context.pkey_context.set_method = TRUE;
+  attr_mod = block_index;
+  if ( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH )
+    attr_mod |= osm_physp_get_port_num( p_physp ) << 16;
+  return osm_req_set( p_req, osm_physp_get_dr_path_ptr( p_physp ),
+                      ( uint8_t * ) block, sizeof( *block ),
+                      IB_MAD_ATTR_P_KEY_TABLE,
+                      cl_hton32( attr_mod ), CL_DISP_MSGID_NONE, &context );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+pkey_mgr_enforce_partition(
+  IN osm_log_t *p_log,
+  IN const osm_req_t *p_req,
+  IN const osm_physp_t *p_physp,
+  IN const boolean_t enforce)
+{
+  osm_madw_context_t context;
+  uint8_t payload[IB_SMP_DATA_SIZE];
+  ib_port_info_t *p_pi;
+  ib_api_status_t status;
+
+  if (!(p_pi = osm_physp_get_port_info_ptr( p_physp )))
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "pkey_mgr_enforce_partition: ERR 0507: "
+             "No port info for "
+             "node 0x%016" PRIx64 " port %u\n",
+             cl_ntoh64(
+               osm_node_get_node_guid( 
+                  osm_physp_get_node_ptr( p_physp ))),
+             osm_physp_get_port_num( p_physp ) );
+    return FALSE;
+  }
+
+  if ((p_pi->vl_enforce & 0xc) == (0xc)*(enforce == TRUE)) 
+  {
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "pkey_mgr_enforce_partition: "
+             "No need to update PortInfo for "
+             "node 0x%016" PRIx64 " port %u\n",
+             cl_ntoh64(
+               osm_node_get_node_guid( 
+                  osm_physp_get_node_ptr( p_physp ))),
+             osm_physp_get_port_num( p_physp ) );
+    return FALSE;
+  }
+
+  memset( payload, 0, IB_SMP_DATA_SIZE );
+  memcpy( payload, p_pi, sizeof(ib_port_info_t) );
+
+  p_pi = (ib_port_info_t*)payload;
+  if (enforce == TRUE)
+    p_pi->vl_enforce |= 0xc;
+  else
+    p_pi->vl_enforce &= ~0xc;
+  p_pi->state_info2 = 0;
+  ib_port_info_set_port_state( p_pi, IB_LINK_NO_CHANGE );
+
+  context.pi_context.node_guid =
+    osm_node_get_node_guid( osm_physp_get_node_ptr( p_physp ) );
+  context.pi_context.port_guid = osm_physp_get_port_guid( p_physp );
+  context.pi_context.set_method = TRUE;
+  context.pi_context.update_master_sm_base_lid = FALSE;
+  context.pi_context.ignore_errors = FALSE;
+  context.pi_context.light_sweep = FALSE;
+  context.pi_context.active_transition = FALSE;
+
+  status = osm_req_set( p_req, osm_physp_get_dr_path_ptr( p_physp ),
+                       payload, sizeof(payload),
+                       IB_MAD_ATTR_PORT_INFO,
+                       cl_hton32( osm_physp_get_port_num( p_physp ) ),
+                       CL_DISP_MSGID_NONE, &context );
+  if (status != IB_SUCCESS) 
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "pkey_mgr_enforce_partition: ERR 0511: "
+             "Failed to set PortInfo for "
+             "node 0x%016" PRIx64 " port %u\n",
+             cl_ntoh64(
+               osm_node_get_node_guid( 
+                  osm_physp_get_node_ptr( p_physp ))),
+             osm_physp_get_port_num( p_physp ) );
+    return FALSE;
+  }
+  else
+  {
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "pkey_mgr_enforce_partition: "
+             "Set PortInfo for "
+             "node 0x%016" PRIx64 " port %u\n",
+             cl_ntoh64(
+               osm_node_get_node_guid( 
+                  osm_physp_get_node_ptr( p_physp ))),
+             osm_physp_get_port_num( p_physp ) );
+    return TRUE;
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t pkey_mgr_update_port(
+  osm_log_t *p_log,
+  osm_req_t *p_req,
+  const osm_port_t * const p_port )
+{
+  osm_physp_t *p_physp;
+  osm_node_t *p_node;
+  ib_pkey_table_t *block, *new_block;
+  osm_pkey_tbl_t *p_pkey_tbl;
+  uint16_t block_index;
+  uint8_t  pkey_index;
+  uint16_t last_free_block_index = 0;
+  uint8_t  last_free_pkey_index = 0;
+  uint16_t num_of_blocks;
+  uint16_t max_num_of_blocks;
+  ib_api_status_t status;
+  boolean_t ret_val = FALSE;
+  osm_pending_pkey_t *p_pending;
+  boolean_t found;
+  ib_pkey_table_t empty_block;
+
+  memset(&empty_block, 0, sizeof(ib_pkey_table_t));
+
+  p_physp = osm_port_get_default_phys_ptr( p_port );
+  if ( !osm_physp_is_valid( p_physp ) )
+    return FALSE;
+
+  p_node = osm_physp_get_node_ptr( p_physp );
+  p_pkey_tbl = osm_physp_get_mod_pkey_tbl( p_physp );
+  num_of_blocks = osm_pkey_tbl_get_num_blocks( p_pkey_tbl );
+  max_num_of_blocks = pkey_mgr_get_physp_max_blocks( p_req->p_subn, p_physp );
+  if ( p_pkey_tbl->max_blocks > max_num_of_blocks )
+  {
+    osm_log( p_log, OSM_LOG_INFO,
+            "pkey_mgr_update_port: "
+            "Max number of blocks reduced from %u to %u " 
+            "for node 0x%016" PRIx64 " port %u\n",
+            p_pkey_tbl->max_blocks, max_num_of_blocks,
+            cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+            osm_physp_get_port_num( p_physp ) );                               
+  }
+  p_pkey_tbl->max_blocks = max_num_of_blocks;
+
+  osm_pkey_tbl_init_new_blocks( p_pkey_tbl );
+  p_pkey_tbl->used_blocks = 0;
+
+  /* 
+    process every pending pkey in order - 
+    first must be "updated" last are "new" 
+   */
+  p_pending = (osm_pending_pkey_t *)cl_qlist_remove_head( &p_pkey_tbl->pending ); 
+  while ( p_pending != (osm_pending_pkey_t *)cl_qlist_end( &p_pkey_tbl->pending ))
+  {
+    if (p_pending->is_new == FALSE)
+    {
+       block_index = p_pending->block;
+       pkey_index = p_pending->index;
+       found = TRUE;
+    } 
+    else
+    {
+       found = osm_pkey_find_next_free_entry( p_pkey_tbl, 
+                                              &last_free_block_index,
+                                              &last_free_pkey_index );
+       if (!found)
+       {
+         osm_log( p_log, OSM_LOG_ERROR,
+                  "pkey_mgr_update_port: ERR 0504: "
+                  "Failed to find empty space for new pkey 0x%04x "
+                  "for node 0x%016" PRIx64 " port %u\n",
+                  cl_ntoh16( p_pending->pkey ),
+                  cl_ntoh64( osm_node_get_node_guid( p_node )),
+                  osm_physp_get_port_num( p_physp ) );
+       }
+       else
+       {
+         block_index = last_free_block_index;
+         pkey_index = last_free_pkey_index++;
+       }
+    }
+
+   if (found) 
+   {
+       if (IB_SUCCESS != osm_pkey_tbl_set_new_entry( p_pkey_tbl, block_index, 
+                                                      pkey_index, p_pending->pkey ))
+       {
+         osm_log( p_log, OSM_LOG_ERROR,
+                  "pkey_mgr_update_port: ERR 0505: "
+                  "Failed to set PKey 0x%04x in block %u idx %u "
+                  "for node 0x%016" PRIx64 " port %u\n",
+                  p_pending->pkey, block_index, pkey_index,
+                  cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+                  osm_physp_get_port_num( p_physp ) );
+       }
+    }
+
+    free(p_pending);
+    p_pending = (osm_pending_pkey_t *)cl_qlist_remove_head( &p_pkey_tbl->pending );
+  }
+
+  /* now look for changes and store */
+  for (block_index = 0; block_index < num_of_blocks; block_index++)
+  {
+    block = osm_pkey_tbl_block_get( p_pkey_tbl, block_index );
+    new_block = osm_pkey_tbl_new_block_get( p_pkey_tbl, block_index );
+    if (!new_block)
+      new_block = &empty_block;
+    if (block && !memcmp( new_block, block, sizeof( *block ) ))
+      continue;
+
+    status = pkey_mgr_update_pkey_entry( p_req, p_physp, new_block, block_index );
+    if (status == IB_SUCCESS)
+    {
+      osm_log( p_log, OSM_LOG_DEBUG,
+              "pkey_mgr_update_port: "
+              "Updated "
+              "pkey table block %d for node 0x%016" PRIx64 " port %u\n",
+               block_index,
+               cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+               osm_physp_get_port_num( p_physp ) );
+      ret_val = TRUE;
+    }
+    else
+    {
+      osm_log( p_log, OSM_LOG_ERROR,
+              "pkey_mgr_update_port: ERR 0506: "
+               "pkey_mgr_update_pkey_entry() failed to update "
+               "pkey table block %d for node 0x%016" PRIx64 " port %u\n",
+               block_index,
+               cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+               osm_physp_get_port_num( p_physp ) );
+    }
+  }
+
+  return ret_val;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+pkey_mgr_update_peer_port(
+  osm_log_t *p_log,
+  const osm_req_t *p_req,
+  const osm_subn_t *p_subn,
+  const osm_port_t * const p_port,
+  boolean_t enforce )
+{
+  osm_physp_t *p_physp, *peer;
+  osm_node_t *p_node;
+  ib_pkey_table_t *block, *peer_block;
+  const osm_pkey_tbl_t *p_pkey_tbl;
+  osm_pkey_tbl_t *p_peer_pkey_tbl;
+  uint16_t block_index;
+  uint16_t num_of_blocks;
+  uint16_t peer_max_blocks;
+  ib_api_status_t status = IB_SUCCESS;
+  boolean_t ret_val = FALSE;
+  boolean_t port_info_set = FALSE;
+  ib_pkey_table_t empty_block;
+
+  memset(&empty_block, 0, sizeof(ib_pkey_table_t));
+
+  p_physp = osm_port_get_default_phys_ptr( p_port );
+  if (!osm_physp_is_valid( p_physp ))
+    return FALSE;
+  peer = osm_physp_get_remote( p_physp );
+  if ( !peer || !osm_physp_is_valid( peer ) )
+    return FALSE;
+  p_node = osm_physp_get_node_ptr( peer );
+  if ( !p_node->sw || !p_node->sw->switch_info.enforce_cap )
+    return FALSE;
+
+  p_pkey_tbl = osm_physp_get_pkey_tbl( p_physp );
+  p_peer_pkey_tbl = osm_physp_get_mod_pkey_tbl( peer );
+  num_of_blocks = osm_pkey_tbl_get_num_blocks( p_pkey_tbl );
+  peer_max_blocks = pkey_mgr_get_physp_max_blocks( p_subn, peer );
+  if (peer_max_blocks < p_pkey_tbl->used_blocks)
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+            "pkey_mgr_update_peer_port: ERR 0508: "
+            "Not enough pkey entries (%u < %u) on switch 0x%016" PRIx64
+            " port %u. Clearing Enforcement bit\n",
+            peer_max_blocks, num_of_blocks,
+            cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+            osm_physp_get_port_num( peer ) );
+    enforce = FALSE;
+  }
+
+  if ( pkey_mgr_enforce_partition( p_log, p_req, peer, enforce ) )
+    port_info_set = TRUE;
+
+  if (enforce == FALSE)
+    return port_info_set;
+
+  p_peer_pkey_tbl->used_blocks = p_pkey_tbl->used_blocks;
+  for (block_index = 0; block_index < p_pkey_tbl->used_blocks; block_index++)
+  {
+    block = osm_pkey_tbl_new_block_get( p_pkey_tbl, block_index );
+    if (!block)
+      block = &empty_block;
+
+    peer_block = osm_pkey_tbl_block_get( p_peer_pkey_tbl, block_index );
+    if ( !peer_block || memcmp( peer_block, block, sizeof( *peer_block ) ) )
+    {
+      status = pkey_mgr_update_pkey_entry( p_req, peer, block, block_index );
+      if ( status == IB_SUCCESS )
+        ret_val = TRUE;
+      else
+        osm_log( p_log, OSM_LOG_ERROR,
+                "pkey_mgr_update_peer_port: ERR 0509: "
+                "pkey_mgr_update_pkey_entry() failed to update "
+                "pkey table block %d for node 0x%016" PRIx64
+                " port %u\n",
+                block_index,
+                cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+                osm_physp_get_port_num( peer ) );
+    }
+  }
+
+  if ( (ret_val == TRUE) && osm_log_is_active( p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "pkey_mgr_update_peer_port: "
+             "Pkey table was updated for node 0x%016" PRIx64
+             " port %u\n",
+             cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+             osm_physp_get_port_num( peer ) );
+  }
+
+  if (port_info_set)
+    return TRUE;
+  return ret_val;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_signal_t
+osm_pkey_mgr_process(
+  IN osm_opensm_t *p_osm )
+{
+  cl_qmap_t *p_tbl;
+  cl_map_item_t *p_next;
+  osm_prtn_t *p_prtn;
+  osm_port_t *p_port;
+  osm_signal_t signal = OSM_SIGNAL_DONE;
+  osm_node_t *p_node;
+
+  CL_ASSERT( p_osm );
+
+  OSM_LOG_ENTER( &p_osm->log, osm_pkey_mgr_process );
+
+  CL_PLOCK_EXCL_ACQUIRE( &p_osm->lock );
+
+  if ( osm_prtn_make_partitions( &p_osm->log, &p_osm->subn ) != IB_SUCCESS )
+  {
+    osm_log( &p_osm->log, OSM_LOG_ERROR,
+            "osm_pkey_mgr_process: ERR 0510: "
+            "osm_prtn_make_partitions() failed\n" );
+    goto _err;
+  }
+
+  /* populate the pending pkey entries by scanning all partitions */
+  p_tbl = &p_osm->subn.prtn_pkey_tbl;
+  p_next = cl_qmap_head( p_tbl );
+  while ( p_next != cl_qmap_end( p_tbl ) )
+  {
+    p_prtn = ( osm_prtn_t * ) p_next;
+    p_next = cl_qmap_next( p_next );
+    pkey_mgr_process_partition_table( &p_osm->log, &p_osm->sm.req,
+                                     p_prtn, FALSE );
+    pkey_mgr_process_partition_table( &p_osm->log, &p_osm->sm.req,
+                                     p_prtn, TRUE );
+  }
+
+  /* calculate and set new pkey tables */
+  p_tbl = &p_osm->subn.port_guid_tbl;
+  p_next = cl_qmap_head( p_tbl );
+  while ( p_next != cl_qmap_end( p_tbl ) )
+  {
+    p_port = ( osm_port_t * ) p_next;
+    p_next = cl_qmap_next( p_next );
+    if ( pkey_mgr_update_port( &p_osm->log, &p_osm->sm.req, p_port ) )
+      signal = OSM_SIGNAL_DONE_PENDING;
+    p_node = osm_port_get_parent_node( p_port );
+    if ( ( osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH ) &&
+        pkey_mgr_update_peer_port( &p_osm->log, &p_osm->sm.req, 
+                                   &p_osm->subn, p_port,
+                                   !p_osm->subn.opt.no_partition_enforcement ) )
+      signal = OSM_SIGNAL_DONE_PENDING;
+  }
+
+ _err:
+  CL_PLOCK_RELEASE( &p_osm->lock );
+  OSM_LOG_EXIT( &p_osm->log );
+  return ( signal );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey_rcv.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey_rcv.c
new file mode 100644 (file)
index 0000000..1e98211
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_pkey_rcv.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_pkey_rcv.h>
+#include <opensm/osm_node_info_rcv.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_helper.h>
+#include <vendor/osm_vendor_api.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rcv_construct(
+  IN osm_pkey_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rcv_destroy(
+  IN osm_pkey_rcv_t* const p_rcv )
+{
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_pkey_rcv_destroy );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pkey_rcv_init(
+  IN osm_pkey_rcv_t* const p_rcv,
+  IN osm_req_t* const p_req,
+  IN osm_subn_t* const p_subn,
+  IN osm_log_t* const p_log,
+  IN cl_plock_t* const p_lock )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_pkey_rcv_init );
+
+  osm_pkey_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_req = p_req;
+
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ * WE MIGHT ONLY RECEIVE GET or SET responses
+ */
+void
+osm_pkey_rcv_process(
+  IN const osm_pkey_rcv_t* const p_rcv,
+  IN osm_madw_t* const p_madw )
+{
+  cl_qmap_t *p_guid_tbl;
+  ib_pkey_table_t *p_pkey_tbl;
+  ib_smp_t *p_smp;
+  osm_port_t *p_port;
+  osm_physp_t *p_physp;
+  osm_node_t *p_node;
+  osm_pkey_context_t *p_context;
+  ib_net64_t port_guid;
+  ib_net64_t node_guid;
+  uint8_t  port_num;
+  uint16_t block_num;
+
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_pkey_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+
+  p_context = osm_madw_get_pkey_context_ptr( p_madw );
+  p_pkey_tbl = (ib_pkey_table_t*)ib_smp_get_payload_ptr( p_smp );
+
+  port_guid = p_context->port_guid;
+  node_guid = p_context->node_guid;
+
+  CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_P_KEY_TABLE );
+
+  p_guid_tbl = &p_rcv->p_subn->port_guid_tbl;
+  cl_plock_excl_acquire( p_rcv->p_lock );
+  p_port = (osm_port_t*)cl_qmap_get( p_guid_tbl, port_guid );
+
+  if( p_port == (osm_port_t*)cl_qmap_end( p_guid_tbl) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_pkey_rcv_process: ERR 4806: "
+             "No port object for port with GUID 0x%" PRIx64
+             "\n\t\t\t\tfor parent node GUID 0x%" PRIx64
+             ", TID 0x%" PRIx64 "\n",
+             cl_ntoh64( port_guid ),
+             cl_ntoh64( node_guid ),
+             cl_ntoh64( p_smp->trans_id ) );
+    goto Exit;
+  }
+
+  p_node = osm_port_get_parent_node( p_port );
+  CL_ASSERT( p_node );
+
+  block_num = (uint16_t)((cl_ntoh32(p_smp->attr_mod)) & 0x0000FFFF);
+  /* in case of a non switch node the attr modifier should be ignored */
+  if (osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH)
+  {
+    port_num = (uint8_t)(((cl_ntoh32( p_smp->attr_mod)) & 0x00FF0000) >> 16 );
+    p_physp = osm_node_get_physp_ptr( p_node, port_num );
+  }
+  else
+  {
+    p_physp = osm_port_get_default_phys_ptr(p_port);
+    port_num = p_port->default_port_num;
+  }
+
+  CL_ASSERT( p_physp );
+
+  /*
+    We do not mind if this is a result of a set or get - all we want is to
+    update the subnet.
+  */
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "osm_pkey_rcv_process: "
+             "Got GetResp(PKey) block:%u port_num %u with GUID 0x%" PRIx64
+             " for parent node GUID 0x%" PRIx64
+             ", TID 0x%" PRIx64 "\n",
+             block_num, port_num,
+             cl_ntoh64( port_guid ),
+             cl_ntoh64( node_guid ),
+             cl_ntoh64( p_smp->trans_id ) );
+  }
+
+  /*
+    Determine if we encountered a new Physical Port.
+    If so, ignore it.
+  */
+  if( !osm_physp_is_valid( p_physp ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_pkey_rcv_process: ERR 4807: "
+             "Got invalid port number 0x%X\n",
+             port_num );
+    goto Exit;
+  }
+
+  osm_dump_pkey_block( p_rcv->p_log,
+                       port_guid, block_num,
+                       port_num, p_pkey_tbl,
+                       OSM_LOG_DEBUG );
+
+  osm_physp_set_pkey_tbl( p_rcv->p_log, p_rcv->p_subn,
+                          p_physp, p_pkey_tbl, block_num );
+
+ Exit:
+  cl_plock_release( p_rcv->p_lock );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey_rcv_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_pkey_rcv_ctrl.c
new file mode 100644 (file)
index 0000000..17eb035
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_pkey_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_pkey_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pkey_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_pkey_rcv_process( ((osm_pkey_rcv_ctrl_t*)context)->p_rcv,
+                        (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rcv_ctrl_construct(
+  IN osm_pkey_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rcv_ctrl_destroy(
+  IN osm_pkey_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pkey_rcv_ctrl_init(
+  IN osm_pkey_rcv_ctrl_t* const p_ctrl,
+  IN osm_pkey_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_pkey_rcv_ctrl_init );
+
+  osm_pkey_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+
+
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_PKEY,
+    __osm_pkey_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_pkey_rcv_ctrl_init: ERR 4901: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_port.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_port.c
new file mode 100644 (file)
index 0000000..2ab02d2
--- /dev/null
@@ -0,0 +1,936 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_port.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_physp_t.
+ * This object represents an Infiniband Port.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mcm_info.h>
+#include <opensm/osm_switch.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_physp_construct(
+  IN osm_physp_t* const p_physp )
+{
+  memset( p_physp, 0, sizeof(*p_physp) );
+  osm_dr_path_construct( &p_physp->dr_path );
+  cl_ptr_vector_construct( &p_physp->slvl_by_port );
+  osm_pkey_tbl_construct( &p_physp->pkeys );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_physp_destroy(
+  IN osm_physp_t* const p_physp )
+{
+  size_t num_slvl, i;
+
+  /* the physp might be un-initialized */
+  if (p_physp->port_guid)
+  {
+    /* free the SL2VL Tables */
+    num_slvl = cl_ptr_vector_get_size(&p_physp->slvl_by_port);
+    for (i = 0; i < num_slvl; i++)
+      free(cl_ptr_vector_get(&p_physp->slvl_by_port, i));
+    cl_ptr_vector_destroy(&p_physp->slvl_by_port);
+    
+    /* free the P_Key Tables */
+    osm_pkey_tbl_destroy( &p_physp->pkeys );
+    
+    memset( p_physp, 0, sizeof(*p_physp) );
+    osm_dr_path_construct( &p_physp->dr_path ); /* clear dr_path */
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_physp_init(
+  IN osm_physp_t* const p_physp,
+  IN const ib_net64_t port_guid,
+  IN const uint8_t port_num,
+  IN const struct _osm_node* const p_node,
+  IN const osm_bind_handle_t h_bind,
+  IN const uint8_t hop_count,
+  IN const uint8_t* const p_initial_path )
+{
+  uint16_t num_slvl, i;
+  ib_slvl_table_t *p_slvl;
+
+  CL_ASSERT( p_node );
+
+  osm_physp_construct( p_physp );
+  p_physp->port_guid = port_guid;
+  p_physp->port_num = port_num;
+  p_physp->healthy = TRUE;
+  p_physp->p_node = (struct _osm_node*)p_node;
+
+  osm_dr_path_init(
+    &p_physp->dr_path,
+    h_bind,
+    hop_count,
+    p_initial_path );
+
+  /* allocate enough SL2VL tables */
+  if (osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH)
+  {
+    /* we need node num ports + 1 SL2VL tables */
+    num_slvl = osm_node_get_num_physp( p_node ) + 1;
+  }
+  else
+  {
+    /* An end node - we need only one SL2VL */
+    num_slvl = 1;
+  }
+
+  cl_ptr_vector_init( &p_physp->slvl_by_port, num_slvl, 1);
+  for (i = 0; i < num_slvl; i++)
+  {
+    p_slvl = (ib_slvl_table_t *)malloc(sizeof(ib_slvl_table_t));
+    if (p_slvl)
+      memset(p_slvl, 0, sizeof(ib_slvl_table_t));
+    cl_ptr_vector_set(&p_physp->slvl_by_port, i, p_slvl);
+  }
+
+  /* initialize the pkey table */
+  osm_pkey_tbl_init( &p_physp->pkeys );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_port_destroy(
+  IN osm_port_t* const p_port )
+{
+  /* cleanup all mcm recs attached */
+  osm_port_remove_all_mgrp( p_port );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_port_init(
+  IN osm_port_t* const p_port,
+  IN const ib_node_info_t* p_ni,
+  IN const osm_node_t* const p_parent_node )
+{
+  uint32_t port_index;
+  ib_net64_t port_guid;
+  osm_physp_t *p_physp;
+  uint32_t size;
+
+  CL_ASSERT( p_port );
+  CL_ASSERT( p_ni );
+  CL_ASSERT( p_parent_node );
+
+  osm_port_construct( p_port );
+
+  p_port->p_node = (struct _osm_node *)p_parent_node;
+  port_guid = p_ni->port_guid;
+  p_port->guid = port_guid;
+
+  /*
+    See comment in port_new for info about this...
+  */
+  size = p_ni->num_ports;
+
+  p_port->physp_tbl_size = (uint8_t)(size + 1);
+
+  /*
+    Get the pointers to the physical node objects "owned" by this
+    logical port GUID.
+    For switches, all the ports are owned; for HCA's and routers,
+    only the singular part that has this GUID is owned.
+  */
+  p_port->default_port_num = 0xFF;
+  for( port_index = 0; port_index < p_port->physp_tbl_size; port_index++ )
+  {
+    p_physp = osm_node_get_physp_ptr( p_parent_node, port_index );
+    if( osm_physp_is_valid( p_physp ) &&
+        port_guid == osm_physp_get_port_guid( p_physp ) )
+    {
+      p_port->tbl[port_index] = p_physp;
+      /*
+        Because much of the PortInfo data is only valid
+        for port 0 on switches, try to keep the lowest
+        possible value of default_port_num.
+      */
+      if( port_index < p_port->default_port_num )
+        p_port->default_port_num = (uint8_t)port_index;
+    }
+    else
+      p_port->tbl[port_index] = NULL;
+  }
+
+  CL_ASSERT( p_port->default_port_num < 0xFF );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_port_t*
+osm_port_new(
+  IN const ib_node_info_t* p_ni,
+  IN const osm_node_t* const p_parent_node )
+{
+  osm_port_t*  p_port;
+  uint32_t size;
+
+  /*
+    The port object already contains one physical port object pointer.
+    Therefore, subtract 1 from the number of physical ports
+    used by the switch.  This is not done for CA's since they
+    need to occupy 1 more physp pointer than they physically have since
+    we still reserve room for a "port 0".
+  */
+  size = p_ni->num_ports;
+
+  p_port = malloc( sizeof(*p_port) + sizeof(void *) * size );
+  if( p_port != NULL )
+  {
+    memset( p_port, 0, sizeof(*p_port) + sizeof(void *) * size );
+    osm_port_init( p_port, p_ni, p_parent_node );
+  }
+
+  return( p_port );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_port_get_lid_range_ho(
+  IN const osm_port_t* const p_port,
+  IN uint16_t* const p_min_lid,
+  IN uint16_t* const p_max_lid )
+{
+  uint8_t lmc;
+
+  *p_min_lid = cl_ntoh16( osm_port_get_base_lid( p_port ) );
+  lmc = osm_port_get_lmc( p_port );
+  *p_max_lid = (uint16_t)(*p_min_lid + (1 << lmc) - 1);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_get_port_by_base_lid(
+  IN const osm_subn_t*      const p_subn,
+  IN const ib_net16_t       lid,
+  IN OUT const osm_port_t** const pp_port )
+{
+  ib_api_status_t           status;
+  uint16_t                  base_lid; 
+  uint8_t                   lmc;
+
+  *pp_port = NULL;
+
+  /* Loop on lmc from 0 up through max LMC possible */
+  for (lmc = 0; lmc <= IB_PORT_LMC_MAX; lmc++)
+  {
+    /* Calculate a base LID assuming this is the real LMC */
+    base_lid = cl_ntoh16(lid) & ~((1 << lmc) - 1);
+
+    /* Look for a match */
+    status = cl_ptr_vector_at( &p_subn->port_lid_tbl,
+                               base_lid,
+                               (void**)pp_port );
+    if ((status == CL_SUCCESS) && (*pp_port != NULL))
+    {
+       /* Determine if base LID "tested" is the real base LID */
+       /* This is true if the LMC "tested" is the port's actual LMC */
+       if (lmc == osm_port_get_lmc( *pp_port ) )
+       {
+         status = IB_SUCCESS;
+         goto Found;
+       }
+    }
+  }
+  *pp_port = NULL;
+  status = IB_NOT_FOUND;
+
+ Found:
+  return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_port_add_new_physp(
+  IN osm_port_t* const p_port,
+  IN const uint8_t port_num )
+{
+  osm_node_t *p_node;
+  osm_physp_t *p_physp;
+
+  CL_ASSERT( port_num < p_port->physp_tbl_size );
+
+  p_node = p_port->p_node;
+  CL_ASSERT( p_node );
+
+  p_physp = osm_node_get_physp_ptr( p_node, port_num );
+  CL_ASSERT( osm_physp_is_valid( p_physp ) );
+  CL_ASSERT( osm_physp_get_port_guid( p_physp ) == p_port->guid );
+  p_port->tbl[port_num] = p_physp;
+
+  /*
+    For switches, we generally want to use Port 0, which is
+    the management port as the default Physical Port.
+    The LID value in the PortInfo for example, is only valid
+    for port 0 on switches.
+  */
+  if( !osm_physp_is_valid( p_port->tbl[p_port->default_port_num] ) )
+  {
+    p_port->default_port_num = port_num;
+  }
+  else
+  {
+    if(  port_num < p_port->default_port_num )
+    {
+      p_port->default_port_num = port_num;
+    }
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_port_add_mgrp(
+  IN osm_port_t* const p_port,
+  IN const ib_net16_t mlid )
+{
+  ib_api_status_t    status = IB_SUCCESS;
+  osm_mcm_info_t     *p_mcm;
+
+  p_mcm = osm_mcm_info_new( mlid );
+  if( p_mcm )
+    cl_qlist_insert_tail( &p_port->mcm_list, (cl_list_item_t*)p_mcm );
+  else
+    status = IB_INSUFFICIENT_MEMORY;
+
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static cl_status_t
+__osm_port_mgrp_find_func(
+  IN const cl_list_item_t* const p_list_item,
+  IN void* context )
+{
+  if( *((ib_net16_t*)context) == ((osm_mcm_info_t*)p_list_item)->mlid )
+    return( CL_SUCCESS );
+  else
+    return( CL_NOT_FOUND );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_port_remove_mgrp(
+  IN osm_port_t* const p_port,
+  IN const ib_net16_t mlid )
+{
+  cl_list_item_t     *p_mcm;
+
+  p_mcm = cl_qlist_find_from_head( &p_port->mcm_list,
+                                   __osm_port_mgrp_find_func, &mlid );
+
+  if( p_mcm != cl_qlist_end( &p_port->mcm_list ) )
+  {
+    cl_qlist_remove_item( &p_port->mcm_list, p_mcm );
+    osm_mcm_info_delete( (osm_mcm_info_t*)p_mcm );
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_port_remove_all_mgrp(
+  IN osm_port_t* const p_port )
+{
+  cl_list_item_t     *p_mcm;
+
+  p_mcm = cl_qlist_remove_head( &p_port->mcm_list );
+  while( p_mcm != cl_qlist_end( &p_port->mcm_list ) )
+  {
+    osm_mcm_info_delete( (osm_mcm_info_t*)p_mcm );
+    p_mcm = cl_qlist_remove_head( &p_port->mcm_list );
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+uint8_t
+osm_physp_calc_link_mtu(
+  IN osm_log_t*           p_log,
+  IN const osm_physp_t*   p_physp )
+{
+  const ib_port_info_t* p_old_pi;
+  const ib_port_info_t* p_remote_pi;
+  const osm_physp_t*    p_remote_physp;
+  uint8_t                  mtu;
+  uint8_t                  remote_mtu;
+
+  OSM_LOG_ENTER( p_log, osm_physp_calc_link_mtu );
+  p_old_pi = osm_physp_get_port_info_ptr( p_physp );
+
+  /* use the available MTU */
+  mtu = ib_port_info_get_mtu_cap( p_old_pi );
+
+  p_remote_physp = osm_physp_get_remote( p_physp );
+  if( p_remote_physp && osm_physp_is_valid( p_remote_physp ) )
+  {
+    p_remote_pi = osm_physp_get_port_info_ptr( p_remote_physp );
+    remote_mtu = ib_port_info_get_mtu_cap( p_remote_pi );
+
+    if( osm_log_is_active( p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_log, OSM_LOG_DEBUG,
+               "osm_physp_calc_link_mtu: "
+               "Remote port 0x%016" PRIx64 " port# = 0x%X : "
+               "MTU = %u. This Port MTU: %u\n",
+               cl_ntoh64( osm_physp_get_port_guid( p_remote_physp ) ),
+               osm_physp_get_port_num( p_remote_physp ),
+               remote_mtu, mtu );
+    }
+
+    if( mtu != remote_mtu )
+    {
+      if( mtu > remote_mtu )
+        mtu = remote_mtu;
+
+      if( osm_log_is_active( p_log, OSM_LOG_VERBOSE ) )
+      {
+        osm_log( p_log, OSM_LOG_VERBOSE,
+                 "osm_physp_calc_link_mtu: "
+                 "MTU mismatch between ports."
+                 "\n\t\t\t\tPort 0x%016" PRIx64 ", port# 0x%X"
+                 " and port 0x%016" PRIx64 ", port# 0x%X."
+                 "\n\t\t\t\tUsing lower MTU of %u\n",
+                 cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+                 osm_physp_get_port_num( p_physp ),
+                 cl_ntoh64( osm_physp_get_port_guid( p_remote_physp ) ),
+                 osm_physp_get_port_num( p_remote_physp ),
+                 mtu );
+      }
+    }
+  }
+
+  if( mtu == 0 )
+  {
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osm_physp_calc_link_mtu: ERR 4101: "
+             "Invalid MTU = 0. Forcing correction to 256\n" );
+    mtu = 1;
+  }
+
+  OSM_LOG_EXIT( p_log );
+  return(mtu);
+}
+
+/**********************************************************************
+ **********************************************************************/
+uint8_t
+osm_physp_calc_link_op_vls(
+  IN osm_log_t*           p_log,
+  IN const osm_subn_t*    p_subn,
+  IN const osm_physp_t*   p_physp )
+{
+  const ib_port_info_t* p_old_pi;
+  const ib_port_info_t* p_remote_pi;
+  const osm_physp_t*    p_remote_physp;
+  uint8_t                  op_vls;
+  uint8_t                  remote_op_vls;
+
+  OSM_LOG_ENTER( p_log, osm_physp_calc_link_op_vls );
+  p_old_pi = osm_physp_get_port_info_ptr( p_physp );
+
+  /* use the available VL CAP */
+  op_vls = ib_port_info_get_vl_cap(p_old_pi);
+
+  p_remote_physp = osm_physp_get_remote( p_physp );
+  if( p_remote_physp && osm_physp_is_valid( p_remote_physp ) )
+  {
+    p_remote_pi = osm_physp_get_port_info_ptr( p_remote_physp );
+    remote_op_vls = ib_port_info_get_vl_cap(p_remote_pi);
+
+    if( osm_log_is_active( p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_log, OSM_LOG_DEBUG,
+               "osm_physp_calc_link_op_vls: "
+               "Remote port 0x%016" PRIx64 " port# = 0x%X : "
+               "VL_CAP = %u. This port VL_CAP:%u\n",
+               cl_ntoh64( osm_physp_get_port_guid( p_remote_physp ) ),
+               osm_physp_get_port_num( p_remote_physp ),
+               remote_op_vls,
+               op_vls
+               );
+    }
+
+    if( op_vls != remote_op_vls )
+    {
+      if( op_vls > remote_op_vls )
+        op_vls = remote_op_vls;
+
+      if( osm_log_is_active( p_log, OSM_LOG_VERBOSE ) )
+      {
+        osm_log( p_log, OSM_LOG_VERBOSE,
+                 "osm_physp_calc_link_op_vls: "
+                 "OP_VLS mismatch between ports."
+                 "\n\t\t\t\tPort 0x%016" PRIx64 ", port# 0x%X"
+                 " and port 0x%016" PRIx64 ", port# 0x%X."
+                 "\n\t\t\t\tUsing lower OP_VLS of %u\n",
+                 cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+                 osm_physp_get_port_num( p_physp ),
+                 cl_ntoh64( osm_physp_get_port_guid( p_remote_physp ) ),
+                 osm_physp_get_port_num( p_remote_physp ),
+                 op_vls );
+      }
+    }
+  }
+
+  /* support user limitation of max_op_vls */
+  if (op_vls > p_subn->opt.max_op_vls)
+    op_vls = p_subn->opt.max_op_vls;
+
+  if( op_vls == 0 )
+  {
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osm_physp_calc_link_op_vls: ERR 4102: "
+             "Invalid OP_VLS = 0. Forcing correction to 1 (VL0)\n" );
+    op_vls = 1;
+  }
+
+  OSM_LOG_EXIT( p_log );
+  return(op_vls);
+}
+
+inline 
+uint64_t 
+__osm_ptr_to_key(void const *p)
+{
+  uint64_t k = 0;
+
+  memcpy(&k, p, sizeof(void *));
+  return k;
+}
+
+inline 
+void *
+__osm_key_to_ptr(uint64_t k)
+{
+  void *p = 0;
+
+  memcpy(&p, &k, sizeof(void *));
+  return p;
+}
+
+/**********************************************************************
+ Traverse the fabric from the SM node following the DR path given and
+ add every phys port traversed to the map. Avoid tracking the first and
+ last phys ports (going into the first switch and into the target port).
+ **********************************************************************/
+cl_status_t
+__osm_physp_get_dr_physp_set(
+  IN osm_log_t*           p_log,
+  IN osm_subn_t    const *p_subn,
+  IN osm_dr_path_t const *p_path,
+  OUT cl_map_t*           p_physp_map)
+{
+  osm_port_t  *p_port;
+  osm_physp_t *p_physp;
+  osm_node_t  *p_node;
+  uint8_t      hop;
+  cl_status_t  status = CL_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, __osm_physp_get_dr_physp_set );
+
+  /* find the OSM node */
+  p_port = osm_get_port_by_guid(p_subn, p_subn->sm_port_guid);
+  if (! p_port) 
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "__osm_physp_get_dr_nodes_set: ERR 4103: "
+             "Failed to find the SM own port by guid\n");
+    status = CL_ERROR;
+    goto Exit;
+  }
+
+  /* get the node of the SM */
+  p_node = osm_port_get_parent_node(p_port);
+  
+  /* 
+     traverse the path adding the nodes to the table 
+     start after the first dummy hop and stop just before the
+     last one
+  */
+  for (hop = 1; hop < p_path->hop_count - 1; hop++) 
+  {
+    /* go out using the phys port of the path */
+    p_physp = osm_node_get_physp_ptr(p_node, p_path->path[hop]);
+    
+    /* we track the ports we go out along the path */
+    if (hop > 1)
+      cl_map_insert(p_physp_map, __osm_ptr_to_key(p_physp), NULL);
+
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "__osm_physp_get_dr_nodes_set: "
+             "Traversed through node: 0x%016" PRIx64
+             " port:%u\n",
+             cl_ntoh64(p_node->node_info.node_guid),
+             p_path->path[hop]);
+
+    /* make sure we got a valid port and it has a remote port */
+    if (!(p_physp && osm_physp_is_valid( p_physp )))
+    {
+      osm_log( p_log, OSM_LOG_ERROR,
+               "__osm_physp_get_dr_nodes_set: ERR 4104: "
+               "DR Traversal stopped on invalid port at hop:%u\n",
+               hop);
+      status = CL_ERROR;
+      goto Exit;
+    }
+
+    if (! (p_physp = osm_physp_get_remote(p_physp))) 
+    {
+      osm_log( p_log, OSM_LOG_ERROR,
+               "__osm_physp_get_dr_nodes_set: ERR 4106: "
+               "DR Traversal stopped on missing remote physp at hop:%u\n",
+               hop);
+      status = CL_ERROR;
+      goto Exit;
+    }
+
+    p_node = osm_physp_get_node_ptr(p_physp);
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_physp_update_new_dr_path(
+  IN osm_physp_t const   *p_dest_physp,
+  IN cl_map_t            *p_visited_map,
+  IN osm_bind_handle_t   *h_bind )
+{
+  cl_list_t tmpPortsList;
+  osm_physp_t *p_physp, *p_src_physp = NULL;
+  uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX];
+  uint8_t i = 0;
+  osm_dr_path_t *p_dr_path;
+
+  cl_list_construct( &tmpPortsList );
+  cl_list_init( &tmpPortsList, 10 );
+
+  cl_list_insert_head( &tmpPortsList, p_dest_physp );
+  /* get the output port where we need to come from */
+  p_physp = (osm_physp_t*)cl_map_get( p_visited_map, 
+                                      __osm_ptr_to_key(p_dest_physp) );
+  while ( p_physp != NULL )
+  {
+    cl_list_insert_head( &tmpPortsList, p_physp );
+    /* get the input port through where we reached the output port */
+    p_src_physp = p_physp;
+    p_physp = (osm_physp_t*)cl_map_get( p_visited_map, 
+                                        __osm_ptr_to_key(p_physp) );
+    /* if we reached a null p_physp - this means we are at the begining
+       of the path. Break. */
+    if ( p_physp == NULL )
+      break;
+    /* get the output port */
+    p_physp = (osm_physp_t*)cl_map_get( p_visited_map, 
+                                        __osm_ptr_to_key(p_physp) );
+  }
+  
+  memset( path_array, 0, sizeof(path_array) );
+  p_physp = (osm_physp_t*)cl_list_remove_head( &tmpPortsList );
+  while ( p_physp != NULL )
+  {
+    i++;
+    path_array[i] = p_physp->port_num;
+    p_physp = (osm_physp_t*)cl_list_remove_head( &tmpPortsList );
+  }
+  if (p_src_physp)
+  {
+    p_dr_path = osm_physp_get_dr_path_ptr( p_src_physp );
+    osm_dr_path_init( p_dr_path, h_bind, i, path_array );
+  }
+
+  cl_list_destroy( &tmpPortsList );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_physp_replace_dr_path_with_alternate_dr_path(
+  IN osm_log_t           *p_log,
+  IN osm_subn_t  const   *p_subn,
+  IN osm_physp_t const   *p_dest_physp,
+  IN osm_bind_handle_t   *h_bind
+  )
+{
+  cl_map_t physp_map;
+  cl_map_t      visited_map;
+  osm_dr_path_t * p_dr_path;
+  cl_list_t     *p_currPortsList;
+  cl_list_t     *p_nextPortsList;
+  cl_qmap_t const     *p_port_tbl;
+  osm_port_t    *p_port;
+  osm_physp_t   *p_physp, *p_remote_physp;
+  ib_net64_t    port_guid;
+  boolean_t     next_list_is_full = TRUE, reached_dest = FALSE;
+  uint8_t       num_ports, port_num;
+
+  /* 
+     initialize the map of all port participating in current dr path
+     not including first and last switches
+   */
+  cl_map_construct( &physp_map );
+  cl_map_init( &physp_map, 4 );
+  cl_map_construct( &visited_map );
+  cl_map_init( &visited_map, 4 );
+  p_dr_path = osm_physp_get_dr_path_ptr( p_dest_physp );
+  __osm_physp_get_dr_physp_set(p_log, p_subn, p_dr_path, &physp_map);
+
+  /* 
+     BFS from OSM port until we find the target physp but avoid 
+     going through mapped ports
+  */
+  p_nextPortsList = (cl_list_t*)malloc(sizeof(cl_list_t));
+  cl_list_construct( p_nextPortsList );
+  cl_list_init( p_nextPortsList, 10 );
+
+  p_port_tbl = &p_subn->port_guid_tbl;
+  port_guid = p_subn->sm_port_guid;
+
+  CL_ASSERT( port_guid );
+
+  p_port = (osm_port_t*)cl_qmap_get( p_port_tbl, port_guid );
+
+  if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_physp_replace_dr_path_with_alternate_dr_path: ERR 4105: "
+             "No SM port object\n" );
+    goto Exit;
+  }
+  
+  /* 
+     HACK: We are assuming SM is running on HCA, so when getting the default
+     port we'll get the port connected to the rest of the subnet. If SM is
+     running on SWITCH - we should try to get a dr path from all switch ports.
+  */
+  p_physp = osm_port_get_default_phys_ptr( p_port );
+
+  CL_ASSERT( p_physp );
+  CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+  cl_list_insert_tail( p_nextPortsList, p_physp );
+  
+  while (next_list_is_full == TRUE) 
+  {
+    next_list_is_full = FALSE;
+    p_currPortsList = p_nextPortsList;
+    p_nextPortsList = (cl_list_t*)malloc(sizeof(cl_list_t));
+    cl_list_construct( p_nextPortsList );
+    cl_list_init( p_nextPortsList, 10 );
+    p_physp = (osm_physp_t*)cl_list_remove_head( p_currPortsList );
+    while ( p_physp != NULL )
+    {
+      /* If we are in a switch - need to go out through all the other
+         physical ports of the switch */
+      num_ports = osm_node_get_num_physp( p_physp->p_node );
+      
+      for (port_num = 1 ; port_num < num_ports ; port_num++)
+      {
+        if (osm_node_get_type( p_physp->p_node ) == IB_NODE_TYPE_SWITCH)
+          p_remote_physp = osm_node_get_physp_ptr( p_physp->p_node, port_num );
+        else
+          /* this is HCA or router - the remote port is just the port connected
+             on the other side */
+          p_remote_physp = p_physp->p_remote_physp;
+
+        /* 
+           make sure that all of the following occurred:
+           1. The port isn't NULL
+           2. The port is a valid port
+           3. This is not the port we came from
+           4. The port is not in the physp_map
+           5. This port haven't been visited before
+        */
+        if ( p_remote_physp &&
+             osm_physp_is_valid ( p_remote_physp ) &&
+             p_remote_physp != p_physp &&
+             cl_map_get( &physp_map, __osm_ptr_to_key(p_remote_physp)) == NULL &&
+             cl_map_get( &visited_map, __osm_ptr_to_key(p_remote_physp)) == NULL )
+        {
+          /* Insert the port into the visited_map, and save its source port */
+          cl_map_insert( &visited_map, __osm_ptr_to_key(p_remote_physp), p_physp );
+          
+          /* Is this the p_dest_physp? */
+          if ( p_remote_physp == p_dest_physp )
+          {
+            /* update the new dr path */
+            __osm_physp_update_new_dr_path( p_dest_physp, &visited_map, h_bind );
+            reached_dest = TRUE;
+            break;
+          }
+          
+          /* add the p_remote_physp to the nextPortsList */
+          cl_list_insert_tail( p_nextPortsList, p_remote_physp );
+          next_list_is_full = TRUE;
+        }
+      }
+
+      p_physp = (osm_physp_t*)cl_list_remove_head( p_currPortsList );
+      if ( reached_dest == TRUE )
+      {
+        /* free the rest of the currPortsList */
+        while ( p_physp != NULL )
+          p_physp = (osm_physp_t*)cl_list_remove_head( p_currPortsList );
+        /* free the nextPortsList, if items were added to it */
+        p_physp = (osm_physp_t*)cl_list_remove_head( p_nextPortsList );
+        while ( p_physp != NULL )
+          p_physp = (osm_physp_t*)cl_list_remove_head( p_nextPortsList );
+        next_list_is_full = FALSE;
+      }
+    }
+    cl_list_destroy( p_currPortsList );
+    free(p_currPortsList);
+  }
+
+  /* cleanup */
+ Exit:
+  cl_list_destroy( p_nextPortsList );
+  free( p_nextPortsList );
+  cl_map_destroy( &physp_map );
+  cl_map_destroy( &visited_map );
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_link_is_healthy(
+  IN const osm_physp_t* const p_physp )
+{
+  osm_physp_t* p_remote_physp;
+  CL_ASSERT( p_physp );
+  p_remote_physp = p_physp->p_remote_physp;
+  if (p_remote_physp != NULL && osm_physp_is_valid(p_remote_physp) )
+    return( (p_physp->healthy)&(p_remote_physp->healthy) );
+  /* the other side is not known - consider the link as healthy */
+  return(TRUE);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_physp_set_pkey_tbl(
+  IN osm_log_t* p_log,
+  IN const osm_subn_t* p_subn,
+  IN osm_physp_t* const p_physp,
+  IN ib_pkey_table_t *p_pkey_tbl,
+  IN uint16_t block_num ) 
+{
+  uint16_t max_blocks;
+
+  CL_ASSERT( p_pkey_tbl );
+  CL_ASSERT( osm_physp_is_valid( p_physp ) );
+  /*
+    (14.2.5.7) - the block number valid values are 0-2047, and are further
+    limited by the size of the P_Key table specified by the PartitionCap on the 
+    node.
+  */
+  if (!p_physp->p_node->sw || p_physp->port_num == 0 )
+  {
+    /* 
+       The maximum blocks is defined in the node info: partition cap for CA,
+       routers and switch management ports.
+    */
+    max_blocks = (cl_ntoh16(p_physp->p_node->node_info.partition_cap) +
+                  IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1) 
+      / IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
+  }
+  else
+  {
+    /*
+      This is a switch, and not a management port. The maximum blocks is defined
+      in the switch info: partition enforcement cap.
+    */
+    max_blocks = 
+      (cl_ntoh16(p_physp->p_node->sw->switch_info.enforce_cap) +
+       IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1) / IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
+  }
+
+  if ( block_num >= max_blocks )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_physp_set_pkey_tbl: ERR 4108: "
+             "Got illegal set for block number:%u "
+             "For GUID: %" PRIx64 " port number:0x%X\n",
+             block_num,
+             cl_ntoh64(p_physp->p_node->node_info.node_guid),
+             p_physp->port_num );
+    return;
+  }
+  
+  osm_pkey_tbl_set( &p_physp->pkeys, block_num, p_pkey_tbl);
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_port_info_rcv.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_port_info_rcv.c
new file mode 100644 (file)
index 0000000..bdf1b61
--- /dev/null
@@ -0,0 +1,870 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_port_info_rcv.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_pi_rcv_t.
+ * This object represents the PortInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.8 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_port_info_rcv.h>
+#include <opensm/osm_node_info_rcv.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_helper.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_remote_sm.h>
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pi_rcv_set_sm(
+  IN const osm_pi_rcv_t* const p_rcv,
+  IN osm_physp_t* const p_physp )
+{
+  osm_bind_handle_t h_bind;
+  osm_dr_path_t *p_dr_path;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_set_sm );
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_pi_rcv_set_sm: "
+             "Setting 'IS_SM' bit in port attributes\n" );
+  }
+
+  p_dr_path = osm_physp_get_dr_path_ptr( p_physp );
+  h_bind = osm_dr_path_get_bind_handle( p_dr_path );
+  /*
+    The 'IS_SM' bit isn't already set, so set it.
+  */
+  osm_vendor_set_sm( h_bind, TRUE );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pi_rcv_process_endport(
+  IN const osm_pi_rcv_t* const p_rcv,
+  IN osm_physp_t* const p_physp,
+  IN const ib_port_info_t* const p_pi )
+{
+  osm_madw_context_t context;
+  ib_api_status_t    status;
+  ib_net64_t         port_guid;
+  uint8_t            rate, mtu;
+  cl_qmap_t*         p_sm_tbl;
+  osm_remote_sm_t*   p_sm;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_process_endport );
+
+  port_guid = osm_physp_get_port_guid( p_physp );
+
+  /* HACK extended port 0 should be handled too! */
+  if (osm_physp_get_port_num( p_physp ) != 0)
+  {
+    /* track the minimal endport MTU and rate */
+    mtu = ib_port_info_get_mtu_cap(p_pi);
+    if (mtu < p_rcv->p_subn->min_ca_mtu)
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+               "__osm_pi_rcv_process_endport: "
+               "Setting endport minimal MTU to:%u defined by port:0x%" 
+               PRIx64 "\n",
+               mtu,
+               cl_ntoh64( port_guid ) );
+      p_rcv->p_subn->min_ca_mtu = mtu;
+    }
+    
+    rate = ib_port_info_compute_rate( p_pi );
+    if (rate < p_rcv->p_subn->min_ca_rate)
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+               "__osm_pi_rcv_process_endport: "
+               "Setting endport minimal rate to:%u defined by port:0x%" 
+               PRIx64 "\n",
+               rate,
+               cl_ntoh64( port_guid ) );
+      p_rcv->p_subn->min_ca_rate = rate;
+    }
+  }
+
+  if( port_guid == p_rcv->p_subn->sm_port_guid )
+  {
+    /*
+      We received the PortInfo for our own port.
+    */
+    if( !(p_pi->capability_mask & IB_PORT_CAP_IS_SM ) )
+    {
+      /*
+        Set the IS_SM bit to indicate our port hosts an SM.
+      */
+      __osm_pi_rcv_set_sm( p_rcv, p_physp );
+    }
+  }
+  else
+  {
+    /*
+       Before querying the SM - we want to make sure we clean its state, so
+       if the querying fails we recognize that this SM is not active.
+    */
+    p_sm_tbl = &p_rcv->p_subn->sm_guid_tbl;
+    p_sm = (osm_remote_sm_t*)cl_qmap_get( p_sm_tbl, port_guid );
+    if( p_sm != (osm_remote_sm_t*)cl_qmap_end( p_sm_tbl ) )
+    {
+      /* clean it up */
+      p_sm->smi.pri_state = 0xF0 & p_sm->smi.pri_state;
+    }
+
+    if( p_pi->capability_mask & IB_PORT_CAP_IS_SM )
+    {
+      if( p_rcv->p_subn->opt.ignore_other_sm )
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+                 "__osm_pi_rcv_process_endport: "
+                 "Ignoring SM on port 0x%" PRIx64 "\n",
+                 cl_ntoh64( port_guid ) );
+      }
+      else
+      {
+        if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+        {
+          osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+                   "__osm_pi_rcv_process_endport: "
+                   "Detected another SM. Requesting SMInfo"
+                   "\n\t\t\t\tPort 0x%" PRIx64 "\n",
+                   cl_ntoh64( port_guid ) );
+        }
+
+        /*
+          This port indicates it's an SM and it's not our own port.
+          Acquire the SMInfo Attribute.
+        */
+        memset( &context, 0, sizeof(context) );
+        context.smi_context.set_method = FALSE;
+        status = osm_req_get( p_rcv->p_req,
+                              osm_physp_get_dr_path_ptr( p_physp ),
+                              IB_MAD_ATTR_SM_INFO,
+                              0,
+                              CL_DISP_MSGID_NONE,
+                              &context );
+
+        if( status != IB_SUCCESS )
+        {
+          osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                   "__osm_pi_rcv_process_endport: ERR 0F05: "
+                   "Failure requesting SMInfo (%s)\n",
+                   ib_get_err_str( status ) );
+        }
+      }
+    }
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_pi_rcv_process_switch_port(
+  IN const osm_pi_rcv_t* const p_rcv,
+  IN osm_node_t* const p_node,
+  IN osm_physp_t* const p_physp,
+  IN const ib_port_info_t* const p_pi )
+{
+  ib_api_status_t status = IB_SUCCESS;
+  osm_madw_context_t context;
+  osm_physp_t *p_remote_physp;
+  osm_node_t *p_remote_node;
+  ib_net16_t orig_lid;
+  uint8_t port_num;
+  uint8_t remote_port_num;
+  osm_dr_path_t path;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_process_switch_port );
+
+  /*
+    Check the state of the physical port.
+    If there appears to be something on the other end of the wire,
+    then ask for NodeInfo.  Ignore the switch management port.
+  */
+  port_num = osm_physp_get_port_num( p_physp );
+  /* if in_sweep_hop_0 is TRUE, then this means the SM in on the switch,
+     and we got switchInfo of our local switch. Do not continue
+     probing through the switch. */
+  if( port_num != 0 && p_rcv->p_subn->in_sweep_hop_0 == FALSE)
+  {
+    switch( ib_port_info_get_port_state( p_pi ) )
+    {
+    case IB_LINK_DOWN:
+      p_remote_physp = osm_physp_get_remote( p_physp );
+      if( p_remote_physp && osm_physp_is_valid( p_remote_physp ) )
+      {
+        p_remote_node = osm_physp_get_node_ptr( p_remote_physp );
+        remote_port_num = osm_physp_get_port_num( p_remote_physp );
+
+        osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+                 "__osm_pi_rcv_process_switch_port: "
+                 "Unlinking local node 0x%" PRIx64 ", port 0x%X"
+                 "\n\t\t\t\tand remote node 0x%" PRIx64
+                 ", port 0x%X\n",
+                 cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+                 port_num,
+                 cl_ntoh64( osm_node_get_node_guid( p_remote_node ) ),
+                 remote_port_num );
+
+        osm_node_unlink( p_node, (uint8_t)port_num,
+                         p_remote_node, (uint8_t)remote_port_num );
+
+      }
+      break;
+
+    case IB_LINK_INIT:
+    case IB_LINK_ARMED:
+    case IB_LINK_ACTIVE:
+      /*
+        To avoid looping forever, only probe the port if it
+        is NOT the port that responded to the SMP.
+
+        Request node info from the other end of this link:
+        1) Copy the current path from the parent node.
+        2) Extend the path to the next hop thru this port.
+        3) Request node info with the new path
+        
+      */
+      if( p_pi->local_port_num != osm_physp_get_port_num( p_physp ) )
+      {
+        path = *osm_physp_get_dr_path_ptr( p_physp );
+
+        osm_dr_path_extend( &path, osm_physp_get_port_num( p_physp ) );
+
+        context.ni_context.node_guid = osm_node_get_node_guid( p_node );
+        context.ni_context.port_num = osm_physp_get_port_num( p_physp );
+
+        status = osm_req_get( p_rcv->p_req,
+                              &path,
+                              IB_MAD_ATTR_NODE_INFO,
+                              0,
+                              CL_DISP_MSGID_NONE,
+                              &context );
+
+        if( status != IB_SUCCESS )
+        {
+          osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                   "__osm_pi_rcv_process_switch_port: ERR 0F02: "
+                   "Failure initiating NodeInfo request (%s)\n",
+                   ib_get_err_str(status) );
+        }
+      }
+      else
+      {
+        if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+        {
+          osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+                   "__osm_pi_rcv_process_switch_port: "
+                   "Skipping SMP responder port 0x%X\n",
+                   p_pi->local_port_num );
+        }
+      }
+      break;
+
+    default:
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_pi_rcv_process_switch_port: ERR 0F03: "
+               "Unknown link state = %u, port = 0x%X\n",
+               ib_port_info_get_port_state( p_pi ),
+               p_pi->local_port_num );
+      break;
+    }
+  }
+
+  /*
+    Update the PortInfo attribute.
+  */
+  osm_physp_set_port_info( p_physp, p_pi );
+
+  if (port_num == 0)
+  {
+       /* This is switch management port 0 */
+       if ( ( orig_lid = osm_physp_trim_base_lid_to_valid_range( p_physp ) ) )
+               osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                        "__osm_pi_rcv_process_switch_port: ERR 0F04: "
+                        "Invalid base LID 0x%x corrected\n",
+                        cl_ntoh16( orig_lid ) );
+       /* Determine if base switch port 0 */
+       if (p_node->sw &&
+           !ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info))
+        {
+               /* PortState is not used on BSP0 but just in case it is DOWN */
+               p_physp->port_info = *p_pi;
+        }
+       __osm_pi_rcv_process_endport(p_rcv, p_physp, p_pi);
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pi_rcv_process_ca_port(
+  IN const osm_pi_rcv_t* const p_rcv,
+  IN osm_node_t* const p_node,
+  IN osm_physp_t* const p_physp,
+  IN const ib_port_info_t* const p_pi )
+{
+  ib_net16_t orig_lid;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_process_ca_port );
+
+  UNUSED_PARAM( p_node );
+
+  osm_physp_set_port_info( p_physp, p_pi );
+
+  if ( (orig_lid = osm_physp_trim_base_lid_to_valid_range( p_physp ) ) )
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+            "__osm_pi_rcv_process_ca_port: ERR 0F08: "
+            "Invalid base LID 0x%x corrected\n",
+            cl_ntoh16 ( orig_lid ) );
+
+  __osm_pi_rcv_process_endport(p_rcv, p_physp, p_pi);
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pi_rcv_process_router_port(
+  IN const osm_pi_rcv_t* const p_rcv,
+  IN osm_node_t* const p_node,
+  IN osm_physp_t* const p_physp,
+  IN const ib_port_info_t* const p_pi )
+{
+  ib_net16_t orig_lid;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_process_router_port );
+
+  UNUSED_PARAM( p_node );
+
+  /*
+    Update the PortInfo attribute.
+  */
+  osm_physp_set_port_info( p_physp, p_pi );
+
+  if ( (orig_lid = osm_physp_trim_base_lid_to_valid_range( p_physp ) ) )
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+            "__osm_pi_rcv_process_router_port: ERR 0F09: "
+            "Invalid base LID 0x%x corrected\n",
+            cl_ntoh16 ( orig_lid) );
+
+  __osm_pi_rcv_process_endport(p_rcv, p_physp, p_pi);
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+#define IBM_VENDOR_ID  (0x5076)
+/**********************************************************************
+ **********************************************************************/
+void osm_pkey_get_tables(
+  IN osm_log_t         *p_log,
+  IN osm_req_t         *p_req,
+  IN osm_subn_t* const  p_subn,
+  IN osm_node_t* const  p_node,
+  IN osm_physp_t* const p_physp ) {
+
+  osm_madw_context_t context;
+  ib_api_status_t status;
+  osm_dr_path_t path;
+  uint8_t  port_num;
+  uint16_t block_num, max_blocks;
+  uint32_t attr_mod_ho;
+
+  OSM_LOG_ENTER( p_log, osm_pkey_get_tables );
+
+  path = *osm_physp_get_dr_path_ptr( p_physp );
+
+  context.pkey_context.node_guid =
+    osm_node_get_node_guid( p_node );
+  context.pkey_context.port_guid =
+    osm_physp_get_port_guid( p_physp );
+  context.pkey_context.set_method = FALSE;
+
+  port_num = p_physp->port_num;
+
+  if (!p_node->sw || port_num == 0)
+  {
+    /* The maximum blocks is defined by the node info partition cap for CA,
+       router, and switch management ports. */
+    max_blocks = (cl_ntoh16(p_node->node_info.partition_cap)+IB_NUM_PKEY_ELEMENTS_IN_BLOCK -1)
+      / IB_NUM_PKEY_ELEMENTS_IN_BLOCK ;
+  }
+  else
+  {
+    /* This is a switch, and not a management port. The maximum blocks
+       is defined in the switch info partition enforcement cap. */
+
+    /* Check for IBM eHCA firmware defect in reporting partition enforcement cap */
+    if (cl_ntoh32(ib_node_info_get_vendor_id(&p_node->node_info)) == IBM_VENDOR_ID)
+      p_node->sw->switch_info.enforce_cap = 0;
+
+    /* Bail out if this is a switch with no partition enforcement capability */
+    if (cl_ntoh16(p_node->sw->switch_info.enforce_cap) == 0)
+      goto Exit;
+
+    max_blocks = (cl_ntoh16(p_node->sw->switch_info.enforce_cap) +
+                  IB_NUM_PKEY_ELEMENTS_IN_BLOCK -1) / IB_NUM_PKEY_ELEMENTS_IN_BLOCK ;
+  }
+
+  for (block_num = 0 ; block_num < max_blocks  ; block_num++)
+  {
+    if (osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH)
+      attr_mod_ho = block_num;
+    else
+      attr_mod_ho = block_num | (port_num << 16);
+    status = osm_req_get( p_req,
+                          &path,
+                          IB_MAD_ATTR_P_KEY_TABLE,
+                          cl_hton32(attr_mod_ho),
+                          CL_DISP_MSGID_NONE,
+                          &context );
+
+    if( status != IB_SUCCESS )
+    {
+      osm_log( p_log, OSM_LOG_ERROR,
+               "osm_physp_has_pkey: ERR 0F12: "
+               "Failure initiating PKeyTable request (%s)\n",
+               ib_get_err_str(status));
+      goto Exit;
+    }
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pi_rcv_get_pkey_slvl_vla_tables(
+  IN const osm_pi_rcv_t* const p_rcv,
+  IN osm_node_t* const p_node,
+  IN osm_physp_t* const p_physp )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_get_pkey_slvl_vla_tables );
+
+  osm_pkey_get_tables( p_rcv->p_log, p_rcv->p_req, p_rcv->p_subn,
+                       p_node, p_physp );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pi_rcv_construct(
+  IN osm_pi_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pi_rcv_destroy(
+  IN osm_pi_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_pi_rcv_destroy );
+
+  CL_ASSERT( p_rcv );
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pi_rcv_init(
+  IN osm_pi_rcv_t* const p_rcv,
+  IN osm_req_t* const p_req,
+  IN osm_subn_t* const p_subn,
+  IN osm_log_t* const p_log,
+  IN osm_state_mgr_t* const p_state_mgr,
+  IN cl_plock_t* const p_lock )
+{
+  ib_api_status_t status = IB_SUCCESS;
+  OSM_LOG_ENTER( p_log, osm_pi_rcv_init );
+
+  osm_pi_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_req = p_req;
+  p_rcv->p_state_mgr = p_state_mgr;
+
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pi_rcv_process_set(
+  IN const osm_pi_rcv_t* const p_rcv,
+  IN osm_port_t* const p_port,
+  IN const uint8_t port_num,
+  IN osm_madw_t* const p_madw )
+{
+  osm_physp_t *p_physp;
+  osm_node_t *p_node;
+  ib_net64_t port_guid;
+  ib_smp_t *p_smp;
+  ib_port_info_t *p_pi;
+  osm_pi_context_t *p_context;
+  osm_log_level_t level;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_pi_rcv_process_set );
+
+  p_context = osm_madw_get_pi_context_ptr( p_madw );
+
+  p_physp = osm_port_get_phys_ptr( p_port, port_num );
+  CL_ASSERT( p_physp );
+  CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+  port_guid = osm_physp_get_port_guid( p_physp );
+  p_node = osm_port_get_parent_node( p_port );
+  CL_ASSERT( p_node );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+  p_pi = (ib_port_info_t*)ib_smp_get_payload_ptr( p_smp );
+
+  /* check for error */
+  if (!p_context->ignore_errors && (cl_ntoh16(p_smp->status) & 0x7fff))
+  {
+    /* If port already ACTIVE, don't treat status 7 as error */
+    if (p_context->active_transition &&
+       (cl_ntoh16(p_smp->status) & 0x7fff) == 0x1c)
+    {
+      level = OSM_LOG_INFO;
+      osm_log( p_rcv->p_log, OSM_LOG_INFO,
+               "osm_pi_rcv_process_set: "
+               "Received error status 0x%x for SetResp() during ACTIVE transition\n",
+               cl_ntoh16(p_smp->status) & 0x7fff);
+      /* Should there be a subsequent Get to validate that port is ACTIVE ? */
+    }
+    else
+    {
+      level = OSM_LOG_ERROR;
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_pi_rcv_process_set: ERR 0F10: "
+               "Received error status for SetResp()\n");
+    }
+    osm_dump_port_info(
+      p_rcv->p_log,
+      osm_node_get_node_guid( p_node ),
+      port_guid,
+      port_num,
+      p_pi,
+      level);
+  }
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "osm_pi_rcv_process_set: "
+             "Received logical SetResp() for GUID 0x%" PRIx64
+             ", port num 0x%X"
+             "\n\t\t\t\tfor parent node GUID 0x%" PRIx64
+             " TID 0x%" PRIx64 "\n",
+             cl_ntoh64( port_guid ),
+             port_num,
+             cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+             cl_ntoh64( p_smp->trans_id ) );
+  }
+
+  osm_physp_set_port_info( p_physp, p_pi );
+
+  /* We got a PortInfoSetResp - set the got_set_resp flag to TRUE */
+  p_physp->got_set_resp = TRUE;
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pi_rcv_process(
+  IN const osm_pi_rcv_t* const p_rcv,
+  IN osm_madw_t* const p_madw )
+{
+  cl_qmap_t *p_guid_tbl;
+  ib_port_info_t *p_pi;
+  ib_smp_t *p_smp;
+  osm_port_t *p_port;
+  osm_physp_t *p_physp;
+  osm_dr_path_t *p_dr_path;
+  osm_node_t *p_node;
+  osm_pi_context_t *p_context;
+  ib_net64_t port_guid;
+  ib_net64_t node_guid;
+  uint8_t port_num;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_pi_rcv_process );
+
+  CL_ASSERT( p_rcv );
+  CL_ASSERT( p_madw );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+  p_context = osm_madw_get_pi_context_ptr( p_madw );
+  p_pi = (ib_port_info_t*)ib_smp_get_payload_ptr( p_smp );
+
+  CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_PORT_INFO );
+
+  /* On receipt of client reregister, clear the reregister bit so
+     reregistering won't be sent again and again */
+  if ( ib_port_info_get_client_rereg( p_pi ) )
+  {
+       osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+                 "osm_pi_rcv_process: "
+                 "Client reregister received on response\n");
+       ib_port_info_set_client_rereg( p_pi, 0 );
+  }
+
+  port_num = (uint8_t)cl_ntoh32( p_smp->attr_mod );
+
+  port_guid = p_context->port_guid;
+  node_guid = p_context->node_guid;
+
+  osm_dump_port_info( p_rcv->p_log,
+                      node_guid, port_guid, port_num, p_pi,
+                      OSM_LOG_DEBUG );
+
+  /* 
+     we might get a response during a light sweep looking for a change in 
+     the status of a remote port that did not respond in earlier sweeps.
+     So if the context of the Get was light_sweep - we do not need to 
+     do anything with the response - just flag that we need a heavy sweep
+  */
+  if (p_context->light_sweep == TRUE) 
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "osm_pi_rcv_process: "
+             "Got light sweep response from remote port of parent node "
+             "GUID 0x%" PRIx64 " port 0x%016" PRIx64
+             ", Commencing heavy sweep\n",
+             cl_ntoh64( node_guid ),
+             cl_ntoh64( port_guid ) );
+    osm_state_mgr_process( p_rcv->p_state_mgr,
+                           OSM_SIGNAL_CHANGE_DETECTED );
+    goto Exit;
+  }
+  
+  p_guid_tbl = &p_rcv->p_subn->port_guid_tbl;
+  CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
+  p_port = (osm_port_t*)cl_qmap_get( p_guid_tbl, port_guid );
+
+  if( p_port == (osm_port_t*)cl_qmap_end( p_guid_tbl) )
+  {
+    CL_PLOCK_RELEASE( p_rcv->p_lock );
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_pi_rcv_process: ERR 0F06: "
+             "No port object for port with GUID 0x%" PRIx64
+             "\n\t\t\t\tfor parent node GUID 0x%" PRIx64
+             ", TID 0x%" PRIx64 "\n",
+             cl_ntoh64( port_guid ),
+             cl_ntoh64( node_guid ),
+             cl_ntoh64( p_smp->trans_id ) );
+    goto Exit;
+  }
+
+  /*
+    If we were setting the PortInfo, then receiving
+    this attribute was not part of sweeping the subnet.
+    In this case, just update the PortInfo attribute.
+
+    In an unfortunate blunder, the IB spec defines the
+    return method for Set() as a GetResp().  Thus, we can't
+    use the method (what would have been SetResp()) to determine
+    our course of action.  So, we have to carry this extra
+    boolean around to determine if we were doing Get() or Set().
+  */
+  if( p_context->set_method )
+  {
+    osm_pi_rcv_process_set( p_rcv, p_port, port_num, p_madw );
+  }
+  else
+  {
+    osm_port_discovery_count_inc( p_port );
+
+    /*
+      This PortInfo arrived because we did a Get() method,
+      most likely due to a subnet sweep in progress.
+    */
+    if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+               "osm_pi_rcv_process: "
+               "Discovered port num 0x%X with GUID 0x%" PRIx64
+               " for parent node GUID 0x%" PRIx64
+               ", TID 0x%" PRIx64 "\n",
+               port_num,
+               cl_ntoh64( port_guid ),
+               cl_ntoh64( node_guid ),
+               cl_ntoh64( p_smp->trans_id ) );
+    }
+
+    p_node = osm_port_get_parent_node( p_port );
+    p_physp = osm_node_get_physp_ptr( p_node, port_num );
+
+    CL_ASSERT( p_node );
+    CL_ASSERT( p_physp );
+
+    /*
+      Determine if we encountered a new Physical Port.
+      If so, initialize the new Physical Port then
+      continue processing as normal.
+    */
+    if( !osm_physp_is_valid( p_physp ) )
+    {
+      if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+                 "osm_pi_rcv_process: "
+                 "Initializing port number 0x%X\n",
+                 port_num );
+      }
+
+      osm_physp_init( p_physp,
+                      port_guid,
+                      port_num,
+                      p_node,
+                      osm_madw_get_bind_handle( p_madw ),
+                      p_smp->hop_count,
+                      p_smp->initial_path );
+
+      osm_port_add_new_physp( p_port, port_num );
+    }
+    else
+    {
+      /*
+        Update the directed route path to this port
+        in case the old path is no longer usable.
+      */
+      p_dr_path = osm_physp_get_dr_path_ptr( p_physp );
+      osm_dr_path_init( p_dr_path,
+                        osm_madw_get_bind_handle( p_madw ),
+                        p_smp->hop_count, p_smp->initial_path );
+    }
+
+    /*
+      Check if the update_sm_base_lid in the context is TRUE.
+      If it is - then update the master_sm_base_lid of the variable
+      in the subnet.
+    */
+    if (p_context->update_master_sm_base_lid == TRUE)
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+               "osm_pi_rcv_process: "
+               "update_master_sm is TRUE. "
+               "Updating master_sm_base_lid to:%u\n",
+               p_pi->master_sm_base_lid );
+
+      p_rcv->p_subn->master_sm_base_lid = p_pi->master_sm_base_lid;
+    }
+
+    switch( osm_node_get_type( p_node ) )
+    {
+    case IB_NODE_TYPE_CA:
+      __osm_pi_rcv_process_ca_port( p_rcv,
+                                    p_node, p_physp, p_pi );
+      break;
+    case IB_NODE_TYPE_ROUTER:
+      __osm_pi_rcv_process_router_port( p_rcv,
+                                        p_node, p_physp, p_pi );
+      break;
+    case IB_NODE_TYPE_SWITCH:
+      __osm_pi_rcv_process_switch_port( p_rcv,
+                                        p_node, p_physp, p_pi );
+      break;
+    default:
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_pi_rcv_process: ERR 0F07: "
+               "Unknown node type %u with GUID 0x%" PRIx64 "\n",
+               osm_node_get_type( p_node ),
+               cl_ntoh64( node_guid ) );
+      break;
+    }
+
+    /*
+      Get the tables on the physp.
+    */
+    __osm_pi_rcv_get_pkey_slvl_vla_tables( p_rcv, p_node, p_physp );
+
+  }
+
+  CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+ Exit:
+  /*
+    Release the lock before jumping here!!
+  */
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_port_info_rcv_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_port_info_rcv_ctrl.c
new file mode 100644 (file)
index 0000000..ff60905
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_port_info_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_pi_rcv_ctrl_t.
+ * This object represents the PortInfo request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_port_info_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_pi_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_pi_rcv_process( ((osm_pi_rcv_ctrl_t*)context)->p_rcv,
+                      (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pi_rcv_ctrl_construct(
+  IN osm_pi_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pi_rcv_ctrl_destroy(
+  IN osm_pi_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pi_rcv_ctrl_init(
+  IN osm_pi_rcv_ctrl_t* const p_ctrl,
+  IN osm_pi_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_pi_rcv_ctrl_init );
+
+  osm_pi_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_PORT_INFO,
+    __osm_pi_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_pi_rcv_ctrl_init: ERR 1001: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_prtn.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_prtn.c
new file mode 100644 (file)
index 0000000..4440553
--- /dev/null
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_prtn_t.
+ * This object represents an IBA partition.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision$
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_partition.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_sa.h>
+#include <opensm/osm_multicast.h>
+
+extern int osm_prtn_config_parse_file(osm_log_t * const p_log,
+                                     osm_subn_t * const p_subn,
+                                     const char *file_name);
+
+static uint16_t global_pkey_counter;
+
+osm_prtn_t* osm_prtn_new(
+       IN const char *name,
+       IN const uint16_t pkey )
+{
+       osm_prtn_t *p = malloc(sizeof(*p));
+       if (!p)
+               return NULL;
+
+       memset(p, 0, sizeof(*p));
+       p->pkey = pkey;
+       p->sl = OSM_DEFAULT_SL;
+       cl_map_construct(&p->full_guid_tbl);
+       cl_map_init(&p->full_guid_tbl, 32);
+       cl_map_construct(&p->part_guid_tbl);
+       cl_map_init(&p->part_guid_tbl, 32);
+
+       if (name && *name)
+               strncpy(p->name, name, sizeof(p->name));
+       else
+               snprintf(p->name, sizeof(p->name), "%04x", cl_ntoh16(pkey));
+
+       return p;
+}
+
+void osm_prtn_delete(
+       IN OUT osm_prtn_t** const pp_prtn )
+{
+       osm_prtn_t *p = *pp_prtn;
+
+       cl_map_remove_all(&p->full_guid_tbl);
+       cl_map_destroy(&p->full_guid_tbl);
+       cl_map_remove_all(&p->part_guid_tbl);
+       cl_map_destroy(&p->part_guid_tbl);
+       free(p);
+       *pp_prtn = NULL;
+}
+
+ib_api_status_t osm_prtn_add_port(osm_log_t *p_log, osm_subn_t *p_subn,
+                                 osm_prtn_t *p, ib_net64_t guid, boolean_t full)
+{
+       cl_qmap_t *p_port_tbl = &p_subn->port_guid_tbl;
+       ib_api_status_t status = IB_SUCCESS;
+       cl_map_t *p_tbl;
+       osm_port_t *p_port;
+       osm_physp_t *p_physp;
+
+       p_port = (osm_port_t *)cl_qmap_get(p_port_tbl, guid);
+       if (!p_port || p_port == (osm_port_t *)cl_qmap_end(p_port_tbl)) {
+               osm_log(p_log, OSM_LOG_VERBOSE, "osm_prtn_add_port: "
+                       "port 0x%" PRIx64 " not found\n",
+                       cl_ntoh64(guid));
+               return status;
+       }
+
+       p_physp = osm_port_get_default_phys_ptr(p_port);
+       if (!p_physp) {
+               osm_log(p_log, OSM_LOG_VERBOSE, "osm_prtn_add_port: "
+                       "no physical for port 0x%" PRIx64 "\n",
+                       cl_ntoh64(guid));
+               return status;
+       }
+
+       if (cl_map_remove(&p->part_guid_tbl, guid) ||
+           cl_map_remove(&p->full_guid_tbl, guid)) {
+               osm_log(p_log, OSM_LOG_VERBOSE, "osm_prtn_add_port: "
+                       "port 0x%" PRIx64 " already in "
+                       "partition \'%s\' (0x%04x). Will overwrite\n",
+                       cl_ntoh64(guid), p->name, cl_ntoh16(p->pkey));
+       }
+
+       p_tbl = (full == TRUE) ? &p->full_guid_tbl : &p->part_guid_tbl ;
+
+       if (cl_map_insert(p_tbl, guid, p_physp) == NULL)
+               return IB_INSUFFICIENT_MEMORY;
+
+       return status;
+}
+
+ib_api_status_t osm_prtn_add_all(osm_log_t *p_log, osm_subn_t *p_subn,
+                                osm_prtn_t *p, boolean_t full)
+{
+       cl_qmap_t *p_port_tbl = &p_subn->port_guid_tbl;
+       cl_map_item_t *p_item;
+       osm_port_t *p_port;
+       ib_api_status_t status = IB_SUCCESS;
+
+       p_item = cl_qmap_head(p_port_tbl);
+       while (p_item != cl_qmap_end(p_port_tbl)) {
+               p_port = (osm_port_t *)p_item;
+               p_item = cl_qmap_next(p_item);
+               status = osm_prtn_add_port(p_log, p_subn, p,
+                                          osm_port_get_guid(p_port), full);
+               if (status != IB_SUCCESS)
+                       goto _err;
+       }
+
+  _err:
+       return status;
+}
+
+static const ib_gid_t osm_ipoib_mgid = {
+  {
+    0xff,                           /*  multicast field */
+    0x12,                           /*  non-permanent bit, link local scope */
+    0x40, 0x1b,                     /*  IPv4 signature */
+    0xff, 0xff,                     /*  16 bits of P_Key (to be filled in) */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   /*  48 bits of zeros */
+    0xff, 0xff, 0xff, 0xff,            /*  32 bit IPv4 broadcast address */
+  },
+};
+
+/*
+ * HACK: Until TS resolves their noncompliant join compmask,
+ * we have to pre-define the MGID
+ */
+static const ib_gid_t osm_ts_ipoib_mgid = {
+  {
+    0xff,                           /*  multicast field */
+    0x12,                           /*  non-permanent bit, link local scope */
+    0x40, 0x1b,                     /*  IPv4 signature */
+    0xff, 0xff,                     /*  16 bits of P_Key (to be filled in) */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   /*  48 bits of zeros */
+    0x00, 0x00, 0x00, 0x01,            /*  32 bit IPv4 broadcast address */
+  },
+};
+
+ib_api_status_t osm_prtn_add_mcgroup(osm_log_t *p_log,
+                                    osm_subn_t *p_subn, osm_prtn_t *p,
+                                    unsigned is_ipoib, uint8_t rate,
+                                    uint8_t mtu, uint8_t scope)
+{
+       ib_member_rec_t mc_rec;
+       ib_net64_t comp_mask;
+       ib_net16_t pkey;
+       osm_mgrp_t *p_mgrp = NULL;
+       osm_sa_t *p_sa = &p_subn->p_osm->sa;
+       ib_api_status_t status = IB_SUCCESS;
+       uint8_t ts_scope;
+
+       pkey = p->pkey | cl_hton16(0x8000);
+
+       memset(&mc_rec, 0, sizeof(mc_rec));
+
+       mc_rec.mgid = osm_ipoib_mgid; /* ipv4 broadcast group */
+       memcpy(&mc_rec.mgid.raw[4], &pkey, sizeof(pkey));
+
+       mc_rec.qkey = CL_HTON32(0x0b1b);
+       mc_rec.mtu = (mtu ? mtu : OSM_DEFAULT_MGRP_MTU) | (2 << 6); /* 2048 Bytes */
+       mc_rec.tclass = 0;
+       mc_rec.pkey = pkey;
+       mc_rec.rate = (rate ? rate : OSM_DEFAULT_MGRP_RATE) | (2 << 6); /* 10Gb/sec */
+       mc_rec.pkt_life = OSM_DEFAULT_SUBNET_TIMEOUT;
+       mc_rec.sl_flow_hop = ib_member_set_sl_flow_hop(p->sl, 0, 0);
+       /* Scope in MCMemberRecord needs to be consistent with MGID */
+       mc_rec.scope_state = ib_member_set_scope_state(scope ? scope : OSM_DEFAULT_MGRP_SCOPE, MC_FULL_MEMBER);
+       ib_mgid_set_scope(&mc_rec.mgid, scope ? scope : OSM_DEFAULT_MGRP_SCOPE);
+
+       /* don't update rate, mtu, scope */
+       comp_mask = IB_MCR_COMPMASK_MTU | IB_MCR_COMPMASK_MTU_SEL
+                       | IB_MCR_COMPMASK_RATE | IB_MCR_COMPMASK_RATE_SEL
+                       | IB_MCR_COMPMASK_SCOPE;
+       status = osm_mcmr_rcv_find_or_create_new_mgrp(&p_sa->mcmr_rcv,
+                                                     comp_mask, &mc_rec, &p_mgrp);
+       if (!p_mgrp || status != IB_SUCCESS)
+               osm_log( p_log, OSM_LOG_ERROR,
+                       "osm_prtn_add_mcgroup: "
+                       "Failed to create MC group with pkey 0x%04x\n",
+                       cl_ntoh16(pkey));
+       if (p_mgrp)
+               p_mgrp->well_known = TRUE;
+
+       /* workaround for TS */
+       /* FIXME: remove this upon TS fixes */
+       mc_rec.mgid = osm_ts_ipoib_mgid;
+       memcpy(&mc_rec.mgid.raw[4], &pkey, sizeof(pkey));
+       /* Scope in MCMemberRecord needs to be consistent with MGID */
+       ts_scope = ib_mgid_get_scope(&osm_ts_ipoib_mgid); /* get scope from MGID */
+       mc_rec.scope_state = ib_member_set_scope_state(ts_scope, MC_FULL_MEMBER);
+       status = osm_mcmr_rcv_find_or_create_new_mgrp(&p_sa->mcmr_rcv,
+                       comp_mask, &mc_rec, &p_mgrp);
+       if (p_mgrp)
+               p_mgrp->well_known = TRUE;
+
+       return status;
+}
+
+static uint16_t __generate_pkey(osm_subn_t *p_subn)
+{
+       uint16_t pkey;
+
+       cl_qmap_t *m = &p_subn->prtn_pkey_tbl;
+       while (global_pkey_counter < cl_ntoh16(IB_DEFAULT_PARTIAL_PKEY) - 1) {
+               pkey = ++global_pkey_counter;
+               pkey = cl_hton16(pkey);
+               if (cl_qmap_get(m, pkey) == cl_qmap_end(m))
+                       return pkey;
+       }
+       return 0;
+}
+
+static osm_prtn_t *find_prtn_by_name(osm_subn_t *p_subn, const char *name)
+{
+       cl_map_item_t *p_next;
+       osm_prtn_t *p;
+
+       p_next = cl_qmap_head(&p_subn->prtn_pkey_tbl);
+       while (p_next != cl_qmap_end(&p_subn->prtn_pkey_tbl)) {
+               p = (osm_prtn_t *)p_next;
+               p_next = cl_qmap_next(&p->map_item);
+               if (!strncmp(p->name, name, sizeof(p->name)))
+                       return p;
+       }
+
+       return NULL;
+}
+
+osm_prtn_t *osm_prtn_make_new(osm_log_t *p_log, osm_subn_t *p_subn,
+                             const char *name, uint16_t pkey)
+{
+       osm_prtn_t *p = NULL, *p_check;
+
+       pkey &= cl_hton16((uint16_t)~0x8000);
+
+       if (!pkey) {
+               if (name && (p = find_prtn_by_name(p_subn, name)))
+                       return p;
+               if(!(pkey = __generate_pkey(p_subn)))
+                       return NULL;
+       }
+
+       p = osm_prtn_new(name, pkey);
+       if (!p) {
+               osm_log(p_log, OSM_LOG_ERROR,
+                       "osm_prtn_make_new: Unable to create"
+                       " partition \'%s\' (0x%04x)\n",
+                       name, cl_ntoh16(pkey));
+               return NULL;
+       }
+
+       p_check = (osm_prtn_t *)cl_qmap_insert(&p_subn->prtn_pkey_tbl,
+                                              p->pkey, &p->map_item);
+       if (p != p_check) {
+               osm_log(p_log, OSM_LOG_VERBOSE,
+                       "osm_prtn_make_new: Duplicated partition"
+                       " definition: \'%s\' (0x%04x) prev name \'%s\'"
+                       ".  Will use it\n",
+                       name, cl_ntoh16(pkey), p_check->name);
+               osm_prtn_delete(&p);
+               p = p_check;
+       }
+
+       return p;
+}
+
+static ib_api_status_t osm_prtn_make_default(osm_log_t * const p_log,
+                                            osm_subn_t * const p_subn,
+                                            boolean_t no_config)
+{
+       ib_api_status_t status = IB_UNKNOWN_ERROR;
+       osm_prtn_t *p;
+
+       p = osm_prtn_make_new(p_log, p_subn, "Default", IB_DEFAULT_PARTIAL_PKEY);
+       if (!p)
+               goto _err;
+       status = osm_prtn_add_all(p_log, p_subn, p, no_config);
+       if (status != IB_SUCCESS)
+               goto _err;
+       cl_map_remove(&p->part_guid_tbl, p_subn->sm_port_guid);
+       status = osm_prtn_add_port(p_log, p_subn, p, p_subn->sm_port_guid, TRUE);
+
+       if (no_config)
+               osm_prtn_add_mcgroup(p_log, p_subn, p, 1, 0, 0, 0);
+
+  _err:
+       return status;
+}
+
+ib_api_status_t osm_prtn_make_partitions(osm_log_t * const p_log,
+                                        osm_subn_t * const p_subn)
+{
+       struct stat statbuf;
+       const char *file_name;
+       boolean_t is_config = TRUE;
+       ib_api_status_t status = IB_SUCCESS;
+       cl_map_item_t *p_next;
+       osm_prtn_t *p;
+
+       file_name = p_subn->opt.partition_config_file ?
+                       p_subn->opt.partition_config_file :
+                       "/etc/osm-partitions.conf";
+       if (stat(file_name, &statbuf))
+               is_config = FALSE;
+
+       /* clean up current port maps */
+       p_next = cl_qmap_head(&p_subn->prtn_pkey_tbl);
+       while (p_next != cl_qmap_end(&p_subn->prtn_pkey_tbl)) {
+               p = (osm_prtn_t *)p_next;
+               p_next = cl_qmap_next(&p->map_item);
+               cl_map_remove_all(&p->part_guid_tbl);
+               cl_map_remove_all(&p->full_guid_tbl);
+       }
+
+       global_pkey_counter = 0;
+
+       status = osm_prtn_make_default(p_log, p_subn, !is_config);
+       if (status != IB_SUCCESS)
+               goto _err;
+
+       if (is_config && osm_prtn_config_parse_file(p_log, p_subn, file_name)) {
+               osm_log(p_log, OSM_LOG_VERBOSE,
+                       "osm_prtn_make_partitions: Partition configuration "
+                       "was not fully processed\n");
+       }
+
+       /* and now clean up empty partitions */
+       p_next = cl_qmap_head(&p_subn->prtn_pkey_tbl);
+       while (p_next != cl_qmap_end(&p_subn->prtn_pkey_tbl)) {
+               p = (osm_prtn_t *)p_next;
+               p_next = cl_qmap_next(&p->map_item);
+               if (cl_map_count(&p->part_guid_tbl) == 0 &&
+                   cl_map_count(&p->full_guid_tbl) == 0) {
+                       cl_qmap_remove_item(&p_subn->prtn_pkey_tbl,
+                                           (cl_map_item_t *)p);
+                       osm_prtn_delete(&p);
+               }
+       }
+
+  _err:
+       return status;
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_prtn_config.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_prtn_config.c
new file mode 100644 (file)
index 0000000..3d4411b
--- /dev/null
@@ -0,0 +1,447 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of opensm partition management configuration
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision$
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_partition.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+
+#if __WORDSIZE == 64
+#define STRTO_IB_NET64(str, end, base) strtoul(str, end, base)
+#else
+#define STRTO_IB_NET64(str, end, base) strtoull(str, end, base)
+#endif
+
+/*
+ */
+struct part_conf {
+       osm_log_t  *p_log;
+       osm_subn_t *p_subn;
+       osm_prtn_t *p_prtn;
+       unsigned    is_ipoib, mtu, rate, sl, scope;
+};
+
+extern osm_prtn_t *osm_prtn_make_new(osm_log_t *p_log, osm_subn_t *p_subn,
+                                    const char *name, uint16_t pkey);
+extern ib_api_status_t osm_prtn_add_all(osm_log_t *p_log,
+                                       osm_subn_t *p_subn,
+                                       osm_prtn_t *p, boolean_t full);
+extern ib_api_status_t osm_prtn_add_port(osm_log_t *p_log,
+                                        osm_subn_t *p_subn, osm_prtn_t *p,
+                                        ib_net64_t guid, boolean_t full);
+extern ib_api_status_t osm_prtn_add_mcgroup(osm_log_t *p_log,
+                                           osm_subn_t *p_subn, osm_prtn_t *p,
+                                           unsigned is_ipoib, uint8_t rate,
+                                           uint8_t mtu, uint8_t scope);
+
+static int partition_create(unsigned lineno, struct part_conf *conf,
+                           char *name, char *id, char *flag, char *flag_val)
+{
+       uint16_t pkey;
+
+       if (!id && name && isdigit(*name)) {
+               id = name;
+               name = NULL;
+       }
+
+       if (id) {
+               char *end;
+
+               pkey = (uint16_t)strtoul(id, &end, 0);
+               if (end == id || *end)
+                       return -1;
+       } else
+               pkey = 0;
+
+       conf->p_prtn = osm_prtn_make_new(conf->p_log, conf->p_subn,
+                                        name, cl_hton16(pkey));
+       if (!conf->p_prtn)
+               return -1;
+
+       if (conf->p_subn->opt.no_qos) {
+               if (conf->sl != OSM_DEFAULT_SL) {
+                       osm_log(conf->p_log, OSM_LOG_ERROR,
+                               "partition_create: Overriding SL %d to default SL %d on partition %s as QoS not enabled\n",
+                               conf->sl, OSM_DEFAULT_SL, name);
+                 conf->sl = OSM_DEFAULT_SL;
+               }
+       }
+       conf->p_prtn->sl = (uint8_t)conf->sl;
+
+       if (conf->is_ipoib)
+               osm_prtn_add_mcgroup(conf->p_log, conf->p_subn, conf->p_prtn,
+                            conf->is_ipoib, (uint8_t)conf->rate,
+                            (uint8_t)conf->mtu, (uint8_t)conf->scope);
+
+       return 0;
+}
+
+static int partition_add_flag(unsigned lineno, struct part_conf *conf,
+                             char *flag, char *val)
+{
+       int len = strlen(flag);
+       if (!strncmp(flag, "ipoib", len)) {
+               conf->is_ipoib = 1;
+       } else if (!strncmp(flag, "mtu", len)) {
+               if (!val || (conf->mtu = strtoul(val, NULL, 0)) == 0)
+                       osm_log(conf->p_log, OSM_LOG_VERBOSE,
+                               "PARSE WARN: line %d: "
+                               "flag \'mtu\' requires valid value"
+                               " - skipped\n", lineno);
+       } else if (!strncmp(flag, "rate", len)) {
+               if (!val || (conf->rate = strtoul(val, NULL, 0)) == 0)
+                       osm_log(conf->p_log, OSM_LOG_VERBOSE,
+                               "PARSE WARN: line %d: "
+                               "flag \'rate\' requires valid value"
+                               " - skipped\n", lineno);
+       } else if (!strncmp(flag, "scope", len)) {
+               if (!val || (conf->scope = strtoul(val, NULL, 0)) == 0)
+                       osm_log(conf->p_log, OSM_LOG_VERBOSE,
+                               "PARSE WARN: line %d: "
+                               "flag \'scope\' requires valid value"
+                               " - skipped\n", lineno);
+       } else if (!strncmp(flag, "sl", len)) {
+               unsigned sl;
+               char *end;
+
+               if (!val || !*val || (sl = strtoul(val, &end, 0)) > 15 ||
+                   (*end && !isspace(*end)))
+                       osm_log(conf->p_log, OSM_LOG_VERBOSE,
+                               "PARSE WARN: line %d: "
+                               "flag \'sl\' requires valid value"
+                               " - skipped\n", lineno);
+               else
+                       conf->sl = sl;
+       } else {
+                       osm_log(conf->p_log, OSM_LOG_VERBOSE,
+                                         "PARSE WARN: line %d: "
+                                         "unrecognized partition flag \'%s\'"
+                                         " - ignored\n", lineno, flag);
+       }
+       return 0;
+}
+
+static int partition_add_port(unsigned lineno, struct part_conf *conf,
+                             char *name, char *flag)
+{
+       osm_prtn_t *p = conf->p_prtn;
+       ib_net64_t guid;
+       boolean_t full = FALSE;
+
+       if (!name || !*name || !strncmp(name, "NONE", strlen(name)))
+               return 0;
+
+       if (flag) {
+               if (!strncmp(flag, "full", strlen(flag)))
+                       full = TRUE;
+               else if (strncmp(flag, "limited", strlen(flag))) {
+                       osm_log(conf->p_log, OSM_LOG_VERBOSE,
+                               "PARSE WARN: line %d: "
+                               "unrecognized port flag \'%s\'." 
+                               " Assume \'limited\'\n", lineno, flag);
+               }
+       }
+
+       if (!strncmp(name, "ALL", strlen(name))) {
+               return osm_prtn_add_all(conf->p_log, conf->p_subn, p,
+                                       full) == IB_SUCCESS ? 0 : -1;
+       } else if (!strncmp(name, "SELF", strlen(name))) {
+               guid = cl_ntoh64(conf->p_subn->sm_port_guid);
+       } else {
+               char *end;
+               guid = STRTO_IB_NET64(name, &end, 0);
+               if (!guid || *end)
+                       return -1;
+       }
+
+       if (osm_prtn_add_port(conf->p_log, conf->p_subn, p,
+                             cl_hton64(guid), full) != IB_SUCCESS)
+               return -1;
+
+       return 0;
+}
+
+/* conf file parser */
+
+#define STRIP_HEAD_SPACES(p) while (*(p) == ' ' || *(p) == '\t' || \
+               *(p) == '\n') { (p)++; }
+#define STRIP_TAIL_SPACES(p) { char *q = (p) + strlen(p); \
+                               while ( q != (p) && ( *q == '\0' || \
+                                       *q == ' ' || *q == '\t' || \
+                                       *q == '\n')) { *q-- = '\0'; }; }
+
+static int parse_name_token(char *str, char **name, char **val)
+{
+       int len = 0;
+       char *p, *q;
+
+       *name = *val = NULL;
+
+       p = str;
+
+       while (*p == ' ' || *p == '\t' || *p == '\n')
+               p++;
+
+       q = strchr(p, '=');
+       if (q)
+               *q++ = '\0';
+
+       len = strlen(str) + 1;
+       str = q;
+
+       q = p + strlen(p);
+       while ( q != p &&
+               ( *q == '\0' || *q == ' ' || *q == '\t' || *q == '\n'))
+               *q-- = '\0';
+
+       *name = p;
+
+       p = str;
+       if (!p)
+               return len;
+
+       while (*p == ' ' || *p == '\t' || *p == '\n')
+               p++;
+
+       q = p + strlen(p);
+       len += (int)(q - str) + 1;
+       while ( q != p &&
+               ( *q == '\0' || *q == ' ' || *q == '\t' || *q == '\n'))
+               *q-- = '\0';
+       *val = p;
+
+       return len;
+}
+
+static struct part_conf *new_part_conf(osm_log_t *p_log, osm_subn_t *p_subn)
+{
+       static struct part_conf part;
+       struct part_conf *conf = &part;
+
+       memset(conf, 0, sizeof(*conf));
+       conf->p_log = p_log;
+       conf->p_subn = p_subn;
+       conf->p_prtn = NULL;
+       conf->is_ipoib = 0;
+       conf->sl = OSM_DEFAULT_SL;
+       return conf;
+}
+
+static int flush_part_conf(struct part_conf *conf)
+{
+       memset(conf, 0, sizeof(*conf));
+       return 0;
+}
+
+static int parse_part_conf(struct part_conf *conf, char *str, int lineno)
+{
+       int ret, len = 0;
+       char *name, *id, *flag, *flval;
+       char *q, *p;
+
+       p = str;
+       if (*p == '\t' || *p == '\0' || *p == '\n')
+               p++;
+
+       len += (int)(p - str);
+       str = p;
+
+       if (conf->p_prtn)
+               goto skip_header;
+
+       q = strchr(p, ':');
+       if (!q) {
+               osm_log(conf->p_log, OSM_LOG_ERROR,
+                       "PARSE ERROR: line %d: "
+                       "no partition definition found\n", lineno);
+               fprintf(stderr, "\nPARSE ERROR: line %d: "
+                       "no partition definition found\n", lineno);
+               return -1;
+       }
+
+       *q++ = '\0';
+       str = q;
+
+       name = id = flag = flval = NULL;
+
+       q = strchr(p, ',');
+       if (q)
+               *q = '\0';
+
+       ret = parse_name_token(p, &name, &id);
+       p += ret;
+       len += ret;
+
+       while (q) {
+               flag = flval = NULL;
+               q = strchr(p, ',');
+               if (q)
+                       *q++ = '\0';
+               ret = parse_name_token(p, &flag, &flval);
+               if (!flag) {
+                       osm_log(conf->p_log, OSM_LOG_ERROR,
+                               "PARSE ERROR: line %d: "
+                               "bad partition flags\n",lineno);
+                       fprintf(stderr, "\nPARSE ERROR: line %d: "
+                               "bad partition flags\n",lineno);
+                       return -1;
+               }
+               p += ret;
+               len += ret;
+               partition_add_flag(lineno, conf, flag, flval);
+       }
+
+       if (p != str || (partition_create(lineno, conf,
+                                       name, id, flag, flval) < 0)) {
+               osm_log(conf->p_log, OSM_LOG_ERROR,
+                       "PARSE ERROR: line %d: "        
+                       "bad partition definition\n", lineno);
+               fprintf(stderr, "\nPARSE ERROR: line %d: "
+                       "bad partition definition\n", lineno);
+               return -1;
+       }
+
+  skip_header:
+       do {
+               name = flag = NULL;
+               q = strchr(p, ',');
+               if (q)
+                       *q++ = '\0';
+               ret = parse_name_token(p, &name, &flag);
+               if (partition_add_port(lineno, conf, name, flag) < 0) {
+                       osm_log(conf->p_log, OSM_LOG_ERROR,
+                               "PARSE ERROR: line %d: "
+                               "bad PortGUID\n", lineno);
+                       fprintf(stderr, "PARSE ERROR: line %d: "
+                               "bad PortGUID\n", lineno);
+                       return -1;
+               }
+               p += ret;
+               len += ret;
+       } while (q);
+
+       return len;
+}
+
+int osm_prtn_config_parse_file(osm_log_t *p_log, osm_subn_t *p_subn,
+                              const char *file_name)
+{
+       char line[1024];
+       struct part_conf *conf = NULL;
+       FILE *file;
+       int lineno;
+
+       file = fopen(file_name, "r");
+       if (!file) {
+               osm_log(p_log, OSM_LOG_VERBOSE,
+                               "osm_prtn_config_parse_file: "
+                               "Cannot open config file \'%s\': %s\n",
+                               file_name, strerror(errno));
+               return -1;
+       }
+
+       lineno = 0;
+
+       while (fgets(line, sizeof(line) - 1, file) != NULL) {
+               char *q, *p = line;
+
+               lineno++;
+
+               p = line;
+
+               q = strchr(p, '#');
+               if (q)
+                       *q = '\0';
+
+               do {
+                       int len;
+                       while (*p == ' ' || *p == '\t' || *p == '\n')
+                               p++;
+                       if (*p == '\0')
+                               break;
+
+                       if (!conf &&
+                               !(conf = new_part_conf(p_log, p_subn))) {
+                               osm_log(conf->p_log, OSM_LOG_ERROR,
+                                       "PARSE ERROR: line %d: "
+                                       "internal: cannot create config\n", lineno);
+                               fprintf(stderr, "PARSE ERROR: line %d: "
+                                       "internal: cannot create config\n", lineno);
+                               break;
+                       }
+
+                       q = strchr(p, ';');
+                       if (q)
+                               *q = '\0';
+
+                       len = parse_part_conf(conf, p, lineno);
+                       if (len < 0) {
+                               break;
+                       }
+
+                       p += len;
+
+                       if (q) {
+                               flush_part_conf(conf);
+                               conf = NULL;
+                       }
+               } while (q);
+       }
+
+       fclose(file);
+
+       return 0;
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_qos.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_qos.c
new file mode 100644 (file)
index 0000000..fe3b953
--- /dev/null
@@ -0,0 +1,451 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of OpenSM QoS infrastructure primitives
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif                         /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_subnet.h>
+
+struct qos_config {
+       uint8_t max_vls;
+       uint8_t vl_high_limit;
+       ib_vl_arb_table_t vlarb_high[2];
+       ib_vl_arb_table_t vlarb_low[2];
+       ib_slvl_table_t sl2vl;
+};
+
+static void qos_build_config(struct qos_config * cfg,
+                            osm_qos_options_t * opt, osm_qos_options_t * dflt);
+
+/*
+ * QoS primitives
+ */
+static ib_api_status_t vlarb_update_table_block(osm_req_t * p_req,
+                                               osm_physp_t * p,
+                                               uint8_t port_num,
+                                               const ib_vl_arb_table_t *table_block,
+                                               unsigned block_length,
+                                               unsigned block_num)
+{
+       ib_vl_arb_table_t block;
+       osm_madw_context_t context;
+       uint32_t attr_mod;
+       ib_port_info_t *p_pi;
+       unsigned vl_mask, i;
+
+       if (!(p_pi = osm_physp_get_port_info_ptr(p)))
+               return IB_ERROR;
+
+       vl_mask = (1 << (ib_port_info_get_op_vls(p_pi) - 1)) - 1;
+
+       memset(&block, 0, sizeof(block));
+       memcpy(&block, table_block,
+               block_length * sizeof(block.vl_entry[0]));
+       for (i = 0; i < block_length; i++)
+               block.vl_entry[i].vl &= vl_mask;
+
+       if (!memcmp(&p->vl_arb[block_num], &block,
+                    block_length * sizeof(block.vl_entry[0])))
+               return IB_SUCCESS;
+
+       context.vla_context.node_guid =
+           osm_node_get_node_guid(osm_physp_get_node_ptr(p));
+       context.vla_context.port_guid = osm_physp_get_port_guid(p);
+       context.vla_context.set_method = TRUE;
+       attr_mod = ((block_num + 1) << 16) | port_num;
+
+       return osm_req_set(p_req, osm_physp_get_dr_path_ptr(p),
+                          (uint8_t *) & block, sizeof(block),
+                          IB_MAD_ATTR_VL_ARBITRATION,
+                          cl_hton32(attr_mod), CL_DISP_MSGID_NONE, &context);
+}
+
+static ib_api_status_t vlarb_update(osm_req_t * p_req,
+                                   osm_physp_t * p, uint8_t port_num,
+                                   const struct qos_config *qcfg)
+{
+       ib_api_status_t status = IB_SUCCESS;
+       ib_port_info_t *p_pi;
+       unsigned len;
+
+       if (!(p_pi = osm_physp_get_port_info_ptr(p)))
+               return IB_ERROR;
+
+       if (p_pi->vl_arb_low_cap > 0) {
+               len = p_pi->vl_arb_low_cap < IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK ?
+                   p_pi->vl_arb_low_cap : IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK;
+               if ((status = vlarb_update_table_block(p_req, p, port_num,
+                                                      &qcfg->vlarb_low[0],
+                                                      len, 0)) != IB_SUCCESS)
+                       return status;
+       }
+       if (p_pi->vl_arb_low_cap > IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK) {
+               len = p_pi->vl_arb_low_cap % IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK;
+               if ((status = vlarb_update_table_block(p_req, p, port_num,
+                                                      &qcfg->vlarb_low[1],
+                                                      len, 1)) != IB_SUCCESS)
+                       return status;
+       }
+       if (p_pi->vl_arb_high_cap > 0) {
+               len = p_pi->vl_arb_high_cap < IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK ?
+                   p_pi->vl_arb_high_cap : IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK;
+               if ((status = vlarb_update_table_block(p_req, p, port_num,
+                                                      &qcfg->vlarb_high[0],
+                                                      len, 2)) != IB_SUCCESS)
+                       return status;
+       }
+       if (p_pi->vl_arb_high_cap > IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK) {
+               len = p_pi->vl_arb_high_cap % IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK;
+               if ((status = vlarb_update_table_block(p_req, p, port_num,
+                                                      &qcfg->vlarb_high[1],
+                                                      len, 3)) != IB_SUCCESS)
+                       return status;
+       }
+
+       return status;
+}
+
+static ib_api_status_t sl2vl_update_table(osm_req_t * p_req,
+                                         osm_physp_t * p, uint8_t in_port,
+                                         uint8_t out_port,
+                                         const ib_slvl_table_t * sl2vl_table)
+{
+       osm_madw_context_t context;
+       ib_slvl_table_t tbl, *p_tbl;
+       osm_node_t *p_node = osm_physp_get_node_ptr(p);
+       uint32_t attr_mod;
+       ib_port_info_t *p_pi;
+       unsigned vl_mask;
+       uint8_t vl1, vl2;
+       int i;
+
+       if (!(p_pi = osm_physp_get_port_info_ptr(p)))
+               return IB_ERROR;
+
+       vl_mask = (1 << (ib_port_info_get_op_vls(p_pi) - 1)) - 1;
+
+       for (i = 0; i < IB_MAX_NUM_VLS / 2; i++) {
+               vl1 = sl2vl_table->raw_vl_by_sl[i] >> 4;
+               vl2 = sl2vl_table->raw_vl_by_sl[i] & 0xf;
+               if (vl1 != 15)
+                       vl1 &= vl_mask;
+               if (vl2 != 15)
+                       vl2 &= vl_mask;
+               tbl.raw_vl_by_sl[i] = (vl1 << 4 ) | vl2 ;
+       }
+
+       p_tbl = osm_physp_get_slvl_tbl(p, in_port);
+       if (p_tbl && !memcmp(p_tbl, &tbl, sizeof(tbl)))
+               return IB_SUCCESS;
+
+       context.slvl_context.node_guid = osm_node_get_node_guid(p_node);
+       context.slvl_context.port_guid = osm_physp_get_port_guid(p);
+       context.slvl_context.set_method = TRUE;
+       attr_mod = in_port << 8 | out_port;
+       return osm_req_set(p_req, osm_physp_get_dr_path_ptr(p),
+                          (uint8_t *) & tbl, sizeof(tbl),
+                          IB_MAD_ATTR_SLVL_TABLE,
+                          cl_hton32(attr_mod), CL_DISP_MSGID_NONE, &context);
+}
+
+static ib_api_status_t sl2vl_update(osm_req_t * p_req, osm_port_t * p_port,
+                                   osm_physp_t * p, uint8_t port_num,
+                                   const struct qos_config *qcfg)
+{
+       ib_api_status_t status;
+       uint8_t i, num_ports;
+       ib_port_info_t *p_pi = osm_physp_get_port_info_ptr(p);
+       osm_physp_t *p_physp;
+
+       if (!p_pi)
+               return IB_ERROR;
+
+       if (osm_node_get_type(osm_physp_get_node_ptr(p)) == IB_NODE_TYPE_SWITCH) {
+               if (ib_port_info_get_vl_cap(p_pi) == 1) {
+                       /* Check port 0's capability mask */
+                       p_physp = osm_port_get_default_phys_ptr(p_port);
+                       p_pi = osm_physp_get_port_info_ptr(p_physp);
+                       if (!(p_pi->capability_mask & IB_PORT_CAP_HAS_SL_MAP))
+                               return IB_SUCCESS;
+               }
+               num_ports = osm_node_get_num_physp(osm_physp_get_node_ptr(p));
+       } else {
+               if (!(p_pi->capability_mask & IB_PORT_CAP_HAS_SL_MAP))
+                       return IB_SUCCESS;
+               num_ports = 1;
+       }
+
+       for (i = 0; i < num_ports; i++) {
+               status =
+                   sl2vl_update_table(p_req, p, i, port_num, &qcfg->sl2vl);
+               if (status != IB_SUCCESS)
+                       return status;
+       }
+
+       return IB_SUCCESS;
+}
+
+static ib_api_status_t vl_high_limit_update(osm_req_t * p_req,
+                                           osm_physp_t * p,
+                                           const struct qos_config *qcfg)
+{
+       uint8_t payload[IB_SMP_DATA_SIZE];
+       osm_madw_context_t context;
+       ib_port_info_t *p_pi;
+
+       if (!(p_pi = osm_physp_get_port_info_ptr(p)))
+               return IB_ERROR;
+
+       if (p_pi->vl_high_limit == qcfg->vl_high_limit)
+               return IB_SUCCESS;
+
+       memset(payload, 0, IB_SMP_DATA_SIZE);
+       memcpy(payload, p_pi, sizeof(ib_port_info_t));
+
+       p_pi = (ib_port_info_t *) payload;
+       ib_port_info_set_state_no_change(p_pi);
+
+       p_pi->vl_high_limit = qcfg->vl_high_limit;
+
+       context.pi_context.node_guid =
+           osm_node_get_node_guid(osm_physp_get_node_ptr(p));
+       context.pi_context.port_guid = osm_physp_get_port_guid(p);
+       context.pi_context.set_method = TRUE;
+       context.pi_context.update_master_sm_base_lid = FALSE;
+       context.pi_context.ignore_errors = FALSE;
+       context.pi_context.light_sweep = FALSE;
+       context.pi_context.active_transition = FALSE;
+
+       return osm_req_set(p_req, osm_physp_get_dr_path_ptr(p),
+                          payload, sizeof(payload), IB_MAD_ATTR_PORT_INFO,
+                          cl_hton32(osm_physp_get_port_num(p)),
+                          CL_DISP_MSGID_NONE, &context);
+}
+
+static ib_api_status_t qos_physp_setup(osm_log_t * p_log, osm_req_t * p_req,
+                                      osm_port_t * p_port, osm_physp_t * p,
+                                      uint8_t port_num,
+                                      const struct qos_config *qcfg)
+{
+       ib_api_status_t status;
+
+       /* OpVLs should be ok at this moment - just use it */
+
+       /* setup VL high limit */
+       status = vl_high_limit_update(p_req, p, qcfg);
+       if (status != IB_SUCCESS) {
+               osm_log(p_log, OSM_LOG_ERROR,
+                       "qos_physp_setup: ERR 6201 : "
+                       "failed to update VLHighLimit "
+                       "for port %" PRIx64 " #%d\n",
+                       cl_ntoh64(p->port_guid), port_num);
+               return status;
+       }
+
+       /* setup VLArbitration */
+       status = vlarb_update(p_req, p, port_num, qcfg);
+       if (status != IB_SUCCESS) {
+               osm_log(p_log, OSM_LOG_ERROR,
+                       "qos_physp_setup: ERR 6202 : "
+                       "failed to update VLArbitration tables "
+                       "for port %" PRIx64 " #%d\n",
+                       cl_ntoh64(p->port_guid), port_num);
+               return status;
+       }
+
+       /* setup SL2VL tables */
+       status = sl2vl_update(p_req, p_port, p, port_num, qcfg);
+       if (status != IB_SUCCESS) {
+               osm_log(p_log, OSM_LOG_ERROR,
+                       "qos_physp_setup: ERR 6203 : "
+                       "failed to update SL2VLMapping tables "
+                       "for port %" PRIx64 " #%d\n",
+                       cl_ntoh64(p->port_guid), port_num);
+               return status;
+       }
+
+       return IB_SUCCESS;
+}
+
+osm_signal_t osm_qos_setup(osm_opensm_t * p_osm)
+{
+       struct qos_config ca_config, sw0_config, swe_config, rtr_config;
+       struct qos_config *cfg;
+       cl_qmap_t *p_tbl;
+       cl_map_item_t *p_next;
+       osm_port_t *p_port;
+       uint32_t num_physp;
+       osm_physp_t *p_physp;
+       osm_node_t *p_node;
+       ib_api_status_t status;
+       uint8_t i;
+
+       if (p_osm->subn.opt.no_qos)
+               return OSM_SIGNAL_DONE;
+
+       OSM_LOG_ENTER(&p_osm->log, osm_qos_setup);
+
+       qos_build_config(&ca_config, &p_osm->subn.opt.qos_ca_options,
+                        &p_osm->subn.opt.qos_options);
+       qos_build_config(&sw0_config, &p_osm->subn.opt.qos_sw0_options,
+                        &p_osm->subn.opt.qos_options);
+       qos_build_config(&swe_config, &p_osm->subn.opt.qos_swe_options,
+                        &p_osm->subn.opt.qos_options);
+       qos_build_config(&rtr_config, &p_osm->subn.opt.qos_rtr_options,
+                        &p_osm->subn.opt.qos_options);
+
+       cl_plock_excl_acquire(&p_osm->lock);
+
+       p_tbl = &p_osm->subn.port_guid_tbl;
+       p_next = cl_qmap_head(p_tbl);
+       while (p_next != cl_qmap_end(p_tbl)) {
+               p_port = (osm_port_t *) p_next;
+               p_next = cl_qmap_next(p_next);
+
+               p_node = p_port->p_node;
+               if (p_node->sw) {
+                       num_physp = osm_port_get_num_physp(p_port);
+                       for (i = 1; i < num_physp; i++) {
+                               p_physp = osm_port_get_phys_ptr(p_port, i);
+                               if (!p_physp || !osm_physp_is_valid(p_physp))
+                                       continue;
+                               status =
+                                   qos_physp_setup(&p_osm->log, &p_osm->sm.req,
+                                                   p_port, p_physp, i, &swe_config);
+                       }
+                       /* skip base port 0 */
+                       if (!ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info))
+                               continue;
+
+                       cfg = &sw0_config;
+               } else if (osm_node_get_type(p_node) == IB_NODE_TYPE_ROUTER)
+                       cfg = &rtr_config;
+               else
+                       cfg = &ca_config;
+
+               p_physp = osm_port_get_default_phys_ptr(p_port);
+               if (!osm_physp_is_valid(p_physp))
+                       continue;
+
+               status = qos_physp_setup(&p_osm->log, &p_osm->sm.req,
+                                        p_port, p_physp, 0, cfg);
+       }
+
+       cl_plock_release(&p_osm->lock);
+       OSM_LOG_EXIT(&p_osm->log);
+
+       return OSM_SIGNAL_DONE;
+}
+
+/*
+ *  QoS config stuff
+ */
+static int parse_one_unsigned(char *str, char delim, unsigned *val)
+{
+       char *end;
+       *val = strtoul(str, &end, 0);
+       if (*end)
+               end++;
+       return (int)(end - str);
+}
+
+static int parse_vlarb_entry(char *str, ib_vl_arb_element_t * e)
+{
+       unsigned val;
+       char *p = str;
+       p += parse_one_unsigned(p, ':', &val);
+       e->vl = val % 15;
+       p += parse_one_unsigned(p, ',', &val);
+       e->weight = (uint8_t)val;
+       return (int)(p - str);
+}
+
+static int parse_sl2vl_entry(char *str, uint8_t * raw)
+{
+       unsigned val1, val2;
+       char *p = str;
+       p += parse_one_unsigned(p, ',', &val1);
+       p += parse_one_unsigned(p, ',', &val2);
+       *raw = (val1 << 4) | (val2 & 0xf);
+       return (int)(p - str);
+}
+
+static void qos_build_config(struct qos_config *cfg,
+                            osm_qos_options_t * opt, osm_qos_options_t * dflt)
+{
+       int i;
+       char *p;
+
+       memset(cfg, 0, sizeof(*cfg));
+
+       cfg->max_vls = opt->max_vls > 0 ? opt->max_vls : dflt->max_vls;
+       cfg->vl_high_limit = (uint8_t)opt->high_limit;
+
+       p = opt->vlarb_high ? opt->vlarb_high : dflt->vlarb_high;
+       for (i = 0; i < 2 * IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK; i++) {
+               p += parse_vlarb_entry(p,
+                                      &cfg->vlarb_high[i/IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK].
+                                      vl_entry[i%IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK]);
+       }
+
+       p = opt->vlarb_low ? opt->vlarb_low : dflt->vlarb_low;
+       for (i = 0; i < 2 * IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK; i++) {
+               p += parse_vlarb_entry(p,
+                                      &cfg->vlarb_low[i/IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK].
+                                      vl_entry[i%IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK]);
+       }
+
+       p = opt->sl2vl ? opt->sl2vl : dflt->sl2vl;
+       for (i = 0; i < IB_MAX_NUM_VLS / 2; i++)
+               p += parse_sl2vl_entry(p, &cfg->sl2vl.raw_vl_by_sl[i]);
+
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_remote_sm.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_remote_sm.c
new file mode 100644 (file)
index 0000000..22a68de
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_remote_sm.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_sm_t.
+ * This object represents the remote SM object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_remote_sm.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_remote_sm_construct(
+  IN osm_remote_sm_t* const p_sm )
+{
+  memset( p_sm, 0, sizeof(*p_sm) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_remote_sm_destroy(
+  IN osm_remote_sm_t* const p_sm )
+{
+  memset( p_sm, 0, sizeof(*p_sm) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_remote_sm_init(
+  IN osm_remote_sm_t* const p_sm,
+  IN const osm_port_t* const p_port,
+  IN const ib_sm_info_t* const p_smi )
+{
+  CL_ASSERT( p_sm );
+  CL_ASSERT( p_port );
+
+  osm_remote_sm_construct( p_sm );
+
+  p_sm->p_port = p_port;
+  p_sm->smi = *p_smi;
+  return;
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_req.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_req.c
new file mode 100644 (file)
index 0000000..0002e15
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_req.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_req_t.
+ * This object represents the generic attribute requester.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_attrib_req.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_req_construct(
+  IN osm_req_t* const p_req )
+{
+  CL_ASSERT( p_req );
+
+  memset( p_req, 0, sizeof(*p_req) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_req_destroy(
+  IN osm_req_t* const p_req )
+{
+  CL_ASSERT( p_req );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_req_init(
+  IN osm_req_t*            const p_req,
+  IN osm_mad_pool_t*       const p_pool,
+  IN osm_vl15_t*           const p_vl15,
+  IN osm_subn_t*           const p_subn,
+  IN osm_log_t*            const p_log,
+  IN atomic32_t*           const p_sm_trans_id )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_req_init );
+
+  osm_req_construct( p_req );
+  p_req->p_log = p_log;
+
+  p_req->p_pool = p_pool;
+  p_req->p_vl15 = p_vl15;
+  p_req->p_subn = p_subn;
+  p_req->p_sm_trans_id = p_sm_trans_id;
+
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+/**********************************************************************
+  The plock MAY or MAY NOT be held before calling this function.
+**********************************************************************/
+ib_api_status_t
+osm_req_get(
+  IN const osm_req_t* const p_req,
+  IN const osm_dr_path_t* const p_path,
+  IN const uint16_t attr_id,
+  IN const uint32_t attr_mod,
+  IN const cl_disp_msgid_t err_msg,
+  IN const osm_madw_context_t* const p_context )
+{
+  osm_madw_t *p_madw;
+  ib_api_status_t status = IB_SUCCESS;
+  ib_net64_t tid;
+
+  CL_ASSERT( p_req );
+
+  OSM_LOG_ENTER( p_req->p_log, osm_req_get );
+
+  CL_ASSERT( p_path );
+  CL_ASSERT( attr_id );
+
+  /* do nothing if we are exiting ... */
+  if (osm_exit_flag)
+    goto Exit;
+
+  /* p_context may be NULL. */
+
+  p_madw = osm_mad_pool_get(
+    p_req->p_pool,
+    p_path->h_bind,
+    MAD_BLOCK_SIZE,
+    NULL );
+
+  if( p_madw == NULL )
+  {
+    osm_log( p_req->p_log, OSM_LOG_ERROR,
+             "osm_req_get: ERR 1101: "
+             "Unable to acquire MAD\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+  tid = cl_hton64( (uint64_t)cl_atomic_inc( p_req->p_sm_trans_id ) );
+
+  if( osm_log_is_active( p_req->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_req->p_log, OSM_LOG_DEBUG,
+             "osm_req_get: "
+             "Getting %s (0x%X), modifier 0x%X, TID 0x%" PRIx64 "\n",
+             ib_get_sm_attr_str( attr_id ),
+             cl_ntoh16( attr_id ),
+             cl_ntoh32( attr_mod ),
+             cl_ntoh64( tid ) );
+  }
+
+  ib_smp_init_new(
+    osm_madw_get_smp_ptr( p_madw ),
+    IB_MAD_METHOD_GET,
+    tid,
+    attr_id,
+    attr_mod,
+    p_path->hop_count,
+    p_req->p_subn->opt.m_key,
+    p_path->path,
+    IB_LID_PERMISSIVE,
+    IB_LID_PERMISSIVE );
+
+  p_madw->mad_addr.dest_lid = IB_LID_PERMISSIVE;
+  p_madw->mad_addr.addr_type.smi.source_lid = IB_LID_PERMISSIVE;
+  p_madw->resp_expected = TRUE;
+  p_madw->fail_msg = err_msg;
+
+  /*
+    Fill in the mad wrapper context for the recipient.
+    In this case, the only thing the recipient needs is the
+    guid value.
+  */
+
+  if( p_context )
+    p_madw->context = *p_context;
+
+  osm_vl15_post( p_req->p_vl15, p_madw );
+
+ Exit:
+  OSM_LOG_EXIT( p_req->p_log );
+  return( status );
+}
+
+/**********************************************************************
+  The plock MAY or MAY NOT be held before calling this function.
+**********************************************************************/
+ib_api_status_t
+osm_req_set(
+  IN const osm_req_t* const p_req,
+  IN const osm_dr_path_t* const p_path,
+  IN const uint8_t* const p_payload,
+  IN const size_t payload_size,
+  IN const uint16_t attr_id,
+  IN const uint32_t attr_mod,
+  IN const cl_disp_msgid_t err_msg,
+  IN const osm_madw_context_t* const p_context )
+{
+  osm_madw_t *p_madw;
+  ib_api_status_t status = IB_SUCCESS;
+  ib_net64_t tid;
+
+  CL_ASSERT( p_req );
+
+  OSM_LOG_ENTER( p_req->p_log, osm_req_set );
+
+  CL_ASSERT( p_path );
+  CL_ASSERT( attr_id );
+  CL_ASSERT( p_payload );
+
+  /* do nothing if we are exiting ... */
+  if (osm_exit_flag)
+    goto Exit;
+
+  /* p_context may be NULL. */
+
+  p_madw = osm_mad_pool_get(
+    p_req->p_pool,
+    p_path->h_bind,
+    MAD_BLOCK_SIZE,
+    NULL );
+
+  if( p_madw == NULL )
+  {
+    osm_log( p_req->p_log, OSM_LOG_ERROR,
+             "osm_req_set: ERR 1102: "
+             "Unable to acquire MAD\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+  tid = cl_hton64( (uint64_t)cl_atomic_inc( p_req->p_sm_trans_id ) );
+
+  if( osm_log_is_active( p_req->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_req->p_log, OSM_LOG_DEBUG,
+             "osm_req_set: "
+             "Setting %s (0x%X), modifier 0x%X, TID 0x%" PRIx64 "\n",
+             ib_get_sm_attr_str( attr_id ),
+             cl_ntoh16( attr_id ),
+             cl_ntoh32( attr_mod ),
+             cl_ntoh64( tid ) );
+  }
+
+  ib_smp_init_new(
+    osm_madw_get_smp_ptr( p_madw ),
+    IB_MAD_METHOD_SET,
+    tid,
+    attr_id,
+    attr_mod,
+    p_path->hop_count,
+    p_req->p_subn->opt.m_key,
+    p_path->path,
+    IB_LID_PERMISSIVE,
+    IB_LID_PERMISSIVE );
+
+  p_madw->mad_addr.dest_lid = IB_LID_PERMISSIVE;
+  p_madw->mad_addr.addr_type.smi.source_lid = IB_LID_PERMISSIVE;
+  p_madw->resp_expected = TRUE;
+  p_madw->fail_msg = err_msg;
+
+  /*
+    Fill in the mad wrapper context for the recipient.
+    In this case, the only thing the recipient needs is the
+    guid value.
+  */
+
+  if( p_context )
+    p_madw->context = *p_context;
+
+  memcpy( osm_madw_get_smp_ptr( p_madw )->data,
+          p_payload, payload_size );
+
+  osm_vl15_post( p_req->p_vl15, p_madw );
+
+ Exit:
+  OSM_LOG_EXIT( p_req->p_log );
+  return( status );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_req_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_req_ctrl.c
new file mode 100644 (file)
index 0000000..fbec64c
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_req_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_req_ctrl_t.
+ * This object represents the request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_req_ctrl.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_attrib_req.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_req_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_req_get( ((osm_req_ctrl_t*)context)->p_req,
+               (&((osm_attrib_req_t*)p_data)->path),
+               ((osm_attrib_req_t*)p_data)->attrib_id,
+               ((osm_attrib_req_t*)p_data)->attrib_mod,
+               ((osm_attrib_req_t*)p_data)->err_msg,
+               (&((osm_attrib_req_t*)p_data)->context) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_req_ctrl_construct(
+  IN osm_req_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_req_ctrl_destroy(
+  IN osm_req_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_req_ctrl_init(
+  IN osm_req_ctrl_t* const p_ctrl,
+  IN osm_req_t*      const p_req,
+  IN osm_log_t*         const p_log,
+  IN cl_dispatcher_t*      const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_req_ctrl_init );
+
+  osm_req_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+
+  p_ctrl->p_disp = p_disp;
+  p_ctrl->p_req = p_req;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_REQ,
+    __osm_req_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_req_ctrl_init: ERR 1202: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_resp.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_resp.c
new file mode 100644 (file)
index 0000000..e12a901
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_resp.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_resp_t.
+ * This object represents the generic attribute responder.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_resp.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_attrib_req.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_resp_construct(
+  IN osm_resp_t* const p_resp )
+{
+  memset( p_resp, 0, sizeof(*p_resp) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_resp_destroy(
+  IN osm_resp_t* const p_resp )
+{
+  CL_ASSERT( p_resp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_resp_init(
+  IN osm_resp_t*           const p_resp,
+  IN osm_mad_pool_t*    const p_pool,
+  IN osm_vl15_t*           const p_vl15,
+  IN osm_subn_t*           const p_subn,
+  IN osm_log_t*            const p_log )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_resp_init );
+
+  osm_resp_construct( p_resp );
+
+  p_resp->p_log = p_log;
+  p_resp->p_pool = p_pool;
+  p_resp->p_vl15 = p_vl15;
+  p_resp->p_subn = p_subn;
+
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_resp_make_resp_smp(
+  IN const osm_resp_t* const p_resp,
+  IN const ib_smp_t* const p_src_smp,
+  IN const ib_net16_t status,
+  IN const uint8_t* const p_payload,
+  OUT ib_smp_t* const p_dest_smp )
+{
+  OSM_LOG_ENTER( p_resp->p_log, osm_resp_make_resp_smp );
+
+  CL_ASSERT( p_dest_smp );
+  CL_ASSERT( p_src_smp );
+  CL_ASSERT( !ib_smp_is_response( p_src_smp ) );
+
+  *p_dest_smp = *p_src_smp;
+  if (p_src_smp->method == IB_MAD_METHOD_GET ||
+      p_src_smp->method == IB_MAD_METHOD_SET ) {
+    p_dest_smp->method = IB_MAD_METHOD_GET_RESP;
+    p_dest_smp->status = status;
+  }
+  else if (p_src_smp->method == IB_MAD_METHOD_TRAP)
+  {
+    p_dest_smp->method = IB_MAD_METHOD_TRAP_REPRESS;
+    p_dest_smp->status = 0;
+  }
+  else
+  {
+    osm_log( p_resp->p_log, OSM_LOG_ERROR,
+             "osm_resp_make_resp_smp: ERR 1302: "
+             "src smp method unsupported 0x%X\n",
+             p_src_smp->method );
+    goto Exit;
+  }
+
+  if (p_src_smp->mgmt_class == IB_MCLASS_SUBN_DIR)
+    p_dest_smp->status |= IB_SMP_DIRECTION;
+
+  p_dest_smp->dr_dlid = p_dest_smp->dr_slid;
+  p_dest_smp->dr_slid = p_dest_smp->dr_dlid;
+  memcpy( &p_dest_smp->data, p_payload, IB_SMP_DATA_SIZE );
+
+ Exit:
+  OSM_LOG_EXIT( p_resp->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_resp_send(
+  IN const osm_resp_t*     const p_resp,
+  IN const osm_madw_t*     const p_req_madw,
+  IN const ib_net16_t         mad_status,
+  IN const uint8_t*        const p_payload )
+{
+  const ib_smp_t*          p_req_smp;
+  ib_smp_t*                p_smp;
+  osm_madw_t*              p_madw;
+  ib_api_status_t          status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_resp->p_log, osm_resp_send );
+
+  CL_ASSERT( p_req_madw );
+  CL_ASSERT( p_payload );
+
+  /* do nothing if we are exiting ... */
+  if (osm_exit_flag)
+    goto Exit;
+
+  p_madw = osm_mad_pool_get(
+    p_resp->p_pool,
+    osm_madw_get_bind_handle( p_req_madw ),
+    MAD_BLOCK_SIZE,
+    NULL );
+
+  if( p_madw == NULL )
+  {
+    osm_log( p_resp->p_log, OSM_LOG_ERROR,
+             "osm_resp_send: ERR 1301: "
+             "Unable to acquire MAD\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+  /*
+    Copy the request smp to the response smp, then just
+    update the necessary fields.
+  */
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+  p_req_smp = osm_madw_get_smp_ptr( p_req_madw );
+  osm_resp_make_resp_smp( p_resp, p_req_smp, mad_status,
+                          p_payload, p_smp );
+  p_madw->mad_addr.dest_lid =
+    p_req_madw->mad_addr.addr_type.smi.source_lid;
+  p_madw->mad_addr.addr_type.smi.source_lid =
+    p_req_madw->mad_addr.dest_lid;
+
+  p_madw->resp_expected = FALSE;
+  p_madw->fail_msg = CL_DISP_MSGID_NONE;
+
+  if( osm_log_is_active( p_resp->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_resp->p_log, OSM_LOG_DEBUG,
+             "osm_resp_send: "
+             "Responding to %s (0x%X)"
+             "\n\t\t\t\tattribute modifier 0x%X, TID 0x%" PRIx64 "\n",
+             ib_get_sm_attr_str( p_smp->attr_id ),
+             cl_ntoh16( p_smp->attr_id ),
+             cl_ntoh32( p_smp->attr_mod ),
+             cl_ntoh64( p_smp->trans_id ) );
+  }
+
+  osm_vl15_post( p_resp->p_vl15, p_madw );
+
+ Exit:
+  OSM_LOG_EXIT( p_resp->p_log );
+  return( status );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_router.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_router.c
new file mode 100644 (file)
index 0000000..0f478b6
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_router_t.
+ * This object represents an Infiniband router.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_math.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_router.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_router_construct(
+  IN osm_router_t* const p_rtr )
+{
+  CL_ASSERT( p_rtr );
+  memset( p_rtr, 0, sizeof(*p_rtr) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_router_init(
+  IN osm_router_t* const p_rtr,
+  IN osm_port_t*   const p_port )
+{
+  ib_api_status_t  status = IB_SUCCESS;
+
+  CL_ASSERT( p_rtr );
+  CL_ASSERT( p_port );
+
+  osm_router_construct( p_rtr );
+
+  p_rtr->p_port = p_port;
+
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_router_destroy(
+  IN osm_router_t* const p_rtr )
+{
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_router_delete(
+  IN OUT osm_router_t** const pp_rtr )
+{
+  osm_router_destroy( *pp_rtr );
+  free( *pp_rtr );
+  *pp_rtr = NULL;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_router_t*
+osm_router_new(
+  IN osm_port_t* const p_port )
+{
+  ib_api_status_t status;
+  osm_router_t *p_rtr;
+
+  p_rtr = (osm_router_t*)malloc( sizeof(*p_rtr) );
+  if( p_rtr )
+  {
+    memset( p_rtr, 0, sizeof(*p_rtr) );
+    status = osm_router_init( p_rtr, p_port );
+    if( status != IB_SUCCESS )
+      osm_router_delete( &p_rtr );
+  }
+
+  return( p_rtr );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa.c
new file mode 100644 (file)
index 0000000..3f5dfb7
--- /dev/null
@@ -0,0 +1,1207 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_sa_t.
+ * This object represents the Subnet Administration object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.14 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_sa.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_multicast.h>
+#include <opensm/osm_inform.h>
+#include <opensm/osm_service.h>
+
+#define  OSM_SA_INITIAL_TID_VALUE 0xabc
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_construct(
+  IN osm_sa_t* const p_sa )
+{
+  memset( p_sa, 0, sizeof(*p_sa) );
+  p_sa->state = OSM_SA_STATE_INIT;
+  p_sa->sa_trans_id = OSM_SA_INITIAL_TID_VALUE;
+
+  osm_sa_mad_ctrl_construct( &p_sa->mad_ctrl );
+  osm_sa_resp_construct( &p_sa->resp );
+
+  osm_nr_rcv_construct( &p_sa->nr_rcv);
+  osm_nr_rcv_ctrl_construct( &p_sa->nr_rcv_ctrl );
+
+  osm_pir_rcv_construct( &p_sa->pir_rcv );
+  osm_pir_rcv_ctrl_construct( &p_sa->pir_rcv_ctrl );
+
+  osm_gir_rcv_construct( &p_sa->gir_rcv );
+  osm_gir_rcv_ctrl_construct( &p_sa->gir_rcv_ctrl );
+
+  osm_lr_rcv_construct( &p_sa->lr_rcv );
+  osm_lr_rcv_ctrl_construct( &p_sa->lr_rcv_ctrl );
+
+  osm_pr_rcv_construct( &p_sa->pr_rcv );
+  osm_pr_rcv_ctrl_construct( &p_sa->pr_rcv_ctrl );
+
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+  osm_mpr_rcv_construct( &p_sa->mpr_rcv );
+  osm_mpr_rcv_ctrl_construct( &p_sa->mpr_rcv_ctrl );
+#endif
+
+  osm_smir_rcv_construct( &p_sa->smir_rcv );
+  osm_smir_ctrl_construct( &p_sa->smir_ctrl );
+
+  osm_mcmr_rcv_construct(&p_sa->mcmr_rcv );
+  osm_mcmr_rcv_ctrl_construct(&p_sa->mcmr_rcv_ctlr);
+
+  osm_sr_rcv_construct( &p_sa->sr_rcv );
+  osm_sr_rcv_ctrl_construct( &p_sa->sr_rcv_ctrl );
+
+  osm_infr_rcv_construct( &p_sa->infr_rcv );
+  osm_infr_rcv_ctrl_construct( &p_sa->infr_rcv_ctrl );
+
+  osm_vlarb_rec_rcv_construct( &p_sa->vlarb_rec_rcv );
+  osm_vlarb_rec_rcv_ctrl_construct( &p_sa->vlarb_rec_rcv_ctrl );
+
+  osm_slvl_rec_rcv_construct( &p_sa->slvl_rec_rcv );
+  osm_slvl_rec_rcv_ctrl_construct( &p_sa->slvl_rec_rcv_ctrl );
+
+  osm_pkey_rec_rcv_construct( &p_sa->pkey_rec_rcv );
+  osm_pkey_rec_rcv_ctrl_construct( &p_sa->pkey_rec_rcv_ctrl );
+
+  osm_lftr_rcv_construct( &p_sa->lftr_rcv );
+  osm_lftr_rcv_ctrl_construct( &p_sa->lftr_rcv_ctrl );
+
+  osm_sir_rcv_construct( &p_sa->sir_rcv );
+  osm_sir_rcv_ctrl_construct( &p_sa->sir_rcv_ctrl );
+
+  osm_mftr_rcv_construct( &p_sa->mftr_rcv );
+  osm_mftr_rcv_ctrl_construct( &p_sa->mftr_rcv_ctrl );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_shutdown(
+  IN osm_sa_t* const p_sa )
+{
+  ib_api_status_t status;
+  OSM_LOG_ENTER( p_sa->p_log, osm_sa_shutdown );
+
+  /* unbind from the mad service */
+  status = osm_sa_mad_ctrl_unbind( &p_sa->mad_ctrl );
+
+  /* remove any registered dispatcher message */
+  osm_nr_rcv_ctrl_destroy( &p_sa->nr_rcv_ctrl );
+  osm_pir_rcv_ctrl_destroy( &p_sa->pir_rcv_ctrl );
+  osm_gir_rcv_ctrl_destroy( &p_sa->gir_rcv_ctrl );
+  osm_lr_rcv_ctrl_destroy( &p_sa->lr_rcv_ctrl );
+  osm_pr_rcv_ctrl_destroy( &p_sa->pr_rcv_ctrl );
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+  osm_mpr_rcv_ctrl_destroy( &p_sa->mpr_rcv_ctrl );
+#endif
+  osm_smir_ctrl_destroy( &p_sa->smir_ctrl );
+  osm_mcmr_rcv_ctrl_destroy( &p_sa->mcmr_rcv_ctlr);
+  osm_sr_rcv_ctrl_destroy( &p_sa->sr_rcv_ctrl );
+  osm_infr_rcv_ctrl_destroy( &p_sa->infr_rcv_ctrl );
+  osm_vlarb_rec_rcv_ctrl_destroy( &p_sa->vlarb_rec_rcv_ctrl );
+  osm_slvl_rec_rcv_ctrl_destroy( &p_sa->slvl_rec_rcv_ctrl );
+  osm_pkey_rec_rcv_ctrl_destroy( &p_sa->pkey_rec_rcv_ctrl );
+  osm_lftr_rcv_ctrl_destroy( &p_sa->lftr_rcv_ctrl );
+  osm_sir_rcv_ctrl_destroy( &p_sa->sir_rcv_ctrl );
+  osm_mftr_rcv_ctrl_destroy( &p_sa->mftr_rcv_ctrl );
+  osm_sa_mad_ctrl_destroy( &p_sa->mad_ctrl );
+
+  OSM_LOG_EXIT( p_sa->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_destroy(
+  IN osm_sa_t* const p_sa )
+{
+  OSM_LOG_ENTER( p_sa->p_log, osm_sa_destroy );
+
+  p_sa->state = OSM_SA_STATE_INIT;
+
+  osm_nr_rcv_destroy( &p_sa->nr_rcv );
+  osm_pir_rcv_destroy( &p_sa->pir_rcv );
+  osm_gir_rcv_destroy( &p_sa->gir_rcv );
+  osm_lr_rcv_destroy( &p_sa->lr_rcv );
+  osm_pr_rcv_destroy( &p_sa->pr_rcv );
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+  osm_mpr_rcv_destroy( &p_sa->mpr_rcv );
+#endif
+  osm_smir_rcv_destroy( &p_sa->smir_rcv );
+  osm_mcmr_rcv_destroy(&p_sa->mcmr_rcv);
+  osm_sr_rcv_destroy( &p_sa->sr_rcv );
+  osm_infr_rcv_destroy( &p_sa->infr_rcv );
+  osm_vlarb_rec_rcv_destroy( &p_sa->vlarb_rec_rcv );
+  osm_slvl_rec_rcv_destroy( &p_sa->slvl_rec_rcv );
+  osm_pkey_rec_rcv_destroy( &p_sa->pkey_rec_rcv );
+  osm_lftr_rcv_destroy( &p_sa->lftr_rcv );
+  osm_sir_rcv_destroy( &p_sa->sir_rcv );
+  osm_mftr_rcv_destroy( &p_sa->mftr_rcv );
+  osm_sa_resp_destroy( &p_sa->resp );
+
+  OSM_LOG_EXIT( p_sa->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sa_init(
+  IN osm_sm_t* const p_sm,
+  IN osm_sa_t* const p_sa,
+  IN osm_subn_t* const p_subn,
+  IN osm_vendor_t* const p_vendor,
+  IN osm_mad_pool_t* const p_mad_pool,
+  IN osm_log_t* const p_log,
+  IN osm_stats_t* const p_stats,
+  IN cl_dispatcher_t* const p_disp,
+  IN cl_plock_t* const p_lock )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_sa_init );
+
+  p_sa->p_subn = p_subn;
+  p_sa->p_vendor = p_vendor;
+  p_sa->p_mad_pool = p_mad_pool;
+  p_sa->p_log = p_log;
+  p_sa->p_disp = p_disp;
+  p_sa->p_lock = p_lock;
+
+  p_sa->state = OSM_SA_STATE_READY;
+
+  status = osm_sa_resp_init(&p_sa->resp,
+                            p_sa->p_mad_pool,
+                            p_log);
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_sa_mad_ctrl_init(
+    &p_sa->mad_ctrl,
+    &p_sa->resp,
+    p_sa->p_mad_pool,
+    p_sa->p_vendor,
+    p_subn,
+    p_log,
+    p_stats,
+    p_disp );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_cpi_rcv_init(
+    &p_sa->cpi_rcv,
+    &p_sa->resp,
+    p_sa->p_mad_pool,
+    p_subn,
+    p_log,
+    p_lock );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_cpi_rcv_ctrl_init(
+    &p_sa->cpi_rcv_ctrl,
+    &p_sa->cpi_rcv,
+    p_log,
+    p_disp );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_nr_rcv_init(
+    &p_sa->nr_rcv,
+    &p_sa->resp,
+    p_sa->p_mad_pool,
+    p_subn,
+    p_log,
+    p_lock );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_nr_rcv_ctrl_init(
+    &p_sa->nr_rcv_ctrl,
+    &p_sa->nr_rcv,
+    p_log,
+    p_disp );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_pir_rcv_init(
+    &p_sa->pir_rcv,
+    &p_sa->resp,
+    p_sa->p_mad_pool,
+    p_subn,
+    p_log,
+    p_lock );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_pir_rcv_ctrl_init(
+    &p_sa->pir_rcv_ctrl,
+    &p_sa->pir_rcv,
+    p_log,
+    p_disp );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_gir_rcv_init(
+    &p_sa->gir_rcv,
+    &p_sa->resp,
+    p_sa->p_mad_pool,
+    p_subn,
+    p_log,
+    p_lock );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_gir_rcv_ctrl_init(
+    &p_sa->gir_rcv_ctrl,
+    &p_sa->gir_rcv,
+    p_log,
+    p_disp );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_lr_rcv_init(
+    &p_sa->lr_rcv,
+    &p_sa->resp,
+    p_sa->p_mad_pool,
+    p_subn,
+    p_log,
+    p_lock );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_lr_rcv_ctrl_init(
+    &p_sa->lr_rcv_ctrl,
+    &p_sa->lr_rcv,
+    p_log,
+    p_disp );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_pr_rcv_init(
+    &p_sa->pr_rcv,
+    &p_sa->resp,
+    p_sa->p_mad_pool,
+    p_subn,
+    p_log,
+    p_lock );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_pr_rcv_ctrl_init(
+    &p_sa->pr_rcv_ctrl,
+    &p_sa->pr_rcv,
+    p_log,
+    p_disp );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+  status = osm_mpr_rcv_init(
+    &p_sa->mpr_rcv,
+    &p_sa->resp,
+    p_sa->p_mad_pool, 
+    p_subn,
+    p_log,
+    p_lock );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_mpr_rcv_ctrl_init(
+    &p_sa->mpr_rcv_ctrl,
+    &p_sa->mpr_rcv,
+    p_log,
+    p_disp );
+  if( status != IB_SUCCESS )
+    goto Exit;
+#endif
+
+  status = osm_smir_rcv_init(
+    &p_sa->smir_rcv,
+    &p_sa->resp,
+    p_sa->p_mad_pool,
+    p_subn,
+    p_stats,
+    p_log,
+    p_lock );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_smir_ctrl_init(
+    &p_sa->smir_ctrl,
+    &p_sa->smir_rcv,
+    p_log,
+    p_disp );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_mcmr_rcv_init(
+    p_sm,
+    &p_sa->mcmr_rcv,
+    &p_sa->resp,
+    p_sa->p_mad_pool,
+    p_subn,
+    p_log,
+    p_lock);
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_mcmr_rcv_ctrl_init(
+    &p_sa->mcmr_rcv_ctlr,
+    &p_sa->mcmr_rcv,
+    p_log,
+    p_disp);
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_sr_rcv_init(
+    &p_sa->sr_rcv,
+    &p_sa->resp,
+    p_sa->p_mad_pool,
+    p_subn,
+    p_log,
+    p_lock);
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_sr_rcv_ctrl_init(
+    &p_sa->sr_rcv_ctrl,
+    &p_sa->sr_rcv,
+    p_log,
+    p_disp );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_infr_rcv_init(
+    &p_sa->infr_rcv,
+    &p_sa->resp,
+    p_sa->p_mad_pool,
+    p_subn,
+    p_log,
+    p_lock);
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_infr_rcv_ctrl_init(
+    &p_sa->infr_rcv_ctrl,
+    &p_sa->infr_rcv,
+    p_log,
+    p_disp );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_vlarb_rec_rcv_init(
+    &p_sa->vlarb_rec_rcv,
+    &p_sa->resp,
+    p_sa->p_mad_pool,
+    p_subn,
+    p_log,
+    p_lock);
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_vlarb_rec_rcv_ctrl_init(
+    &p_sa->vlarb_rec_rcv_ctrl,
+    &p_sa->vlarb_rec_rcv,
+    p_log,
+    p_disp );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_slvl_rec_rcv_init(
+    &p_sa->slvl_rec_rcv,
+    &p_sa->resp,
+    p_sa->p_mad_pool,
+    p_subn,
+    p_log,
+    p_lock);
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_slvl_rec_rcv_ctrl_init(
+    &p_sa->slvl_rec_rcv_ctrl,
+    &p_sa->slvl_rec_rcv,
+    p_log,
+    p_disp );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_pkey_rec_rcv_init(
+    &p_sa->pkey_rec_rcv,
+    &p_sa->resp,
+    p_sa->p_mad_pool,
+    p_subn,
+    p_log,
+    p_lock);
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_pkey_rec_rcv_ctrl_init(
+    &p_sa->pkey_rec_rcv_ctrl,
+    &p_sa->pkey_rec_rcv,
+    p_log,
+    p_disp );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_lftr_rcv_init(
+    &p_sa->lftr_rcv,
+    &p_sa->resp,
+    p_sa->p_mad_pool,
+    p_subn,
+    p_log,
+    p_lock);
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_lftr_rcv_ctrl_init(
+    &p_sa->lftr_rcv_ctrl,
+    &p_sa->lftr_rcv,
+    p_log,
+    p_disp );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_sir_rcv_init(
+    &p_sa->sir_rcv,
+    &p_sa->resp,
+    p_sa->p_mad_pool,
+    p_subn,
+    p_log,
+    p_lock);
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_sir_rcv_ctrl_init(
+    &p_sa->sir_rcv_ctrl,
+    &p_sa->sir_rcv,
+    p_log,
+    p_disp );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_mftr_rcv_init(
+    &p_sa->mftr_rcv,
+    &p_sa->resp,
+    p_sa->p_mad_pool,
+    p_subn,
+    p_log,
+    p_lock);
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_mftr_rcv_ctrl_init(
+    &p_sa->mftr_rcv_ctrl,
+    &p_sa->mftr_rcv,
+    p_log,
+    p_disp );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sa_bind(
+  IN osm_sa_t* const p_sa,
+  IN const ib_net64_t port_guid )
+{
+  ib_api_status_t status;
+
+  OSM_LOG_ENTER( p_sa->p_log, osm_sa_bind );
+
+  status = osm_sa_mad_ctrl_bind(
+    &p_sa->mad_ctrl, port_guid );
+
+  OSM_LOG_EXIT( p_sa->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ *  SA DB Dumper
+ *
+ */
+
+struct opensm_dump_context {
+       osm_opensm_t *p_osm;
+       FILE *file;
+};
+
+static int
+opensm_dump_to_file(osm_opensm_t *p_osm, const char *file_name,
+                   void (*dump_func)(osm_opensm_t *p_osm, FILE *file))
+{
+       char path[1024];
+       FILE  *file;
+
+       snprintf(path, sizeof(path), "%s/%s",
+                p_osm->subn.opt.dump_files_dir, file_name);
+
+       file = fopen(path, "w");
+       if (!file) {
+               osm_log(&p_osm->log, OSM_LOG_ERROR,
+                       "opensm_dump_to_file: ERR 0000: "
+                       "cannot open file \'%s\': %s\n",
+                       file_name, strerror(errno));
+               return -1;
+       }
+
+       chmod(path, S_IRUSR|S_IWUSR);
+
+       dump_func(p_osm, file);
+
+       fclose(file);
+       return 0;
+}
+
+static void
+mcast_mgr_dump_one_port(cl_map_item_t *p_map_item, void *cxt)
+{
+       FILE *file = ((struct opensm_dump_context *)cxt)->file;
+       osm_mcm_port_t *p_mcm_port = (osm_mcm_port_t *)p_map_item;
+
+       fprintf(file, "mcm_port: "
+               "port_gid=0x%016" PRIx64 ":0x%016" PRIx64 " "
+               "scope_state=0x%02x proxy_join=0x%x" "\n\n",
+               cl_ntoh64(p_mcm_port->port_gid.unicast.prefix),
+               cl_ntoh64(p_mcm_port->port_gid.unicast.interface_id),
+               p_mcm_port->scope_state,
+               p_mcm_port->proxy_join);
+}
+
+static void
+sa_dump_one_mgrp(cl_map_item_t *p_map_item, void *cxt)
+{
+       struct opensm_dump_context dump_context;
+       osm_opensm_t *p_osm = ((struct opensm_dump_context *)cxt)->p_osm;
+       FILE *file = ((struct opensm_dump_context *)cxt)->file;
+       osm_mgrp_t *p_mgrp = (osm_mgrp_t *)p_map_item;
+
+       fprintf(file, "MC Group 0x%04x %s:"
+               " mgid=0x%016" PRIx64 ":0x%016" PRIx64
+               " port_gid=0x%016" PRIx64 ":0x%016" PRIx64
+               " qkey=0x%08x mlid=0x%04x mtu=0x%02x tclass=0x%02x"
+               " pkey=0x%04x rate=0x%02x pkt_life=0x%02x sl_flow_hop=0x%08x"
+               " scope_state=0x%02x proxy_join=0x%x" "\n\n",
+               cl_ntoh16(p_mgrp->mlid),
+               p_mgrp->well_known ? " (well known)" : "",
+               cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix),
+               cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id),
+               cl_ntoh64(p_mgrp->mcmember_rec.port_gid.unicast.prefix),
+               cl_ntoh64(p_mgrp->mcmember_rec.port_gid.unicast.interface_id),
+               cl_ntoh32(p_mgrp->mcmember_rec.qkey),
+               cl_ntoh16(p_mgrp->mcmember_rec.mlid),
+               p_mgrp->mcmember_rec.mtu,
+               p_mgrp->mcmember_rec.tclass,
+               cl_ntoh16(p_mgrp->mcmember_rec.pkey),
+               p_mgrp->mcmember_rec.rate,
+               p_mgrp->mcmember_rec.pkt_life,
+               cl_ntoh32(p_mgrp->mcmember_rec.sl_flow_hop),
+               p_mgrp->mcmember_rec.scope_state,
+               p_mgrp->mcmember_rec.proxy_join
+               );
+
+       dump_context.p_osm = p_osm;
+       dump_context.file = file;
+
+       cl_qmap_apply_func(&p_mgrp->mcm_port_tbl,
+                          mcast_mgr_dump_one_port, &dump_context);
+}
+
+static void
+sa_dump_one_inform(cl_list_item_t *p_list_item, void *cxt)
+{
+       FILE *file = ((struct opensm_dump_context *)cxt)->file;
+       osm_infr_t *p_infr = (osm_infr_t *)p_list_item;
+       ib_inform_info_record_t *p_iir = &p_infr->inform_record;
+
+       fprintf(file, "InformInfo Record:"
+               " subscriber_gid=0x%016" PRIx64 ":0x%016" PRIx64
+               " subscriber_enum=0x%x"
+               " InformInfo:"
+               " gid=0x%016" PRIx64 ":0x%016" PRIx64
+               " lid_range_begin=0x%x"
+               " lid_range_end=0x%x"
+               " is_generic=0x%x"
+               " subscribe=0x%x"
+               " trap_type=0x%x"
+               " trap_num=0x%x"
+               " qpn_resp_time_val=0x%x"
+               " node_type=0x%06x"
+               " rep_addr: lid=0x%04x path_bits=0x%02x static_rate=0x%02x"
+               " remote_qp=0x%08x remote_qkey=0x%08x pkey=0x%04x sl=0x%02x"
+               "\n\n",
+               cl_ntoh64(p_iir->subscriber_gid.unicast.prefix),
+               cl_ntoh64(p_iir->subscriber_gid.unicast.interface_id),
+               cl_ntoh16(p_iir->subscriber_enum),
+               cl_ntoh64(p_iir->inform_info.gid.unicast.prefix),
+               cl_ntoh64(p_iir->inform_info.gid.unicast.interface_id),
+               cl_ntoh16(p_iir->inform_info.lid_range_begin),
+               cl_ntoh16(p_iir->inform_info.lid_range_end),
+               p_iir->inform_info.is_generic,
+               p_iir->inform_info.subscribe,
+               cl_ntoh16(p_iir->inform_info.trap_type),
+               cl_ntoh16(p_iir->inform_info.g_or_v.generic.trap_num),
+               cl_ntoh32(p_iir->inform_info.g_or_v.generic.qpn_resp_time_val),
+               cl_ntoh32(ib_inform_info_get_node_type(&p_iir->inform_info)),
+               cl_ntoh16(p_infr->report_addr.dest_lid),
+               p_infr->report_addr.path_bits,
+               p_infr->report_addr.static_rate,
+               cl_ntoh32(p_infr->report_addr.addr_type.gsi.remote_qp),
+               cl_ntoh32(p_infr->report_addr.addr_type.gsi.remote_qkey),
+               cl_ntoh16(p_infr->report_addr.addr_type.gsi.pkey),
+               p_infr->report_addr.addr_type.gsi.service_level);
+}
+
+static void
+sa_dump_one_service(cl_list_item_t *p_list_item, void *cxt)
+{
+       FILE *file = ((struct opensm_dump_context *)cxt)->file;
+       osm_svcr_t *p_svcr = (osm_svcr_t *)p_list_item;
+       ib_service_record_t *p_sr = &p_svcr->service_record;
+
+       fprintf(file, "Service Record: id=0x%016" PRIx64
+               " gid=0x%016" PRIx64 ":0x%016" PRIx64
+               " pkey=0x%x"
+               " lease=0x%x"
+               " key=0x%02x%02x%02x%02x%02x%02x%02x%02x"
+               ":0x%02x%02x%02x%02x%02x%02x%02x%02x"
+               " name=\'%s\'"
+               " data8=0x%02x%02x%02x%02x%02x%02x%02x%02x"
+               ":0x%02x%02x%02x%02x%02x%02x%02x%02x"
+               " data16=0x%04x%04x%04x%04x:0x%04x%04x%04x%04x"
+               " data32=0x%08x%08x:0x%08x%08x"
+               " data64=0x%016" PRIx64 ":0x%016" PRIx64
+               " modified_time=0x%x lease_period=0x%x\n\n",
+               cl_ntoh64( p_sr->service_id ),
+               cl_ntoh64( p_sr->service_gid.unicast.prefix ),
+               cl_ntoh64( p_sr->service_gid.unicast.interface_id ),
+               cl_ntoh16( p_sr->service_pkey ),
+               cl_ntoh32( p_sr->service_lease ),
+               p_sr->service_key[0], p_sr->service_key[1],
+               p_sr->service_key[2], p_sr->service_key[3],
+               p_sr->service_key[4], p_sr->service_key[5],
+               p_sr->service_key[6], p_sr->service_key[7],
+               p_sr->service_key[8], p_sr->service_key[9],
+               p_sr->service_key[10], p_sr->service_key[11],
+               p_sr->service_key[12], p_sr->service_key[13],
+               p_sr->service_key[14], p_sr->service_key[15],
+               p_sr->service_name,
+               p_sr->service_data8[0], p_sr->service_data8[1],
+               p_sr->service_data8[2], p_sr->service_data8[3],
+               p_sr->service_data8[4], p_sr->service_data8[5],
+               p_sr->service_data8[6], p_sr->service_data8[7],
+               p_sr->service_data8[8], p_sr->service_data8[9],
+               p_sr->service_data8[10], p_sr->service_data8[11],
+               p_sr->service_data8[12], p_sr->service_data8[13],
+               p_sr->service_data8[14], p_sr->service_data8[15],
+               cl_ntoh16(p_sr->service_data16[0]),
+               cl_ntoh16(p_sr->service_data16[1]),
+               cl_ntoh16(p_sr->service_data16[2]),
+               cl_ntoh16(p_sr->service_data16[3]),
+               cl_ntoh16(p_sr->service_data16[4]),
+               cl_ntoh16(p_sr->service_data16[5]),
+               cl_ntoh16(p_sr->service_data16[6]),
+               cl_ntoh16(p_sr->service_data16[7]),
+               cl_ntoh32(p_sr->service_data32[0]),
+               cl_ntoh32(p_sr->service_data32[1]),
+               cl_ntoh32(p_sr->service_data32[2]),
+               cl_ntoh32(p_sr->service_data32[3]),
+               cl_ntoh64(p_sr->service_data64[0]),
+               cl_ntoh64(p_sr->service_data64[1]),
+               p_svcr->modified_time, p_svcr->lease_period);
+}
+
+static void
+sa_dump_all_sa(osm_opensm_t *p_osm, FILE *file)
+{
+       struct opensm_dump_context dump_context;
+
+       dump_context.p_osm = p_osm;
+       dump_context.file = file;
+       osm_log(&p_osm->log, OSM_LOG_DEBUG, "sa_dump_all_sa: Dump multicast:\n");
+       cl_plock_acquire(&p_osm->lock);
+       cl_qmap_apply_func(&p_osm->subn.mgrp_mlid_tbl,
+                          sa_dump_one_mgrp, &dump_context);
+       osm_log(&p_osm->log, OSM_LOG_DEBUG, "sa_dump_all_sa: Dump inform:\n");
+       cl_qlist_apply_func(&p_osm->subn.sa_infr_list,
+                           sa_dump_one_inform, &dump_context);
+       osm_log(&p_osm->log, OSM_LOG_DEBUG, "sa_dump_all_sa: Dump services:\n");
+       cl_qlist_apply_func(&p_osm->subn.sa_sr_list,
+                           sa_dump_one_service, &dump_context);
+       cl_plock_release(&p_osm->lock);
+}
+
+int osm_sa_db_file_dump(osm_opensm_t *p_osm)
+{
+       return opensm_dump_to_file(p_osm, "opensm-sa.dump", sa_dump_all_sa);
+}
+
+/*
+ *  SA DB Loader
+ *
+ */
+
+osm_mgrp_t *load_mcgroup(osm_opensm_t *p_osm, ib_net16_t mlid,
+                        ib_member_rec_t *p_mcm_rec, unsigned well_known)
+{
+       ib_net64_t comp_mask;
+       cl_map_item_t *p_next;
+       osm_mgrp_t *p_mgrp;
+
+       cl_plock_excl_acquire(&p_osm->lock);
+
+       if ((p_next = cl_qmap_get(&p_osm->subn.mgrp_mlid_tbl, mlid)) !=
+            cl_qmap_end(&p_osm->subn.mgrp_mlid_tbl)) {
+               p_mgrp = (osm_mgrp_t *)p_next;
+               if (!memcmp(&p_mgrp->mcmember_rec.mgid, &p_mcm_rec->mgid,
+                           sizeof(ib_gid_t))) {
+                       osm_log(&p_osm->log, OSM_LOG_DEBUG,
+                               "load_mcgroup: mgrp %04x is already here.",
+                               cl_ntoh16(mlid));
+                       goto _out;
+               }
+               osm_log(&p_osm->log, OSM_LOG_VERBOSE,
+                       "load_mcgroup: mlid %04x is already used by another "
+                       "MC group. Will request clients reregistration.\n",
+                       cl_ntoh16(mlid));
+               p_mgrp = NULL;
+               goto _out;
+        }
+
+       comp_mask = IB_MCR_COMPMASK_MTU | IB_MCR_COMPMASK_MTU_SEL
+                       | IB_MCR_COMPMASK_RATE | IB_MCR_COMPMASK_RATE_SEL;
+       if (osm_mcmr_rcv_find_or_create_new_mgrp(&p_osm->sa.mcmr_rcv,
+                                                comp_mask, p_mcm_rec,
+                                                &p_mgrp) != IB_SUCCESS ||
+           !p_mgrp || p_mgrp->mlid != mlid) {
+               osm_log(&p_osm->log, OSM_LOG_ERROR,
+                       "load_mcgroup: cannot create MC group with mlid "
+                       "0x%04x and mgid 0x%016" PRIx64 ":0x%016" PRIx64 "\n",
+                       cl_ntoh16(mlid),
+                       cl_ntoh64(p_mcm_rec->mgid.unicast.prefix),
+                       cl_ntoh64(p_mcm_rec->mgid.unicast.interface_id));
+               p_mgrp=NULL;
+       }
+       else if (well_known)
+               p_mgrp->well_known = TRUE;
+
+  _out:
+       cl_plock_release(&p_osm->lock);
+
+       return p_mgrp;
+}
+
+static int load_svcr(osm_opensm_t *p_osm, ib_service_record_t *sr,
+                    uint32_t modified_time, uint32_t lease_period)
+{
+       osm_svcr_t *p_svcr;
+       int ret = 0;
+
+       cl_plock_excl_acquire(&p_osm->lock);
+
+       if(osm_svcr_get_by_rid(&p_osm->subn, &p_osm->log, sr)) {
+               osm_log(&p_osm->log, OSM_LOG_VERBOSE,
+                       "load_svcr ServiceRecord already exists.\n");
+               goto _out;
+       }
+
+       if (!(p_svcr = osm_svcr_new(sr))) {
+               osm_log(&p_osm->log, OSM_LOG_ERROR,
+                       "load_svcr: cannot allocate new service struct\n");
+               ret = -1;
+               goto _out;
+       }
+
+       p_svcr->modified_time = modified_time;
+       p_svcr->lease_period = lease_period;
+
+       osm_log(&p_osm->log, OSM_LOG_DEBUG,
+               "load_svcr: adding ServiceRecord...\n");
+
+       osm_svcr_insert_to_db(&p_osm->subn, &p_osm->log, p_svcr);
+
+       if (lease_period != 0xffffffff)
+               cl_timer_trim(&p_osm->sa.sr_rcv.sr_timer, 1000);
+
+  _out:
+       cl_plock_release(&p_osm->lock);
+
+       return ret;
+}
+
+static int load_infr(osm_opensm_t *p_osm, ib_inform_info_record_t *iir,
+                    osm_mad_addr_t *addr)
+{
+       osm_infr_t infr, *p_infr;
+       int ret = 0;
+
+       infr.h_bind = p_osm->sa.mad_ctrl.h_bind;
+       infr.p_infr_rcv = &p_osm->sa.infr_rcv;
+       /* other possible way to restore mad_addr partially is
+          to extract qpn from InformInfo and to find lid by gid */
+       infr.report_addr = *addr;
+       infr.inform_record = *iir;
+
+       cl_plock_excl_acquire(&p_osm->lock);
+       if (osm_infr_get_by_rec(&p_osm->subn, &p_osm->log, &infr)) {
+               osm_log(&p_osm->log, OSM_LOG_VERBOSE,
+                       "load_infr: InformInfo Record already exists\n");
+               goto _out;
+       }
+
+       if (!(p_infr = osm_infr_new(&infr))) {
+               osm_log(&p_osm->log, OSM_LOG_ERROR,
+                       "load_infr: cannot allocate new infr struct\n");
+               ret = -1;
+               goto _out;
+       }
+
+       osm_log(&p_osm->log, OSM_LOG_DEBUG,
+               "load_infr: adding InformInfo Record...\n");
+
+       osm_infr_insert_to_db(&p_osm->subn, &p_osm->log, p_infr);
+
+  _out:
+       cl_plock_release(&p_osm->lock);
+
+       return ret;
+}
+
+
+#define UNPACK_FUNC(name,x) \
+int unpack_##name##x(char *p, uint##x##_t *val_ptr) \
+{ \
+       char *q; \
+       unsigned long long num; \
+       num = strtoull(p, &q, 16); \
+       if (num > ~((uint##x##_t)0x0) \
+           || q == p || (!isspace(*q) && *q != ':')) { \
+               *val_ptr = 0; \
+               return -1; \
+       } \
+       *val_ptr = cl_hton##x((uint##x##_t)num); \
+       return (int)(q - p); \
+}
+
+#define cl_hton8(x) (x)
+
+UNPACK_FUNC(net,8);
+UNPACK_FUNC(net,16);
+UNPACK_FUNC(net,32);
+UNPACK_FUNC(net,64);
+
+static int unpack_string(char *p, uint8_t *buf, unsigned len)
+{
+       char *q = p;
+       char delim = ' ';
+
+       if (*q == '\'' || *q == '\"')
+               delim = *q++;
+       while (--len && *q && *q != delim)
+               *buf++ = *q++;
+       *buf = '\0';
+       if (*q == delim && delim != ' ')
+               q++;
+       return (int)(q - p);
+}
+
+static int unpack_string64(char *p, uint8_t *buf)
+{
+       return unpack_string(p, buf, 64);
+}
+
+#define PARSE_AHEAD(p, x, name, val_ptr) { int _ret; \
+       p = strstr(p, name); \
+       if (!p) { \
+               osm_log(&p_osm->log, OSM_LOG_ERROR, \
+                       "PARSE ERROR: %s:%u: cannot find \"%s\" string\n", \
+                       file_name, lineno, (name)); \
+               ret = -2; \
+               goto _error; \
+       } \
+       p += strlen(name); \
+       _ret = unpack_##x(p, (val_ptr)); \
+       if (_ret < 0) { \
+               osm_log(&p_osm->log, OSM_LOG_ERROR, \
+                       "PARSE ERROR: %s:%u: cannot parse "#x" value " \
+                       "after \"%s\"\n", file_name, lineno, (name)); \
+               ret = _ret; \
+               goto _error; \
+       } \
+       p += _ret; \
+}
+
+int osm_sa_db_file_load(osm_opensm_t *p_osm)
+{
+       char line[1024];
+       char *file_name;
+       FILE *file;
+       int ret = 0;
+       osm_mgrp_t *p_mgrp = NULL;
+       unsigned rereg_clients = 0;
+       unsigned lineno;
+
+       file_name = p_osm->subn.opt.sa_db_file;
+       if (!file_name) {
+               osm_log(&p_osm->log, OSM_LOG_VERBOSE,
+                       "osm_sa_db_file_load: sa db file name is not "
+                       "specifed. Skip restore\n");
+               return 0;
+       }
+
+       file = fopen(file_name, "r");
+       if (!file) {
+               osm_log(&p_osm->log, OSM_LOG_ERROR|OSM_LOG_SYS,
+                       "osm_sa_db_file_load: ERR 0000: "
+                       "cannot open sa db file \'%s\'. "
+                       "Skip restoring\n", file_name);
+               return -1;
+       }
+
+       lineno = 0;
+
+       while (fgets(line, sizeof(line) - 1, file) != NULL) {
+               char *p;
+               uint8_t val;
+
+               lineno++;
+
+               p = line;
+               while (isspace(*p))
+                       p++;
+
+               if (*p == '#')
+                       continue;
+
+               if (!strncmp(p, "MC Group", 8)) {
+                       ib_member_rec_t mcm_rec;
+                       ib_net16_t mlid;
+                       unsigned well_known = 0;
+
+                       p_mgrp = NULL;
+                       memset(&mcm_rec, 0, sizeof(mcm_rec));
+
+                       PARSE_AHEAD(p, net16, " 0x", &mlid);
+                       if(strstr(p, "well known"))
+                               well_known = 1;
+                       PARSE_AHEAD(p, net64, " mgid=0x",
+                                   &mcm_rec.mgid.unicast.prefix);
+                       PARSE_AHEAD(p, net64, ":0x",
+                                   &mcm_rec.mgid.unicast.interface_id);
+                       PARSE_AHEAD(p, net64, " port_gid=0x",
+                                   &mcm_rec.port_gid.unicast.prefix);
+                       PARSE_AHEAD(p, net64, ":0x",
+                                   &mcm_rec.port_gid.unicast.interface_id);
+                       PARSE_AHEAD(p, net32, " qkey=0x", &mcm_rec.qkey);
+                       PARSE_AHEAD(p, net16, " mlid=0x", &mcm_rec.mlid);
+                       PARSE_AHEAD(p, net8, " mtu=0x", &mcm_rec.mtu);
+                       PARSE_AHEAD(p, net8, " tclass=0x", &mcm_rec.tclass);
+                       PARSE_AHEAD(p, net16, " pkey=0x", &mcm_rec.pkey);
+                       PARSE_AHEAD(p, net8, " rate=0x", &mcm_rec.rate);
+                       PARSE_AHEAD(p, net8, " pkt_life=0x", &mcm_rec.pkt_life);
+                       PARSE_AHEAD(p, net32, " sl_flow_hop=0x",
+                                   &mcm_rec.sl_flow_hop);
+                       PARSE_AHEAD(p, net8, " scope_state=0x",
+                                   &mcm_rec.scope_state);
+                       PARSE_AHEAD(p, net8, " proxy_join=0x", &val);
+                       mcm_rec.proxy_join = val;
+
+                       p_mgrp = load_mcgroup(p_osm, mlid, &mcm_rec,
+                                             well_known);
+                       if (!p_mgrp)
+                               rereg_clients = 1;
+               }
+               else if (p_mgrp && !strncmp(p, "mcm_port", 8)) {
+                       ib_gid_t port_gid;
+                       ib_net64_t guid;
+                       uint8_t scope_state;
+                       boolean_t proxy_join;
+
+                       PARSE_AHEAD(p, net64, " port_gid=0x",
+                                   &port_gid.unicast.prefix);
+                       PARSE_AHEAD(p, net64, ":0x",
+                                   &port_gid.unicast.interface_id);
+                       PARSE_AHEAD(p, net8, " scope_state=0x", &scope_state);
+                       PARSE_AHEAD(p, net8, " proxy_join=0x", &val);
+                       proxy_join = val;
+
+                       guid = port_gid.unicast.interface_id;
+                       if (cl_qmap_get(&p_mgrp->mcm_port_tbl,
+                                       port_gid.unicast.interface_id) ==
+                               cl_qmap_end(&p_mgrp->mcm_port_tbl))
+                               osm_mgrp_add_port(p_mgrp, &port_gid,
+                                                 scope_state, proxy_join);
+               }
+               else if (!strncmp(p, "Service Record:", 15)) {
+                       ib_service_record_t s_rec;
+                       uint32_t modified_time, lease_period;
+
+                       p_mgrp = NULL;
+                       memset(&s_rec, 0, sizeof(s_rec));
+
+                       PARSE_AHEAD(p, net64, " id=0x", &s_rec.service_id);
+                       PARSE_AHEAD(p, net64, " gid=0x",
+                                   &s_rec.service_gid.unicast.prefix);
+                       PARSE_AHEAD(p, net64, ":0x",
+                                   &s_rec.service_gid.unicast.interface_id);
+                       PARSE_AHEAD(p, net16, " pkey=0x", &s_rec.service_pkey);
+                       PARSE_AHEAD(p, net32, " lease=0x", &s_rec.service_lease);
+                       PARSE_AHEAD(p, net64, " key=0x",
+                                   (ib_net64_t *)(&s_rec.service_key[0]));
+                       PARSE_AHEAD(p, net64, ":0x",
+                                   (ib_net64_t *)(&s_rec.service_key[8]));
+                       PARSE_AHEAD(p, string64, " name=", s_rec.service_name);
+                       PARSE_AHEAD(p, net64, " data8=0x",
+                                   (ib_net64_t *)(&s_rec.service_data8[0]));
+                       PARSE_AHEAD(p, net64, ":0x",
+                                   (ib_net64_t *)(&s_rec.service_data8[8]));
+                       PARSE_AHEAD(p, net64, " data16=0x",
+                                   (ib_net64_t *)(&s_rec.service_data16[0]));
+                       PARSE_AHEAD(p, net64, ":0x",
+                                   (ib_net64_t *)(&s_rec.service_data16[4]));
+                       PARSE_AHEAD(p, net64, " data32=0x",
+                                   (ib_net64_t *)(&s_rec.service_data32[0]));
+                       PARSE_AHEAD(p, net64, ":0x",
+                                   (ib_net64_t *)(&s_rec.service_data32[2]));
+                       PARSE_AHEAD(p, net64, " data64=0x", &s_rec.service_data64[0]);
+                       PARSE_AHEAD(p, net64, ":0x", &s_rec.service_data64[1]);
+                       PARSE_AHEAD(p, net32, " modified_time=0x",
+                                   &modified_time);
+                       PARSE_AHEAD(p, net32, " lease_period=0x",
+                                   &lease_period);
+
+                       if (load_svcr(p_osm, &s_rec, cl_ntoh32(modified_time),
+                                     cl_ntoh32(lease_period)))
+                               rereg_clients = 1;
+               }
+               else if (!strncmp(p, "InformInfo Record:", 18)) {
+                       ib_inform_info_record_t i_rec;
+                       osm_mad_addr_t rep_addr;
+
+                       p_mgrp = NULL;
+                       memset(&i_rec, 0, sizeof(i_rec));
+                       memset(&rep_addr, 0, sizeof(rep_addr));
+
+                       PARSE_AHEAD(p, net64, " subscriber_gid=0x",
+                                   &i_rec.subscriber_gid.unicast.prefix);
+                       PARSE_AHEAD(p, net64, ":0x",
+                                   &i_rec.subscriber_gid.unicast.interface_id);
+                       PARSE_AHEAD(p, net16, " subscriber_enum=0x",
+                                   &i_rec.subscriber_enum);
+                       PARSE_AHEAD(p, net64, " gid=0x",
+                                   &i_rec.inform_info.gid.unicast.prefix);
+                       PARSE_AHEAD(p, net64, ":0x",
+                                   &i_rec.inform_info.gid.unicast.interface_id);
+                       PARSE_AHEAD(p, net16, " lid_range_begin=0x",
+                                   &i_rec.inform_info.lid_range_begin);
+                       PARSE_AHEAD(p, net16, " lid_range_end=0x",
+                                   &i_rec.inform_info.lid_range_end);
+                       PARSE_AHEAD(p, net8, " is_generic=0x",
+                                   &i_rec.inform_info.is_generic);
+                       PARSE_AHEAD(p, net8, " subscribe=0x",
+                                   &i_rec.inform_info.subscribe);
+                       PARSE_AHEAD(p, net16, " trap_type=0x",
+                                   &i_rec.inform_info.trap_type);
+                       PARSE_AHEAD(p, net16, " trap_num=0x",
+                                   &i_rec.inform_info.g_or_v.generic.trap_num);
+                       PARSE_AHEAD(p, net32, " qpn_resp_time_val=0x",
+                                   &i_rec.inform_info.g_or_v.generic.qpn_resp_time_val);
+                       PARSE_AHEAD(p, net32, " node_type=0x",
+                                   (uint32_t *)&i_rec.inform_info.g_or_v.generic.reserved2);
+
+                       PARSE_AHEAD(p, net16, " rep_addr: lid=0x",
+                                   &rep_addr.dest_lid);
+                       PARSE_AHEAD(p, net8, " path_bits=0x",
+                                   &rep_addr.path_bits);
+                       PARSE_AHEAD(p, net8, " static_rate=0x",
+                                   &rep_addr.static_rate);
+                       PARSE_AHEAD(p, net32, " remote_qp=0x",
+                                   &rep_addr.addr_type.gsi.remote_qp);
+                       PARSE_AHEAD(p, net32, " remote_qkey=0x",
+                                   &rep_addr.addr_type.gsi.remote_qkey);
+                       PARSE_AHEAD(p, net16, " pkey=0x",
+                                   &rep_addr.addr_type.gsi.pkey);
+                       PARSE_AHEAD(p, net8, " sl=0x",
+                                   &rep_addr.addr_type.gsi.service_level);
+
+                       if (load_infr(p_osm, &i_rec, &rep_addr))
+                               rereg_clients = 1;
+               }
+       }
+
+       if (!rereg_clients)
+               p_osm->subn.opt.no_clients_rereg = TRUE;
+
+  _error:
+       fclose(file);
+       return ret;
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_class_port_info.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_class_port_info.c
new file mode 100644 (file)
index 0000000..bae104d
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_class_port_info.c 1931 2009-02-04 17:56:23Z stansmith $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_cpi_rcv_t.
+ * This object represents the ClassPortInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.8 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_class_port_info.h>
+#include <vendor/osm_vendor.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+
+#define MAX_MSECS_TO_RTV 24
+/* Precalculated table in msec (index is related to encoded value) */
+/* 4.096 usec * 2 ** n (where n = 8 - 31) */
+static uint32_t __msecs_to_rtv_table[MAX_MSECS_TO_RTV] =
+                                       { 1, 2, 4, 8,
+                                         16, 33, 67, 134, 
+                                         268, 536, 1073, 2147,
+                                         4294, 8589, 17179, 34359,
+                                         68719, 137438, 274877, 549755,
+                                         1099511, 2199023, 4398046, 8796093 };
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_cpi_rcv_construct(
+  IN osm_cpi_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_cpi_rcv_destroy(
+  IN osm_cpi_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_cpi_rcv_destroy );
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_cpi_rcv_init(
+  IN osm_cpi_rcv_t*     const p_rcv,
+  IN osm_sa_resp_t*     const p_resp,
+  IN osm_mad_pool_t*    const p_mad_pool,
+  IN osm_subn_t*        const p_subn,
+  IN osm_log_t*         const p_log,
+  IN cl_plock_t*        const p_lock )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_cpi_rcv_init );
+
+  osm_cpi_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_resp = p_resp;
+  p_rcv->p_mad_pool = p_mad_pool;
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_cpi_rcv_respond(
+  IN osm_cpi_rcv_t*        const p_rcv,
+  IN const osm_madw_t*     const p_madw )
+{
+  osm_madw_t*              p_resp_madw;
+  const ib_sa_mad_t*       p_sa_mad;
+  ib_sa_mad_t*             p_resp_sa_mad;
+  ib_class_port_info_t    *p_resp_cpi;
+  ib_api_status_t          status;
+  ib_gid_t                 zero_gid;
+  uint8_t                  rtv;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_cpi_rcv_respond );
+
+  memset(&zero_gid, 0, sizeof(ib_gid_t));
+
+  /*
+    Get a MAD to reply. Address of Mad is in the received mad_wrapper
+  */
+  p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, 
+                                  p_madw->h_bind,
+                                  MAD_BLOCK_SIZE,
+                                  &p_madw->mad_addr );
+  if( !p_resp_madw )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_cpi_rcv_respond: ERR 1408: "
+             "Unable to allocate MAD\n" );
+    goto Exit;
+  }
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+  memcpy( p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+  /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
+  p_resp_sa_mad->sm_key = 0;
+
+  p_resp_cpi = (ib_class_port_info_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+  /* finally do it (the job) man ! */
+  p_resp_cpi->base_ver = 1;
+  p_resp_cpi->class_ver = 2;
+  /* Calculate encoded response time value */
+  /* transaction timeout is in msec */
+  if (p_rcv->p_subn->opt.transaction_timeout > __msecs_to_rtv_table[MAX_MSECS_TO_RTV])
+    rtv = MAX_MSECS_TO_RTV - 1;
+  else
+  {
+    for (rtv = 0; rtv < MAX_MSECS_TO_RTV; rtv++) {
+      if (p_rcv->p_subn->opt.transaction_timeout <= __msecs_to_rtv_table[rtv])
+         break;
+    }
+  }
+  rtv += 8;
+  p_resp_cpi->cap_mask2_resp_time = rtv;
+  p_resp_cpi->redir_gid = zero_gid;
+  p_resp_cpi->redir_tc_sl_fl = 0;
+  p_resp_cpi->redir_lid = 0;
+  p_resp_cpi->redir_pkey = 0;
+  p_resp_cpi->redir_qp = CL_NTOH32(1);
+  p_resp_cpi->redir_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
+  p_resp_cpi->trap_gid = zero_gid;
+  p_resp_cpi->trap_tc_sl_fl = 0;
+  p_resp_cpi->trap_lid = 0;
+  p_resp_cpi->trap_pkey = 0;
+  p_resp_cpi->trap_hop_qp = 0;
+  p_resp_cpi->trap_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
+
+  /* set specific capability mask bits */
+  /* we do not support the following optional records:
+     OSM_CAP_IS_SUBN_OPT_RECS_SUP :
+     RandomForwardingTableRecord,
+     ServiceAssociationRecord
+     other optional records supported "under the table"
+
+     OSM_CAP_IS_MULTIPATH_SUP:
+     TraceRecord
+
+     OSM_CAP_IS_REINIT_SUP:
+     For reinitialization functionality.
+
+     So not sending traps, but supporting Get(Notice) and Set(Notice).
+  */
+
+  /* Note host notation replaced later */
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+  p_resp_cpi->cap_mask = OSM_CAP_IS_SUBN_GET_SET_NOTICE_SUP |
+                         OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED |
+                         OSM_CAP_IS_MULTIPATH_SUP;
+#else
+  p_resp_cpi->cap_mask = OSM_CAP_IS_SUBN_GET_SET_NOTICE_SUP |
+                        OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED;
+#endif
+  if (p_rcv->p_subn->opt.no_multicast_option != TRUE)
+    p_resp_cpi->cap_mask |= OSM_CAP_IS_UD_MCAST_SUP;
+  p_resp_cpi->cap_mask = cl_hton16(p_resp_cpi->cap_mask);
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_FRAMES ) )
+    osm_dump_sa_mad( p_rcv->p_log, p_resp_sa_mad, OSM_LOG_FRAMES );
+
+  status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw,  FALSE );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_cpi_rcv_respond: ERR 1409: "
+             "Unable to send MAD (%s)\n", ib_get_err_str( status ) );
+    /*  osm_mad_pool_put( p_rcv->p_mad_pool, p_resp_madw ); */
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ * This code actually handles the call
+ **********************************************************************/
+void
+osm_cpi_rcv_process(
+  IN osm_cpi_rcv_t*        const p_rcv,
+  IN const osm_madw_t*     const p_madw )
+{
+  const ib_path_rec_t*     p_pr;
+  const ib_sa_mad_t*    p_sa_mad;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_cpi_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+
+  /* we only support GET */
+  if (p_sa_mad->method != IB_MAD_METHOD_GET)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_cpi_rcv_process: ERR 1403: "
+             "Unsupported Method (%s)\n",
+             ib_get_sa_method_str( p_sa_mad->method ) );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+    goto Exit;
+  }
+
+  p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+  CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_CLASS_PORT_INFO );
+
+  /*
+    CLASS PORT INFO does not really look on the SMDB - no lock required.
+  */
+
+  __osm_cpi_rcv_respond( p_rcv, p_madw);
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_class_port_info_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_class_port_info_ctrl.c
new file mode 100644 (file)
index 0000000..22ad8f3
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_class_port_info_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_pr_rcv_ctrl_t.
+ * This object represents the ClassPortInfo request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_class_port_info_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_cpi_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_cpi_rcv_process( ((osm_cpi_rcv_ctrl_t*)context)->p_rcv,
+                       (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_cpi_rcv_ctrl_construct(
+  IN osm_cpi_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_cpi_rcv_ctrl_destroy(
+  IN osm_cpi_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_cpi_rcv_ctrl_init(
+  IN osm_cpi_rcv_ctrl_t* const p_ctrl,
+  IN osm_cpi_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_cpi_rcv_ctrl_init );
+
+  osm_cpi_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_CLASS_PORT_INFO,
+    __osm_cpi_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_cpi_rcv_ctrl_init: ERR 1501: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_guidinfo_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_guidinfo_record.c
new file mode 100644 (file)
index 0000000..90618b9
--- /dev/null
@@ -0,0 +1,611 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_guidinfo_record.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_gir_rcv_t.
+ * This object represents the GUIDInfoRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_guidinfo_record.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_GIR_RCV_POOL_MIN_SIZE      32
+#define OSM_GIR_RCV_POOL_GROW_SIZE     32
+
+typedef  struct _osm_gir_item
+{
+  cl_pool_item_t           pool_item;
+  ib_guidinfo_record_t     rec;
+} osm_gir_item_t;
+
+typedef  struct _osm_gir_search_ctxt
+{
+  const ib_guidinfo_record_t* p_rcvd_rec;
+  ib_net64_t               comp_mask;
+  cl_qlist_t*              p_list;
+  osm_gir_rcv_t*           p_rcv;
+  const osm_physp_t*       p_req_physp;
+} osm_gir_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_gir_rcv_construct(
+  IN osm_gir_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+  cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_gir_rcv_destroy(
+  IN osm_gir_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_gir_rcv_destroy );
+  cl_qlock_pool_destroy( &p_rcv->pool );
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_gir_rcv_init(
+  IN osm_gir_rcv_t*        const p_rcv,
+  IN osm_sa_resp_t*        const p_resp,
+  IN osm_mad_pool_t*       const p_mad_pool,
+  IN const osm_subn_t*     const p_subn,
+  IN osm_log_t*            const p_log,
+  IN cl_plock_t*           const p_lock )
+{
+  ib_api_status_t          status;
+
+  OSM_LOG_ENTER( p_log, osm_gir_rcv_init );
+
+  osm_gir_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_resp = p_resp;
+  p_rcv->p_mad_pool = p_mad_pool;
+
+  status = cl_qlock_pool_init( &p_rcv->pool,
+                               OSM_GIR_RCV_POOL_MIN_SIZE,
+                               0,
+                               OSM_GIR_RCV_POOL_GROW_SIZE,
+                               sizeof(osm_gir_item_t),
+                               NULL, NULL, NULL );
+
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_gir_rcv_new_gir(
+  IN osm_gir_rcv_t*        const p_rcv,
+  IN const osm_node_t*     const p_node,
+  IN cl_qlist_t*           const p_list,
+  IN ib_net64_t            const match_port_guid,
+  IN ib_net16_t            const match_lid,
+  IN const osm_physp_t*    const p_req_physp,
+  IN uint8_t               const block_num )
+{
+  osm_gir_item_t*          p_rec_item;
+  ib_api_status_t          status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_gir_rcv_new_gir );
+
+  p_rec_item = (osm_gir_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+  if( p_rec_item == NULL )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_gir_rcv_new_gir: ERR 5102: "
+             "cl_qlock_pool_get failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_gir_rcv_new_gir: "
+             "New GUIDInfoRecord: lid 0x%X, block num %d\n",
+             cl_ntoh16( match_lid ), block_num );
+  }
+
+  memset( &p_rec_item->rec, 0, sizeof( p_rec_item->rec ) );
+
+  p_rec_item->rec.lid = match_lid;
+  p_rec_item->rec.block_num = block_num;
+  if (!block_num)
+    p_rec_item->rec.guid_info.guid[0] = osm_physp_get_port_guid( p_req_physp );
+
+  cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_gir_create_gir(
+  IN osm_gir_rcv_t*        const p_rcv,
+  IN const osm_node_t*     const p_node,
+  IN cl_qlist_t*           const p_list,
+  IN ib_net64_t            const match_port_guid,
+  IN ib_net16_t            const match_lid,
+  IN const osm_physp_t*    const p_req_physp,
+  IN uint8_t               const match_block_num )
+{
+  const osm_physp_t*       p_physp;
+  uint8_t                  port_num;
+  uint8_t                  num_ports;
+  uint16_t                 match_lid_ho;
+  ib_net16_t               base_lid_ho;
+  ib_net16_t               max_lid_ho;
+  uint8_t                  lmc;
+  ib_net64_t               port_guid;
+  const ib_port_info_t*    p_pi;
+  uint8_t                  block_num, start_block_num, end_block_num, num_blocks;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_gir_create_gir );
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_sa_gir_create_gir: "
+             "Looking for GUIDRecord with LID: 0x%X GUID:0x%016" PRIx64 "\n",
+             cl_ntoh16( match_lid ),
+             cl_ntoh64( match_port_guid )
+             );
+  }
+
+  /*
+    For switches, do not return the GUIDInfo record(s)
+    for each port on the switch, just for port 0.
+  */
+  if( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH )
+    num_ports = 1;
+  else
+    num_ports = osm_node_get_num_physp( p_node );
+
+  for( port_num = 0; port_num < num_ports; port_num++ )
+  {
+    p_physp = osm_node_get_physp_ptr( p_node, port_num );
+
+    if( !osm_physp_is_valid( p_physp ) )
+      continue;
+
+    /* Check to see if the found p_physp and the requester physp
+       share a pkey. If not, continue */
+    if (!osm_physp_share_pkey( p_rcv->p_log, p_physp, p_req_physp ) )
+      continue;
+
+    port_guid = osm_physp_get_port_guid( p_physp );
+
+    if( match_port_guid && ( port_guid != match_port_guid ) )
+      continue;
+
+    p_pi = osm_physp_get_port_info_ptr( p_physp );
+
+    /*
+       Note: the following check is a temporary workaround
+       Since 1. GUIDCap should never be 0 on ports where this applies
+       and   2. GUIDCap should not be used on ports where it doesn't apply
+       So this should really be a check for whether the port is a 
+       switch external port or not!
+     */
+    if ( p_pi->guid_cap == 0 )  
+      continue;
+
+    num_blocks = p_pi->guid_cap / 8;
+    if ( p_pi->guid_cap % 8 )
+      num_blocks++;
+    if ( match_block_num == 255 )
+    {
+      start_block_num = 0;
+      end_block_num = num_blocks - 1;
+    }
+    else
+    {
+      if ( match_block_num >= num_blocks )
+        continue;
+      end_block_num = start_block_num = match_block_num;
+    }
+
+    base_lid_ho = cl_ntoh16( osm_physp_get_base_lid( p_physp ) );
+    match_lid_ho = cl_ntoh16( match_lid );
+    if( match_lid_ho )
+    {
+      lmc = osm_physp_get_lmc( p_physp );
+      max_lid_ho = (uint16_t)( base_lid_ho + (1 << lmc) - 1 );
+
+      /*
+        We validate that the lid belongs to this node.
+      */
+      if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+                 "__osm_sa_gir_create_gir: "
+                 "Comparing LID: 0x%X <= 0x%X <= 0x%X\n",
+                 base_lid_ho, match_lid_ho, max_lid_ho
+                 );
+      }
+
+      if ( match_lid_ho < base_lid_ho || match_lid_ho > max_lid_ho )
+        continue;
+    }
+
+    for (block_num = start_block_num; block_num <= end_block_num; block_num++)
+      __osm_gir_rcv_new_gir( p_rcv, p_node, p_list,
+                             port_guid, cl_ntoh16(base_lid_ho),
+                             p_physp, block_num );
+
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_gir_by_comp_mask_cb(
+  IN cl_map_item_t*            const p_map_item,
+  IN void*                     context )
+{
+  const osm_gir_search_ctxt_t* const p_ctxt = (osm_gir_search_ctxt_t *)context;
+  const osm_node_t*            const p_node = (osm_node_t*)p_map_item;
+  const ib_guidinfo_record_t*  const p_rcvd_rec = p_ctxt->p_rcvd_rec;
+  const osm_physp_t*           const p_req_physp = p_ctxt->p_req_physp;
+  osm_gir_rcv_t*               const p_rcv = p_ctxt->p_rcv;
+  const ib_guid_info_t*        p_comp_gi;
+  ib_net64_t                   const comp_mask = p_ctxt->comp_mask;
+  ib_net64_t                   match_port_guid = 0;
+  ib_net16_t                   match_lid = 0;
+  uint8_t                      match_block_num = 255;
+
+  OSM_LOG_ENTER( p_ctxt->p_rcv->p_log, __osm_sa_gir_by_comp_mask_cb);
+
+  if( comp_mask & IB_GIR_COMPMASK_LID )
+     match_lid = p_rcvd_rec->lid;
+
+  if( comp_mask & IB_GIR_COMPMASK_BLOCKNUM )
+    match_block_num = p_rcvd_rec->block_num;
+
+  p_comp_gi = &p_rcvd_rec->guid_info;
+  /* Different rule for block 0 v. other blocks */
+  if( comp_mask & IB_GIR_COMPMASK_GID0 )
+  {
+    if ( !p_rcvd_rec->block_num )
+      match_port_guid = osm_physp_get_port_guid( p_req_physp );
+    if ( p_comp_gi->guid[0] != match_port_guid )
+      goto Exit;
+  }
+
+  if( comp_mask & IB_GIR_COMPMASK_GID1 )
+  {
+    if ( p_comp_gi->guid[1] != 0)
+      goto Exit;
+  }
+
+  if( comp_mask & IB_GIR_COMPMASK_GID2 )
+  {
+    if ( p_comp_gi->guid[2] != 0)
+      goto Exit;
+  }
+
+  if( comp_mask & IB_GIR_COMPMASK_GID3 )
+  {
+    if ( p_comp_gi->guid[3] != 0)
+      goto Exit;
+  }
+
+  if( comp_mask & IB_GIR_COMPMASK_GID4 )
+  {
+    if ( p_comp_gi->guid[4] != 0)
+      goto Exit;
+  }
+
+  if( comp_mask & IB_GIR_COMPMASK_GID5 )
+  {
+    if ( p_comp_gi->guid[5] != 0)
+      goto Exit;
+  }
+
+  if( comp_mask & IB_GIR_COMPMASK_GID6 )
+  {
+    if ( p_comp_gi->guid[6] != 0)
+      goto Exit;
+  }
+
+  if( comp_mask & IB_GIR_COMPMASK_GID7 )
+  {
+    if ( p_comp_gi->guid[7] != 0)
+      goto Exit;
+  }
+
+  __osm_sa_gir_create_gir( p_rcv, p_node, p_ctxt->p_list,
+                           match_port_guid, match_lid, p_req_physp,
+                           match_block_num );
+
+ Exit:
+  OSM_LOG_EXIT( p_ctxt->p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_gir_rcv_process(
+  IN osm_gir_rcv_t*        const p_rcv,
+  IN const osm_madw_t*     const p_madw )
+{
+  const ib_sa_mad_t*       p_rcvd_mad;
+  const ib_guidinfo_record_t* p_rcvd_rec;
+  cl_qlist_t               rec_list;
+  osm_madw_t*              p_resp_madw;
+  ib_sa_mad_t*             p_resp_sa_mad;
+  ib_guidinfo_record_t*    p_resp_rec;
+  uint32_t                 num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  uint32_t                trim_num_rec;
+#endif
+  uint32_t                 i;
+  osm_gir_search_ctxt_t    context;
+  osm_gir_item_t*          p_rec_item;
+  ib_api_status_t          status;
+  osm_physp_t*             p_req_physp;
+
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_gir_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_rcvd_rec = (ib_guidinfo_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+
+  CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_GUIDINFO_RECORD );
+
+  /* we only support SubnAdmGet and SubnAdmGetTable methods */
+  if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) &&
+       (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_gir_rcv_process: ERR 5105: "
+             "Unsupported Method (%s)\n",
+             ib_get_sa_method_str( p_rcvd_mad->method ) );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+    goto Exit;
+  }
+
+  /* update the requester physical port. */
+  p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+                                          p_rcv->p_subn,
+                                          osm_madw_get_mad_addr_ptr(p_madw) );
+  if (p_req_physp == NULL)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_gir_rcv_process: ERR 5104: "
+             "Cannot find requester physical port\n" );
+    goto Exit;
+  }
+
+  if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+    osm_dump_guidinfo_record( p_rcv->p_log, p_rcvd_rec, OSM_LOG_DEBUG );
+
+  cl_qlist_init( &rec_list );
+
+  context.p_rcvd_rec = p_rcvd_rec;
+  context.p_list = &rec_list;
+  context.comp_mask = p_rcvd_mad->comp_mask;
+  context.p_rcv = p_rcv;
+  context.p_req_physp = p_req_physp;
+
+  cl_plock_acquire( p_rcv->p_lock );
+
+  cl_qmap_apply_func( &p_rcv->p_subn->node_guid_tbl,
+                      __osm_sa_gir_by_comp_mask_cb,
+                      &context );
+
+  cl_plock_release( p_rcv->p_lock );
+
+  num_rec = cl_qlist_count( &rec_list );
+
+  /*
+   * C15-0.1.30:
+   * If we do a SubnAdmGet and got more than one record it is an error !
+   */
+  if (p_rcvd_mad->method == IB_MAD_METHOD_GET)
+  {
+    if (num_rec == 0)
+    {
+      osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+      goto Exit;
+    }
+    if (num_rec > 1)
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_gir_rcv_process: ERR 5103: "
+               "Got more than one record for SubnAdmGet (%u)\n",
+               num_rec );
+      osm_sa_send_error( p_rcv->p_resp, p_madw,
+                         IB_SA_MAD_STATUS_TOO_MANY_RECORDS );
+
+      /* need to set the mem free ... */
+      p_rec_item = (osm_gir_item_t*)cl_qlist_remove_head( &rec_list );
+      while( p_rec_item != (osm_gir_item_t*)cl_qlist_end( &rec_list ) )
+      {
+        cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+        p_rec_item = (osm_gir_item_t*)cl_qlist_remove_head( &rec_list );
+      }
+
+      goto Exit;
+    }
+  }
+
+  pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_guidinfo_record_t);
+  if (trim_num_rec < num_rec)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "osm_gir_rcv_process: "
+             "Number of records:%u trimmed to:%u to fit in one MAD\n",
+             num_rec, trim_num_rec );
+    num_rec = trim_num_rec;
+  }
+#endif
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+           "osm_gir_rcv_process: "
+           "Returning %u records\n", num_rec );
+
+  if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+  {
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+    goto Exit;
+  }
+
+  /*
+   * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+   */
+  p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+                                  p_madw->h_bind,
+                                  num_rec * sizeof(ib_guidinfo_record_t) + IB_SA_MAD_HDR_SIZE,
+                                  &p_madw->mad_addr );
+
+  if( !p_resp_madw )
+  {
+    osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+            "osm_gir_rcv_process: ERR 5106: "
+            "osm_mad_pool_get failed\n" );
+
+    for( i = 0; i < num_rec; i++ )
+    {
+      p_rec_item = (osm_gir_item_t*)cl_qlist_remove_head( &rec_list );
+      cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    }
+
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES );
+    goto Exit;
+  }
+
+  p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+  /*
+    Copy the MAD header back into the response mad.
+    Set the 'R' bit and the payload length,
+    Then copy all records from the list into the response payload.
+  */
+
+  memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+  /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
+  p_resp_sa_mad->sm_key = 0;
+  /* Fill in the offset (paylen will be done by the rmpp SAR) */
+  p_resp_sa_mad->attr_offset =
+    ib_get_attr_offset( sizeof(ib_guidinfo_record_t) );
+
+  p_resp_rec = (ib_guidinfo_record_t*)
+    ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+#ifndef VENDOR_RMPP_SUPPORT
+  /* we support only one packet RMPP - so we will set the first and
+     last flags for gettable */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+  {
+    p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+  }
+#else
+  /* forcefully define the packet as RMPP one */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+  for( i = 0; i < pre_trim_num_rec; i++ )
+  {
+    p_rec_item = (osm_gir_item_t*)cl_qlist_remove_head( &rec_list );
+    /* copy only if not trimmed */
+    if (i < num_rec)
+    {
+      *p_resp_rec = p_rec_item->rec;
+    }
+    cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    p_resp_rec++;
+  }
+
+  CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+  status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE);
+  if (status != IB_SUCCESS)
+  {
+    osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+            "osm_gir_rcv_process: ERR 5107: "
+            "osm_vendor_send status = %s\n",
+            ib_get_err_str(status));
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_guidinfo_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_guidinfo_record_ctrl.c
new file mode 100644 (file)
index 0000000..4431a11
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_guidinfo_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_gir_rcv_ctrl_t.
+ * This object represents the GUIDInfoRecord request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_guidinfo_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_gir_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_gir_rcv_process( ((osm_gir_rcv_ctrl_t*)context)->p_rcv,
+                       (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_gir_rcv_ctrl_construct(
+  IN osm_gir_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_gir_rcv_ctrl_destroy(
+  IN osm_gir_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_gir_rcv_ctrl_init(
+  IN osm_gir_rcv_ctrl_t* const p_ctrl,
+  IN osm_gir_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_gir_rcv_ctrl_init );
+
+  osm_gir_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_GUIDINFO_RECORD,
+    __osm_gir_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_gir_rcv_ctrl_init: ERR 5201: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_informinfo.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_informinfo.c
new file mode 100644 (file)
index 0000000..21646da
--- /dev/null
@@ -0,0 +1,922 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_informinfo.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_infr_rcv_t.
+ * This object represents the InformInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.8 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_informinfo.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <vendor/osm_vendor.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_sa.h>
+#include <opensm/osm_inform.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_IIR_RCV_POOL_MIN_SIZE      32
+#define OSM_IIR_RCV_POOL_GROW_SIZE     32
+
+typedef struct _osm_iir_item
+{
+  cl_pool_item_t          pool_item;
+  ib_inform_info_record_t rec;
+} osm_iir_item_t;
+
+typedef struct _osm_iir_search_ctxt
+{
+  const ib_inform_info_record_t*  p_rcvd_rec;
+  ib_net64_t                      comp_mask;
+  cl_qlist_t*                     p_list;
+  ib_gid_t                        subscriber_gid;
+  ib_net16_t                      subscriber_enum;
+  osm_infr_rcv_t*                 p_rcv;
+  osm_physp_t*                    p_req_physp;
+} osm_iir_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_rcv_construct(
+  IN osm_infr_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+  cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_rcv_destroy(
+  IN osm_infr_rcv_t* const p_rcv )
+{
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_infr_rcv_destroy );
+  cl_qlock_pool_destroy( &p_rcv->pool );
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_infr_rcv_init(
+  IN osm_infr_rcv_t*    const p_rcv,
+  IN osm_sa_resp_t*     const p_resp,
+  IN osm_mad_pool_t*    const p_mad_pool,
+  IN osm_subn_t*        const p_subn,
+  IN osm_log_t*         const p_log,
+  IN cl_plock_t*        const p_lock )
+{
+  ib_api_status_t status = IB_ERROR;
+
+  OSM_LOG_ENTER( p_log, osm_infr_rcv_init );
+
+  osm_infr_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_resp = p_resp;
+  p_rcv->p_mad_pool = p_mad_pool;
+
+  status = cl_qlock_pool_init( &p_rcv->pool,
+                               OSM_IIR_RCV_POOL_MIN_SIZE,
+                               0,
+                               OSM_IIR_RCV_POOL_GROW_SIZE,
+                               sizeof(osm_iir_item_t),
+                               NULL, NULL, NULL );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+o13-14.1.1: Except for Set(InformInfo) requests with Inform-
+Info:LIDRangeBegin=0xFFFF, managers that support event forwarding
+shall, upon receiving a Set(InformInfo), verify that the requester
+originating the Set(InformInfo) and a Trap() source identified by Inform-
+can access each other - can use path record to verify that.
+**********************************************************************/
+static
+boolean_t
+__validate_ports_access_rights(
+  IN osm_infr_rcv_t*   const p_rcv,
+  IN osm_infr_t*       p_infr_rec )
+{
+  boolean_t valid = TRUE;
+  osm_physp_t* p_requester_physp;
+  osm_port_t*  p_port;
+  osm_physp_t* p_physp;
+  ib_net64_t portguid;
+  ib_net16_t lid_range_begin;
+  ib_net16_t lid_range_end;
+  ib_net16_t lid;
+  const cl_ptr_vector_t* p_tbl;
+  ib_gid_t zero_gid;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __validate_ports_access_rights );
+
+  /* get the requester physp from the request address */
+  p_requester_physp = osm_get_physp_by_mad_addr( p_rcv->p_log,
+                                                 p_rcv->p_subn,
+                                                 &p_infr_rec->report_addr );
+
+  memset( &zero_gid, 0, sizeof(zero_gid) );
+  if ( memcmp (&(p_infr_rec->inform_record.inform_info.gid),
+               &zero_gid, sizeof(ib_gid_t) ) )
+  {
+    /* a gid is defined */
+    portguid = p_infr_rec->inform_record.inform_info.gid.unicast.interface_id;
+
+    p_port = osm_get_port_by_guid( p_rcv->p_subn, portguid );
+
+    if ( p_port == NULL )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__validate_ports_access_rights: ERR 4301: "
+               "Invalid port guid: 0x%016" PRIx64 "\n",
+               cl_ntoh64(portguid) );
+      valid = FALSE;
+      goto Exit;
+    }
+
+    /* get the destination InformInfo physical port */
+    p_physp = osm_port_get_default_phys_ptr(p_port);
+
+    /* make sure that the requester and destination port can access each other 
+       according to the current partitioning. */
+    if (! osm_physp_share_pkey( p_rcv->p_log, p_physp, p_requester_physp))
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+               "__validate_ports_access_rights: "
+               "port and requester don't share pkey\n" );
+      valid = FALSE;
+      goto Exit;
+    }
+  }
+  else
+  {
+    /* gid is zero - check if LID range is defined */
+    lid_range_begin = cl_ntoh16(p_infr_rec->inform_record.inform_info.lid_range_begin);
+    /* if lid is 0xFFFF - meaning all endports managed by the manager */
+    if ( lid_range_begin == 0xFFFF )
+      goto Exit;
+
+    lid_range_end = cl_ntoh16(p_infr_rec->inform_record.inform_info.lid_range_end);
+
+    /* lid_range_end is set to zero if no range desired. In this case - 
+       just make it equal to the lid_range_begin. */
+    if (lid_range_end == 0)
+      lid_range_end = lid_range_begin;
+
+    /* go over all defined lids within the range and make sure that the 
+       requester port can access them according to current partitioning. */
+    for ( lid = lid_range_begin; lid <= lid_range_end; lid++ )
+    {
+      p_tbl = &p_rcv->p_subn->port_lid_tbl;
+      if ( cl_ptr_vector_get_size( p_tbl ) > lid )
+      {
+        p_port = cl_ptr_vector_get( p_tbl, lid );
+      }
+      else
+      {
+        /* lid requested is out of range */
+        osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                 "__validate_ports_access_rights: ERR 4302: "
+                 "Given LID (0x%X) is out of range:0x%X\n",
+                 lid, cl_ptr_vector_get_size(p_tbl) );
+        valid = FALSE;
+        goto Exit;
+      }
+      if ( p_port == NULL )
+        continue;
+
+      p_physp = osm_port_get_default_phys_ptr(p_port);
+      /* make sure that the requester and destination port can access 
+         each other according to the current partitioning. */
+      if (! osm_physp_share_pkey( p_rcv->p_log, p_physp, p_requester_physp))
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+                 "__validate_ports_access_rights: "
+                 "port and requester don't share pkey\n" );
+        valid = FALSE;
+        goto Exit;
+      }
+    }
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return valid;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static
+boolean_t
+__validate_infr(
+  IN osm_infr_rcv_t*    const p_rcv,
+  IN osm_infr_t*        p_infr_rec )
+{
+  boolean_t valid = TRUE;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __validate_infr );
+
+  valid = __validate_ports_access_rights( p_rcv, p_infr_rec );
+  if (!valid)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__validate_infr: "
+             "Invalid Access for InformInfo\n" );
+    valid = FALSE;
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return valid;
+}
+
+/**********************************************************************
+o13-12.1.1: Confirm a valid request for event subscription by responding
+with an InformInfo attribute that is a copy of the data in the
+Set(InformInfo) request.
+**********************************************************************/
+static void
+__osm_infr_rcv_respond(
+  IN osm_infr_rcv_t*    const p_rcv,
+  IN const osm_madw_t*  const p_madw )
+{
+  osm_madw_t*           p_resp_madw;
+  const ib_sa_mad_t*    p_sa_mad;
+  ib_sa_mad_t*          p_resp_sa_mad;
+  ib_inform_info_t*     p_resp_infr;
+  ib_api_status_t       status;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_infr_rcv_respond );
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_infr_rcv_respond: "
+             "Generating successful InformInfo response\n");
+  }
+
+  /*
+    Get a MAD to reply. Address of Mad is in the received mad_wrapper
+  */
+  p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, 
+                                  p_madw->h_bind,
+                                  MAD_BLOCK_SIZE,
+                                  &p_madw->mad_addr );
+  if ( !p_resp_madw )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_infr_rcv_respond: ERR 4303: " 
+             "Unable to allocate MAD\n" );
+    goto Exit;
+  }
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+  /* copy the request InformInfo */
+  memcpy( p_resp_sa_mad, p_sa_mad, MAD_BLOCK_SIZE );
+  p_resp_sa_mad->method = IB_MAD_METHOD_GET_RESP;
+  /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
+  p_resp_sa_mad->sm_key = 0;
+
+  p_resp_infr = (ib_inform_info_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+  status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw,  FALSE );
+
+  if ( status != IB_SUCCESS )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_infr_rcv_respond: ERR 4304: " 
+             "Unable to send MAD (%s)\n", ib_get_err_str( status ) );
+    /* osm_mad_pool_put( p_rcv->p_mad_pool, p_resp_madw ); */
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_inform_info_rec_by_comp_mask(
+  IN osm_infr_rcv_t*       const p_rcv,
+  IN const osm_infr_t*     const p_infr,
+  osm_iir_search_ctxt_t*   const p_ctxt )
+{
+  const ib_inform_info_record_t* p_rcvd_rec = NULL; 
+  ib_net64_t               comp_mask;
+  ib_net64_t               portguid;
+  osm_port_t *             p_subscriber_port;
+  osm_physp_t *            p_subscriber_physp;
+  const osm_physp_t*       p_req_physp;
+  osm_iir_item_t*          p_rec_item;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_inform_info_rec_by_comp_mask );
+
+  p_rcvd_rec = p_ctxt->p_rcvd_rec;
+  comp_mask = p_ctxt->comp_mask;
+  p_req_physp = p_ctxt->p_req_physp;
+
+  if (comp_mask & IB_IIR_COMPMASK_SUBSCRIBERGID)
+  {
+    if (memcmp(&p_infr->inform_record.subscriber_gid,
+              &p_ctxt->subscriber_gid,
+              sizeof(p_infr->inform_record.subscriber_gid)))
+      goto Exit; 
+  }
+
+  if (comp_mask & IB_IIR_COMPMASK_ENUM)
+  {
+    if (p_infr->inform_record.subscriber_enum != p_ctxt->subscriber_enum)
+      goto Exit;
+  }
+
+  /* Implement any other needed search cases */
+
+  /* Ensure pkey is shared before returning any records */
+  portguid = p_infr->inform_record.subscriber_gid.unicast.interface_id;
+  p_subscriber_port = osm_get_port_by_guid( p_rcv->p_subn, portguid );
+  if ( p_subscriber_port == NULL )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sa_inform_info_rec_by_comp_mask: ERR 430D: "
+             "Invalid subscriber port guid: 0x%016" PRIx64 "\n",
+             cl_ntoh64(portguid) );
+    goto Exit;
+  }
+
+  /* get the subscriber InformInfo physical port */
+  p_subscriber_physp = osm_port_get_default_phys_ptr(p_subscriber_port);
+  /* make sure that the requester and subscriber port can access each other 
+     according to the current partitioning. */
+  if (! osm_physp_share_pkey( p_rcv->p_log, p_req_physp, p_subscriber_physp ))
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_sa_inform_info_rec_by_comp_mask: "
+             "requester and subscriber ports don't share pkey\n" );
+    goto Exit;
+  }
+  p_rec_item = (osm_iir_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+  if( p_rec_item == NULL )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sa_inform_info_rec_by_comp_mask: ERR 430E: "
+             "cl_qlock_pool_get failed\n" );
+    goto Exit;
+  }
+
+  memcpy((void *)&p_rec_item->rec, (void *)&p_infr->inform_record, sizeof(ib_inform_info_record_t));
+  cl_qlist_insert_tail( p_ctxt->p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_inform_info_rec_by_comp_mask_cb(
+  IN cl_list_item_t*       const p_list_item,
+  IN void*                 context )
+{
+  const osm_infr_t* const p_infr = (osm_infr_t *)p_list_item;
+  osm_iir_search_ctxt_t*   const p_ctxt = (osm_iir_search_ctxt_t *)context;
+
+  __osm_sa_inform_info_rec_by_comp_mask( p_ctxt->p_rcv, p_infr, p_ctxt );
+}
+
+/**********************************************************************
+Received a Get(InformInfoRecord) or GetTable(InformInfoRecord) MAD
+**********************************************************************/
+static void
+osm_infr_rcv_process_get_method(
+  IN osm_infr_rcv_t*      const p_rcv,
+  IN const osm_madw_t*    const p_madw )
+{
+  ib_sa_mad_t*            p_rcvd_mad;
+  const ib_inform_info_record_t* p_rcvd_rec;
+  ib_inform_info_record_t* p_resp_rec;
+  cl_qlist_t              rec_list;
+  osm_madw_t*             p_resp_madw;
+  ib_sa_mad_t*            p_resp_sa_mad;
+  uint32_t                num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  uint32_t                trim_num_rec;
+#endif
+  uint32_t                i, j;
+  osm_iir_search_ctxt_t   context;
+  osm_iir_item_t*         p_rec_item;
+  ib_api_status_t         status = IB_SUCCESS;
+  osm_physp_t*            p_req_physp;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_infr_rcv_process_get_method );
+
+  CL_ASSERT( p_madw );
+  p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_rcvd_rec =
+    (ib_inform_info_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+
+  /* update the requester physical port. */
+  p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+                                          p_rcv->p_subn,
+                                          osm_madw_get_mad_addr_ptr(p_madw) );
+  if (p_req_physp == NULL)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_infr_rcv_process_get_method: ERR 4309: "
+             "Cannot find requester physical port\n" );
+    goto Exit;
+  }
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+    osm_dump_inform_info_record( p_rcv->p_log, p_rcvd_rec, OSM_LOG_DEBUG );
+
+  cl_qlist_init( &rec_list );
+
+  context.p_rcvd_rec = p_rcvd_rec;
+  context.p_list = &rec_list;
+  context.comp_mask = p_rcvd_mad->comp_mask;
+  context.subscriber_gid = p_rcvd_rec->subscriber_gid;
+  context.subscriber_enum = p_rcvd_rec->subscriber_enum;
+  context.p_rcv = p_rcv;
+  context.p_req_physp = p_req_physp;
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+           "osm_infr_rcv_process_get_method: "
+           "Query Subscriber GID:0x%016" PRIx64 " : 0x%016" PRIx64 "(%02X) Enum:0x%X(%02X)\n",
+           cl_ntoh64(p_rcvd_rec->subscriber_gid.unicast.prefix),
+           cl_ntoh64(p_rcvd_rec->subscriber_gid.unicast.interface_id),
+           (p_rcvd_mad->comp_mask & IB_IIR_COMPMASK_SUBSCRIBERGID) != 0,
+           cl_ntoh16(p_rcvd_rec->subscriber_enum),
+           (p_rcvd_mad->comp_mask & IB_IIR_COMPMASK_ENUM) != 0 );
+
+  cl_plock_acquire( p_rcv->p_lock );
+
+  cl_qlist_apply_func( &p_rcv->p_subn->sa_infr_list,
+                       __osm_sa_inform_info_rec_by_comp_mask_cb,
+                       &context );
+
+  cl_plock_release( p_rcv->p_lock );
+
+  num_rec = cl_qlist_count( &rec_list );
+
+  /*
+   * C15-0.1.30:
+   * If we do a SubnAdmGet and got more than one record it is an error !
+   */
+  if (p_rcvd_mad->method == IB_MAD_METHOD_GET)
+  {
+    if (num_rec == 0)
+    {
+      osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+      goto Exit;
+    }
+    if (num_rec > 1)
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_infr_rcv_process_get_method: ERR 430A: "
+               "More than one record for SubnAdmGet (%u)\n",
+               num_rec );
+      osm_sa_send_error( p_rcv->p_resp, p_madw,
+                         IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+
+      /* need to set the mem free ... */
+      p_rec_item = (osm_iir_item_t*)cl_qlist_remove_head( &rec_list );
+      while( p_rec_item != (osm_iir_item_t*)cl_qlist_end( &rec_list ) )
+      {
+        cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+        p_rec_item = (osm_iir_item_t*)cl_qlist_remove_head( &rec_list );
+      }
+
+      goto Exit;
+    }
+  }
+
+  pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  /* we limit the number of records to a single packet */
+  trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_inform_info_record_t);
+  if (trim_num_rec < num_rec)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "osm_infr_rcv_process_get_method: "
+             "Number of records:%u trimmed to:%u to fit in one MAD\n",
+             num_rec, trim_num_rec );
+    num_rec = trim_num_rec;
+  }
+#endif
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+           "osm_infr_rcv_process_get_method: "
+           "Returning %u records\n", num_rec );
+
+  /* 
+   * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+   */
+  p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+                                  p_madw->h_bind,
+                                  num_rec * sizeof(ib_inform_info_record_t) + IB_SA_MAD_HDR_SIZE,
+                                  &p_madw->mad_addr );
+
+  if( !p_resp_madw )
+  {
+    osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+            "osm_infr_rcv_process_get_method: ERR 430B: "
+            "osm_mad_pool_get failed\n" );
+
+    for( i = 0; i < num_rec; i++ )
+    {
+      p_rec_item = (osm_iir_item_t*)cl_qlist_remove_head( &rec_list );
+      cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    }
+
+    osm_sa_send_error( p_rcv->p_resp, p_madw,
+                       IB_SA_MAD_STATUS_NO_RESOURCES );
+
+    goto Exit;
+  }
+
+  p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+  /*
+    Copy the MAD header back into the response mad.
+    Set the 'R' bit and the payload length,
+    Then copy all records from the list into the response payload.
+  */
+
+  memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+  /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
+  p_resp_sa_mad->sm_key = 0;
+  /* Fill in the offset (paylen will be done by the rmpp SAR) */
+  p_resp_sa_mad->attr_offset =
+    ib_get_attr_offset( sizeof(ib_inform_info_record_t) );
+
+  p_resp_rec = (ib_inform_info_record_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+#ifndef VENDOR_RMPP_SUPPORT
+  /* we support only one packet RMPP - so we will set the first and
+     last flags for gettable */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+  {
+    p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+  }
+#else
+  /* forcefully define the packet as RMPP one */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+  for( i = 0; i < pre_trim_num_rec; i++ )
+  {
+    p_rec_item = (osm_iir_item_t*)cl_qlist_remove_head( &rec_list );
+    /* copy only if not trimmed */
+    if (i < num_rec)
+    {
+      *p_resp_rec = p_rec_item->rec;
+      /* clear reserved and pad fields in InformInfoRecord */
+      for (j = 0; j < 6; j++)
+        p_resp_rec->reserved[j] = 0;
+      for (j = 0; j < 4; j++)
+        p_resp_rec->pad[j] = 0;
+    }
+    cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    p_resp_rec++;
+  }
+
+  CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+  status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+  if (status != IB_SUCCESS)
+  {
+    osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+            "osm_infr_rcv_process_get_method: ERR 430C: "
+            "osm_vendor_send status = %s\n",
+            ib_get_err_str(status));
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/*********************************************************************
+Received a Set(InformInfo) MAD
+**********************************************************************/
+static void
+osm_infr_rcv_process_set_method(
+  IN osm_infr_rcv_t*      const p_rcv,
+  IN const osm_madw_t*    const p_madw )
+{
+  ib_sa_mad_t *p_sa_mad;
+  ib_inform_info_t *p_recvd_inform_info;
+  osm_infr_t inform_info_rec; /* actual inform record to be stored for reports */
+  osm_infr_t *p_infr;
+  ib_net32_t qpn;
+  uint8_t resp_time_val;
+  ib_api_status_t res;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_infr_rcv_process_set_method );
+
+  CL_ASSERT( p_madw );
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_recvd_inform_info =
+    (ib_inform_info_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+#if 0
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+    osm_dump_inform_info( p_rcv->p_log, p_recvd_inform_info, OSM_LOG_DEBUG );
+#endif
+
+  /* Grab the lock */
+  cl_plock_excl_acquire( p_rcv->p_lock );
+
+  /* define the inform record */
+  inform_info_rec.inform_record.inform_info = *p_recvd_inform_info;
+
+  /* following C13-32.1.2 Tbl 120: we only copy the source address vector */
+  inform_info_rec.report_addr = p_madw->mad_addr;
+
+  /* we will need to know the mad srvc to send back through */
+  inform_info_rec.h_bind = p_madw->h_bind;
+  inform_info_rec.p_infr_rcv = p_rcv;
+
+  /* update the subscriber GID according to mad address */
+  res = osm_get_gid_by_mad_addr(
+    p_rcv->p_log, 
+    p_rcv->p_subn, 
+    &p_madw->mad_addr,
+    &inform_info_rec.inform_record.subscriber_gid );
+  if ( res != IB_SUCCESS )
+  {    
+    cl_plock_release( p_rcv->p_lock );
+
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_infr_rcv_process_set_method: ERR 4308 "
+             "Subscribe Request from unknown LID: 0x%04X\n",
+             cl_ntoh16(p_madw->mad_addr.dest_lid)
+             );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID );
+    goto Exit;
+  }
+
+  /* HACK: enum is always 0 (currently) */
+  inform_info_rec.inform_record.subscriber_enum = 0;
+
+  /* Subscribe values above 1 are undefined */
+  if ( p_recvd_inform_info->subscribe > 1 )
+  {
+    cl_plock_release( p_rcv->p_lock );
+
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_infr_rcv_process_set_method: ERR 4308 "
+             "Invalid subscribe: %d\n",
+             p_recvd_inform_info->subscribe
+             );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID );
+    goto Exit;
+  }
+
+  /*
+   * MODIFICATIONS DONE ON INCOMING REQUEST:
+   *
+   * QPN:
+   * Internally we keep the QPN field of the InformInfo updated
+   * so we can simply compare it in the record - when finding such.
+   */
+  if ( p_recvd_inform_info->subscribe )
+  {
+    ib_inform_info_set_qpn(
+      &inform_info_rec.inform_record.inform_info,
+      inform_info_rec.report_addr.addr_type.gsi.remote_qp );
+
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "osm_infr_rcv_process_set_method: "
+             "Subscribe Request with QPN: 0x%06X\n",
+             cl_ntoh32(inform_info_rec.report_addr.addr_type.gsi.remote_qp)
+             );
+  }
+  else
+  {
+    ib_inform_info_get_qpn_resp_time(
+      p_recvd_inform_info->g_or_v.generic.qpn_resp_time_val,
+      &qpn, &resp_time_val );
+
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "osm_infr_rcv_process_set_method: "
+             "UnSubscribe Request with QPN: 0x%06X\n",
+             cl_ntoh32(qpn)
+             );
+  }
+
+  /* If record exists with matching InformInfo */
+  p_infr = osm_infr_get_by_rec( p_rcv->p_subn, p_rcv->p_log, &inform_info_rec );
+
+  /* check to see if the request was for subscribe */
+  if ( p_recvd_inform_info->subscribe )
+  {
+    /* validate the request for a new or update InformInfo */
+    if ( __validate_infr( p_rcv, &inform_info_rec ) != TRUE )
+    {
+      cl_plock_release( p_rcv->p_lock );
+
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_infr_rcv_process_set_method: ERR 4305: "
+               "Failed to validate a new inform object\n");
+
+      /* o13-13.1.1: we need to set the subscribe bit to 0 */
+      p_recvd_inform_info->subscribe = 0;
+      osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID );
+      goto Exit;
+    }
+
+    /* ok - we can try and create a new entry */
+    if (p_infr == NULL)
+    {
+      /* Create the instance of the osm_infr_t object */
+      p_infr = osm_infr_new( &inform_info_rec );
+      if (p_infr == NULL)
+      {
+        cl_plock_release( p_rcv->p_lock );
+
+        osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                 "osm_infr_rcv_process_set_method: ERR 4306: "
+                 "Failed to create a new inform object\n");
+
+        /* o13-13.1.1: we need to set the subscribe bit to 0 */
+        p_recvd_inform_info->subscribe = 0;
+        osm_sa_send_error( p_rcv->p_resp, p_madw,
+                           IB_SA_MAD_STATUS_NO_RESOURCES );
+        goto Exit;
+      }
+
+      /* Add this new osm_infr_t object to subnet object */
+      osm_infr_insert_to_db( p_rcv->p_subn, p_rcv->p_log, p_infr );
+    }
+    else
+    {
+      /* Update the old instance of the osm_infr_t object */
+      p_infr->inform_record = inform_info_rec.inform_record;
+    }
+  }
+  else
+  {
+    /* We got an UnSubscribe request */
+    if (p_infr == NULL)
+    {
+      cl_plock_release( p_rcv->p_lock );
+
+      /* No Such Item - So Error */
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_infr_rcv_process_set_method: ERR 4307: "
+               "Failed to UnSubscribe to non existing inform object\n");
+
+      /* o13-13.1.1: we need to set the subscribe bit to 0 */
+      p_recvd_inform_info->subscribe = 0;
+      osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID );
+      goto Exit;
+    }
+    else
+    {
+      /* Delete this object from the subnet list of informs */
+      osm_infr_remove_from_db( p_rcv->p_subn, p_rcv->p_log, p_infr );
+    }
+  }
+
+  cl_plock_release( p_rcv->p_lock );
+
+  /* send the success response */
+  __osm_infr_rcv_respond( p_rcv, p_madw );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/*********************************************************************
+**********************************************************************/
+void
+osm_infr_rcv_process(
+  IN osm_infr_rcv_t*       const p_rcv,
+  IN const osm_madw_t*     const p_madw )
+{
+  ib_sa_mad_t *p_sa_mad;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_infr_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+
+  CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_INFORM_INFO );
+
+  if (p_sa_mad->method != IB_MAD_METHOD_SET)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "osm_infr_rcv_process: "
+             "Unsupported Method (%s)\n",
+             ib_get_sa_method_str( p_sa_mad->method ) );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+    goto Exit;
+  }
+
+  osm_infr_rcv_process_set_method( p_rcv, p_madw );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/*********************************************************************
+**********************************************************************/
+void
+osm_infir_rcv_process(
+  IN osm_infr_rcv_t*       const p_rcv,
+  IN const osm_madw_t*     const p_madw )
+{
+  ib_sa_mad_t *p_sa_mad;
+    
+  OSM_LOG_ENTER( p_rcv->p_log, osm_infr_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+
+  CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_INFORM_INFO_RECORD );
+
+  if ( (p_sa_mad->method != IB_MAD_METHOD_GET) &&
+       (p_sa_mad->method != IB_MAD_METHOD_GETTABLE) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "osm_infir_rcv_process: "
+             "Unsupported Method (%s)\n",
+             ib_get_sa_method_str( p_sa_mad->method ) );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+    goto Exit;
+  }
+
+  osm_infr_rcv_process_get_method( p_rcv, p_madw );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_informinfo_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_informinfo_ctrl.c
new file mode 100644 (file)
index 0000000..33a767c
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_informinfo_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_infr_rcv_ctrl_t.
+ * This object represents the InformInfo set request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_informinfo_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_infr_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_infr_rcv_process( ((osm_infr_rcv_ctrl_t*)context)->p_rcv,
+                        (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_infir_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_infir_rcv_process( ((osm_infr_rcv_ctrl_t*)context)->p_rcv,
+                         (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_rcv_ctrl_construct(
+  IN osm_infr_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+  p_ctrl->h_disp2 = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_rcv_ctrl_destroy(
+  IN osm_infr_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp2 );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_infr_rcv_ctrl_init(
+  IN osm_infr_rcv_ctrl_t* const p_ctrl,
+  IN osm_infr_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_infr_rcv_ctrl_init );
+
+  osm_infr_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_INFORM_INFO,
+    __osm_infr_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_infr_rcv_ctrl_init: ERR 1701: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+  p_ctrl->h_disp2 = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_INFORM_INFO_RECORD,
+    __osm_infir_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp2 == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_infr_rcv_ctrl_init: ERR 1702: "
+             "Dispatcher registration failed\n" );
+    cl_disp_unregister( p_ctrl->h_disp );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_lft_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_lft_record.c
new file mode 100644 (file)
index 0000000..f116ed3
--- /dev/null
@@ -0,0 +1,515 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_lft_record.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_lftr_rcv_t.
+ *   This object represents the LinearForwardingTable Receiver object.
+ *   This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_lft_record.h>
+#include <opensm/osm_switch.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_LFTR_RCV_POOL_MIN_SIZE      32
+#define OSM_LFTR_RCV_POOL_GROW_SIZE     32
+
+typedef   struct _osm_lftr_item
+{
+  cl_pool_item_t          pool_item;
+  ib_lft_record_t         rec;
+} osm_lftr_item_t;
+
+typedef   struct _osm_lftr_search_ctxt
+{
+  const ib_lft_record_t*      p_rcvd_rec;
+  ib_net64_t                  comp_mask;
+  cl_qlist_t*                 p_list;
+  osm_lftr_rcv_t*             p_rcv;
+  const osm_physp_t*          p_req_physp;
+} osm_lftr_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lftr_rcv_construct(
+  IN osm_lftr_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+  cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lftr_rcv_destroy(
+  IN osm_lftr_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_lftr_rcv_destroy );
+  cl_qlock_pool_destroy( &p_rcv->pool );
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lftr_rcv_init(
+  IN osm_lftr_rcv_t* const p_rcv,
+  IN osm_sa_resp_t*  const p_resp,
+  IN osm_mad_pool_t* const p_mad_pool,
+  IN osm_subn_t*     const p_subn,
+  IN osm_log_t*      const p_log,
+  IN cl_plock_t*     const p_lock )
+{
+  ib_api_status_t            status;
+
+  OSM_LOG_ENTER( p_log, osm_lftr_rcv_init );
+
+  osm_lftr_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_resp = p_resp;
+  p_rcv->p_mad_pool = p_mad_pool;
+
+  status = cl_qlock_pool_init( &p_rcv->pool,
+                               OSM_LFTR_RCV_POOL_MIN_SIZE,
+                               0,
+                               OSM_LFTR_RCV_POOL_GROW_SIZE,
+                               sizeof(osm_lftr_item_t),
+                               NULL, NULL, NULL );
+
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_lftr_rcv_new_lftr(
+  IN osm_lftr_rcv_t*         const p_rcv,
+  IN const osm_switch_t*     const p_sw,
+  IN cl_qlist_t*             const p_list,
+  IN ib_net16_t              const lid,
+  IN ib_net16_t              const block )
+{
+  osm_lftr_item_t*           p_rec_item;
+  ib_api_status_t            status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_lftr_rcv_new_lftr );
+
+  p_rec_item = (osm_lftr_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+  if( p_rec_item == NULL )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_lftr_rcv_new_lftr: ERR 4402: "
+             "cl_qlock_pool_get failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_lftr_rcv_new_lftr: "
+             "New LinearForwardingTable: sw 0x%016" PRIx64
+             "\n\t\t\t\tblock 0x%02X lid 0x%02X\n",
+             cl_ntoh64( osm_node_get_node_guid( p_sw->p_node ) ),
+             cl_ntoh16( block ), cl_ntoh16( lid )
+             );
+  }
+
+  memset( &p_rec_item->rec, 0, sizeof(ib_lft_record_t) );
+
+  p_rec_item->rec.lid = lid;
+  p_rec_item->rec.block_num = block;
+
+  /* copy the lft block */
+  osm_switch_get_fwd_tbl_block( p_sw, cl_ntoh16(block), p_rec_item->rec.lft );
+
+  cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static osm_port_t*
+__osm_lftr_get_port_by_guid(
+  IN osm_lftr_rcv_t*  const p_rcv,
+  IN uint64_t         port_guid )
+{
+  osm_port_t*         p_port;
+
+  CL_PLOCK_ACQUIRE(p_rcv->p_lock);
+
+  p_port = (osm_port_t *)cl_qmap_get(&p_rcv->p_subn->port_guid_tbl,
+                                     port_guid);
+  if (p_port == (osm_port_t *)cl_qmap_end(&p_rcv->p_subn->port_guid_tbl))
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_lftr_get_port_by_guid ERR 4404: "
+             "Invalid port GUID 0x%016" PRIx64 "\n",
+             port_guid );
+    p_port = NULL;
+  }
+
+  CL_PLOCK_RELEASE(p_rcv->p_lock);
+  return p_port;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_lftr_rcv_by_comp_mask(
+  IN cl_map_item_t*         const p_map_item,
+  IN void*                  context )
+{
+  const osm_lftr_search_ctxt_t* const p_ctxt =
+    (osm_lftr_search_ctxt_t *)context;
+  const osm_switch_t*       const p_sw = (osm_switch_t*)p_map_item;
+  const ib_lft_record_t*    const p_rcvd_rec = p_ctxt->p_rcvd_rec;
+  osm_lftr_rcv_t*           const p_rcv = p_ctxt->p_rcv;
+  ib_net64_t                const comp_mask = p_ctxt->comp_mask;
+  const osm_physp_t*        const p_req_physp = p_ctxt->p_req_physp;
+  osm_port_t*               p_port;
+  uint16_t                  min_lid_ho, max_lid_ho;
+  uint16_t                  min_block, max_block, block;
+  const osm_physp_t*        p_physp;
+
+  /* In switches, the port guid is the node guid. */
+  p_port =
+    __osm_lftr_get_port_by_guid( p_rcv, p_sw->p_node->node_info.port_guid );
+  if (! p_port)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_lftr_rcv_by_comp_mask: ERR 4405: "
+             "Failed to find Port by Node Guid:0x%016" PRIx64
+             "\n",
+             cl_ntoh64( p_sw->p_node->node_info.node_guid )
+             );
+    return;
+  }
+
+  /* check that the requester physp and the current physp are under
+     the same partition. */
+  p_physp = osm_port_get_default_phys_ptr( p_port );
+  if (! p_physp)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_lftr_rcv_by_comp_mask: ERR 4406: "
+             "Failed to find default physical Port by Node Guid:0x%016" PRIx64
+             "\n",
+             cl_ntoh64( p_sw->p_node->node_info.node_guid )
+             );
+    return;
+  }
+  if (! osm_physp_share_pkey( p_rcv->p_log, p_req_physp, p_physp ))
+    return;
+
+  /* get the port 0 of the switch */
+  osm_port_get_lid_range_ho( p_port, &min_lid_ho, &max_lid_ho );
+
+  /* compare the lids - if required */
+  if( comp_mask & IB_LFTR_COMPMASK_LID )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_lftr_rcv_by_comp_mask: "
+             "Comparing lid:0x%02X to port lid range: 0x%02X .. 0x%02X\n",
+             cl_ntoh16( p_rcvd_rec->lid ), min_lid_ho, max_lid_ho
+             );
+    /* ok we are ready for range check */
+    if (min_lid_ho > cl_ntoh16(p_rcvd_rec->lid) ||
+        max_lid_ho < cl_ntoh16(p_rcvd_rec->lid))
+      return;
+  }
+
+  /* now we need to decide which blocks to output */
+  if( comp_mask & IB_LFTR_COMPMASK_BLOCK )
+  {
+    max_block = min_block = cl_ntoh16(p_rcvd_rec->block_num);
+  }
+  else
+  {
+    /* use as many blocks as "in use" */
+    min_block = 0;
+    max_block = osm_switch_get_max_block_id_in_use(p_sw);
+  }
+
+  /* so we can add these blocks one by one ... */
+  for (block = min_block; block <= max_block; block++)
+    __osm_lftr_rcv_new_lftr( p_rcv, p_sw, p_ctxt->p_list,
+                             osm_port_get_base_lid(p_port),
+                             cl_hton16(block) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lftr_rcv_process(
+  IN osm_lftr_rcv_t*        const p_rcv,
+  IN const osm_madw_t*      const p_madw )
+{
+  const ib_sa_mad_t*        p_rcvd_mad;
+  const ib_lft_record_t*    p_rcvd_rec;
+  ib_lft_record_t*          p_resp_rec;
+  cl_qlist_t                rec_list;
+  osm_madw_t*               p_resp_madw;
+  ib_sa_mad_t*              p_resp_sa_mad;
+  uint32_t                  num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  uint32_t                  trim_num_rec;
+#endif
+  uint32_t                  i;
+  osm_lftr_search_ctxt_t    context;
+  osm_lftr_item_t*          p_rec_item;
+  ib_api_status_t           status = IB_SUCCESS;
+  osm_physp_t*              p_req_physp;
+
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_lftr_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_rcvd_rec = (ib_lft_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+
+  CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_LFT_RECORD );
+
+  /* we only support SubnAdmGet and SubnAdmGetTable methods */
+  if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) &&
+       (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) ) {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_lftr_rcv_process: ERR 4408: "
+             "Unsupported Method (%s)\n",
+             ib_get_sa_method_str( p_rcvd_mad->method ) );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+    goto Exit;
+  }
+
+  /* update the requester physical port. */
+  p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+                                          p_rcv->p_subn,
+                                          osm_madw_get_mad_addr_ptr(p_madw) );
+  if (p_req_physp == NULL)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_lftr_rcv_process: ERR 4407: "
+             "Cannot find requester physical port\n" );
+    goto Exit;
+  }
+
+  cl_qlist_init( &rec_list );
+
+  context.p_rcvd_rec     = p_rcvd_rec;
+  context.p_list         = &rec_list;
+  context.comp_mask      = p_rcvd_mad->comp_mask;
+  context.p_rcv          = p_rcv;
+  context.p_req_physp    = p_req_physp;
+
+  cl_plock_acquire( p_rcv->p_lock );
+
+  /* Go over all switches */
+  cl_qmap_apply_func( &p_rcv->p_subn->sw_guid_tbl,
+                      __osm_lftr_rcv_by_comp_mask,
+                      &context );
+
+  cl_plock_release( p_rcv->p_lock );
+
+  num_rec = cl_qlist_count( &rec_list );
+
+  /*
+   * C15-0.1.30:
+   * If we do a SubnAdmGet and got more than one record it is an error !
+   */
+  if (p_rcvd_mad->method == IB_MAD_METHOD_GET)
+  {
+    if (num_rec == 0)
+    {
+      osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+      goto Exit;
+    }
+    if (num_rec > 1)
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_lftr_rcv_process: ERR 4409: "
+               "Got more than one record for SubnAdmGet (%u)\n",
+               num_rec );
+      osm_sa_send_error( p_rcv->p_resp, p_madw,
+                         IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+
+      /* need to set the mem free ... */
+      p_rec_item = (osm_lftr_item_t*)cl_qlist_remove_head( &rec_list );
+      while( p_rec_item != (osm_lftr_item_t*)cl_qlist_end( &rec_list ) )
+      {
+        cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+        p_rec_item = (osm_lftr_item_t*)cl_qlist_remove_head( &rec_list );
+      }
+
+      goto Exit;
+    }
+  }
+
+  pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  /* we limit the number of records to a single packet */
+  trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_lft_record_t);
+  if (trim_num_rec < num_rec)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "osm_lftr_rcv_process: "
+             "Number of records:%u trimmed to:%u to fit in one MAD\n",
+             num_rec, trim_num_rec );
+    num_rec = trim_num_rec;
+  }
+#endif
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+           "osm_lftr_rcv_process: "
+           "Returning %u records\n", num_rec );
+
+  if ((p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) &&
+      (num_rec == 0))
+  {
+    osm_sa_send_error( p_rcv->p_resp, p_madw,
+                       IB_SA_MAD_STATUS_NO_RECORDS );
+    goto Exit;
+  }
+
+  /* 
+   * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+   */
+  p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+                                  p_madw->h_bind,
+                                  num_rec * sizeof(ib_lft_record_t) + IB_SA_MAD_HDR_SIZE,
+                                  &p_madw->mad_addr );
+
+  if( !p_resp_madw )
+  {
+    osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+            "osm_lftr_rcv_process: ERR 4410: "
+            "osm_mad_pool_get failed\n" );
+
+    for( i = 0; i < num_rec; i++ )
+    {
+      p_rec_item = (osm_lftr_item_t*)cl_qlist_remove_head( &rec_list );
+      cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    }
+
+    osm_sa_send_error( p_rcv->p_resp, p_madw,
+                       IB_SA_MAD_STATUS_NO_RESOURCES );
+
+    goto Exit;
+  }
+
+  p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+  /*
+    Copy the MAD header back into the response mad.
+    Set the 'R' bit and the payload length,
+    Then copy all records from the list into the response payload.
+  */
+
+  memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+  /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
+  p_resp_sa_mad->sm_key = 0;
+  /* Fill in the offset (paylen will be done by the rmpp SAR) */
+  p_resp_sa_mad->attr_offset =
+    ib_get_attr_offset( sizeof(ib_lft_record_t) );
+
+  p_resp_rec = (ib_lft_record_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+#ifndef VENDOR_RMPP_SUPPORT
+  /* we support only one packet RMPP - so we will set the first and
+     last flags for gettable */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+  {
+    p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+  }
+#else
+  /* forcefully define the packet as RMPP one */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+  for( i = 0; i < pre_trim_num_rec; i++ )
+  {
+    p_rec_item = (osm_lftr_item_t*)cl_qlist_remove_head( &rec_list );
+    /* copy only if not trimmed */
+    if (i < num_rec)
+    {
+      *p_resp_rec = p_rec_item->rec;
+    }
+    cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    p_resp_rec++;
+  }
+
+  CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+  status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+  if (status != IB_SUCCESS)
+  {
+    osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+            "osm_lftr_rcv_process: ERR 4411: "
+            "osm_vendor_send status = %s\n",
+            ib_get_err_str(status));
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_lft_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_lft_record_ctrl.c
new file mode 100644 (file)
index 0000000..b11ebaf
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_lft_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_lftr_rcv_ctrl_t.
+ * This object represents the LinearForwardingTable request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_lft_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_lftr_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_lftr_rcv_process( ((osm_lftr_rcv_ctrl_t*)context)->p_rcv,
+                        (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lftr_rcv_ctrl_construct(
+  IN osm_lftr_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lftr_rcv_ctrl_destroy(
+  IN osm_lftr_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lftr_rcv_ctrl_init(
+  IN osm_lftr_rcv_ctrl_t* const p_ctrl,
+  IN osm_lftr_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_lftr_rcv_ctrl_init );
+
+  osm_lftr_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_LFT_RECORD,
+    __osm_lftr_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_lftr_rcv_ctrl_init: ERR 4501: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_link_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_link_record.c
new file mode 100644 (file)
index 0000000..b87bd40
--- /dev/null
@@ -0,0 +1,777 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_link_record.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_lr_rcv_t.
+ * This object represents the LinkRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.8 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_sa_link_record.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_LR_RCV_POOL_MIN_SIZE    64
+#define OSM_LR_RCV_POOL_GROW_SIZE   64
+
+typedef  struct _osm_lr_item
+{
+  cl_pool_item_t           pool_item;
+  ib_link_record_t         link_rec;
+} osm_lr_item_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lr_rcv_construct(
+  IN osm_lr_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+  cl_qlock_pool_construct( &p_rcv->lr_pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lr_rcv_destroy(
+  IN osm_lr_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_lr_rcv_destroy );
+  cl_qlock_pool_destroy( &p_rcv->lr_pool );
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lr_rcv_init(
+  IN osm_lr_rcv_t*   const p_rcv,
+  IN osm_sa_resp_t*  const p_resp,
+  IN osm_mad_pool_t* const p_mad_pool,
+  IN osm_subn_t*     const p_subn,
+  IN osm_log_t*      const p_log,
+  IN cl_plock_t*     const p_lock )
+{
+  ib_api_status_t    status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_lr_rcv_init );
+
+  osm_lr_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_resp = p_resp;
+  p_rcv->p_mad_pool = p_mad_pool;
+
+  status = cl_qlock_pool_init( &p_rcv->lr_pool,
+                               OSM_LR_RCV_POOL_MIN_SIZE,
+                               0,
+                               OSM_LR_RCV_POOL_GROW_SIZE,
+                               sizeof(osm_lr_item_t),
+                               NULL, NULL, NULL );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_lr_rcv_build_physp_link(
+  IN osm_lr_rcv_t*         const p_rcv,
+  IN const ib_net16_t      from_lid,
+  IN const ib_net16_t      to_lid,
+  IN const uint8_t         from_port,
+  IN const uint8_t         to_port,
+  IN cl_qlist_t*           p_list )
+{
+  osm_lr_item_t*           p_lr_item;
+
+  p_lr_item = (osm_lr_item_t*)cl_qlock_pool_get( &p_rcv->lr_pool );
+  if( p_lr_item == NULL )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_lr_rcv_build_physp_link: ERR 1801: "
+             "Unable to acquire link record\n"
+             "\t\t\t\tFrom port 0x%u\n"
+             "\t\t\t\tTo port   0x%u\n"
+             "\t\t\t\tFrom lid  0x%X\n"
+             "\t\t\t\tTo lid    0x%X\n",
+             from_port, to_port,
+             cl_ntoh16(from_lid),
+             cl_ntoh16(to_lid) );
+    return;
+  }
+
+  p_lr_item->link_rec.from_port_num =  from_port;
+  p_lr_item->link_rec.to_port_num = to_port;
+  p_lr_item->link_rec.to_lid = to_lid;
+  p_lr_item->link_rec.from_lid = from_lid;
+
+  cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_lr_item->pool_item );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__get_base_lid(
+  IN const osm_physp_t*  p_physp,
+  OUT uint16_t *         p_base_lid )
+{
+  if(p_physp->p_node->node_info.node_type == IB_NODE_TYPE_SWITCH)
+  {
+    *p_base_lid =
+      cl_ntoh16(
+        osm_physp_get_base_lid(
+          osm_node_get_physp_ptr(p_physp->p_node, 0))
+        );
+  }
+  else
+  {
+    *p_base_lid =
+      cl_ntoh16(osm_physp_get_base_lid(p_physp));
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_lr_rcv_get_physp_link(
+  IN osm_lr_rcv_t*            const p_rcv,
+  IN const ib_link_record_t*  const p_lr,
+  IN const osm_physp_t*       p_src_physp,
+  IN const osm_physp_t*       p_dest_physp,
+  IN const ib_net64_t         comp_mask,
+  IN cl_qlist_t*              const p_list,
+  IN const osm_physp_t*       p_req_physp )
+{
+  uint8_t                     src_port_num;
+  uint8_t                     dest_port_num;
+  ib_net16_t                  from_base_lid_ho;
+  ib_net16_t                  to_base_lid_ho;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_lr_rcv_get_physp_link );
+
+  /*
+    If only one end of the link is specified, determine
+    the other side.
+  */
+  if( p_src_physp )
+  {
+    if( !osm_physp_is_valid( p_src_physp ) )
+      goto Exit;
+
+    if( p_dest_physp )
+    {
+      if( !osm_physp_is_valid( p_dest_physp ) )
+        goto Exit;
+      /*
+        Ensure the two physp's are actually connected.
+        If not, bail out.
+      */
+      if( osm_physp_get_remote( p_src_physp ) != p_dest_physp )
+        goto Exit;
+    }
+    else
+    {
+      p_dest_physp = osm_physp_get_remote( p_src_physp );
+
+      if(p_dest_physp == NULL)
+        goto Exit;
+
+      if( !osm_physp_is_valid( p_dest_physp ) )
+        goto Exit;
+    }
+  }
+  else
+  {
+    if( p_dest_physp )
+    {
+      if( !osm_physp_is_valid( p_dest_physp ) )
+        goto Exit;
+
+      p_src_physp = osm_physp_get_remote( p_dest_physp );
+
+      if(p_src_physp == NULL)
+        goto Exit;
+    }
+    else
+      goto Exit;     /* no physp's, so nothing to do */
+  }
+
+  CL_ASSERT( p_src_physp );
+  CL_ASSERT( p_dest_physp );
+  CL_ASSERT( osm_physp_is_valid( p_src_physp ) );
+  CL_ASSERT( osm_physp_is_valid( p_dest_physp ) );
+
+  /* Check that the p_src_physp, p_dest_physp and p_req_physp
+     all share a pkey (doesn't have to be the same p_key). */
+  if (! osm_physp_share_pkey(p_rcv->p_log, p_src_physp, p_dest_physp))
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_lr_rcv_get_physp_link: "
+             "Source and Dest PhysPorts do not share PKey\n");
+      goto Exit;
+  }
+  if (! osm_physp_share_pkey(p_rcv->p_log, p_src_physp, p_req_physp))
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_lr_rcv_get_physp_link: "
+             "Source and Requester PhysPorts do not share PKey\n");
+    goto Exit;
+  }
+  if (! osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_dest_physp) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_lr_rcv_get_physp_link: "
+             "Requester and Dest PhysPorts do not share PKey\n");
+    goto Exit;
+  }
+
+  src_port_num = osm_physp_get_port_num( p_src_physp );
+  dest_port_num = osm_physp_get_port_num( p_dest_physp );
+
+  if( comp_mask & IB_LR_COMPMASK_FROM_PORT )
+    if( src_port_num != p_lr->from_port_num )
+      goto Exit;
+
+  if( comp_mask & IB_LR_COMPMASK_TO_PORT )
+    if( dest_port_num != p_lr->to_port_num )
+      goto Exit;
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_lr_rcv_get_physp_link: "
+             "Acquiring link record\n"
+             "\t\t\t\tsrc port 0x%" PRIx64 " (port 0x%X)"
+             ", dest port 0x%" PRIx64 " (port 0x%X)\n",
+             cl_ntoh64( osm_physp_get_port_guid( p_src_physp ) ),
+             src_port_num,
+             cl_ntoh64( osm_physp_get_port_guid( p_dest_physp ) ),
+             dest_port_num );
+  }
+
+  __get_base_lid(p_src_physp, &from_base_lid_ho);
+  __get_base_lid(p_dest_physp, &to_base_lid_ho);
+
+  __osm_lr_rcv_build_physp_link(p_rcv, cl_ntoh16(from_base_lid_ho),
+                                cl_ntoh16(to_base_lid_ho),
+                                src_port_num, dest_port_num, p_list);
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_lr_rcv_get_port_links(
+  IN osm_lr_rcv_t*            const p_rcv,
+  IN const ib_link_record_t*  const p_lr,
+  IN const osm_port_t*        p_src_port,
+  IN const osm_port_t*        p_dest_port,
+  IN const ib_net64_t         comp_mask,
+  IN cl_qlist_t*              const p_list,
+  IN const osm_physp_t*       p_req_physp )
+{
+  const osm_physp_t*          p_src_physp;
+  const osm_physp_t*          p_dest_physp;
+  const cl_qmap_t*            p_port_tbl;
+  uint8_t                     port_num;
+  uint8_t                     num_ports;
+  uint8_t                     dest_num_ports;
+  uint8_t                     dest_port_num;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_lr_rcv_get_port_links );
+
+  if( p_src_port )
+  {
+    if( p_dest_port )
+    {
+      /*
+        Build an LR for every link connected between both ports.
+        The inner function will discard physp combinations
+        that do not actually connect.  Don't bother screening
+        for that here.
+      */
+      num_ports = osm_port_get_num_physp( p_src_port );
+      dest_num_ports = osm_port_get_num_physp( p_dest_port );
+      for( port_num = 1; port_num < num_ports; port_num++ )
+      {
+        p_src_physp = osm_port_get_phys_ptr( p_src_port, port_num );
+        for( dest_port_num = 1; dest_port_num < dest_num_ports;
+             dest_port_num++ )
+        {
+          p_dest_physp = osm_port_get_phys_ptr( p_dest_port,
+                                                dest_port_num );
+          /* both physical ports should be with data */
+          if (p_src_physp && p_dest_physp)
+            __osm_lr_rcv_get_physp_link( p_rcv, p_lr, p_src_physp,
+                                         p_dest_physp, comp_mask,
+                                         p_list, p_req_physp );
+        }
+      }
+    }
+    else
+    {
+      /*
+        Build an LR for every link connected from the source port.
+      */
+      if( comp_mask & IB_LR_COMPMASK_FROM_PORT )
+      {
+        port_num = p_lr->from_port_num;
+        /* If the port number is out of the range of the p_src_port, then
+           this couldn't be a relevant record. */
+        if (port_num < p_src_port->physp_tbl_size) 
+        {          
+          p_src_physp = osm_port_get_phys_ptr( p_src_port, port_num );
+          if (p_src_physp)
+            __osm_lr_rcv_get_physp_link( p_rcv, p_lr, p_src_physp,
+                                         NULL, comp_mask, p_list,
+                                         p_req_physp );
+        }
+      }
+      else
+      {
+        num_ports = osm_port_get_num_physp( p_src_port );
+        for( port_num = 1; port_num < num_ports; port_num++ )
+        {
+          p_src_physp = osm_port_get_phys_ptr( p_src_port, port_num );
+          if (p_src_physp)
+            __osm_lr_rcv_get_physp_link( p_rcv, p_lr, p_src_physp,
+                                         NULL, comp_mask, p_list,
+                                         p_req_physp );
+        }
+      }
+    }
+  }
+  else
+  {
+    if( p_dest_port )
+    {
+      /*
+        Build an LR for every link connected to the dest port.
+      */
+      if( comp_mask & IB_LR_COMPMASK_TO_PORT )
+      {
+        port_num = p_lr->to_port_num;
+        /* If the port number is out of the range of the p_dest_port, then
+           this couldn't be a relevant record. */
+        if (port_num < p_dest_port->physp_tbl_size ) 
+        {
+          p_dest_physp = osm_port_get_phys_ptr(
+            p_dest_port, port_num );
+          if (p_dest_physp)
+            __osm_lr_rcv_get_physp_link( p_rcv, p_lr, NULL,
+                                         p_dest_physp, comp_mask,
+                                         p_list, p_req_physp );
+        }
+      }
+      else
+      {
+        num_ports = osm_port_get_num_physp( p_dest_port );
+        for( port_num = 1; port_num < num_ports; port_num++ )
+        {
+          p_dest_physp = osm_port_get_phys_ptr(
+            p_dest_port, port_num );
+          if (p_dest_physp)
+            __osm_lr_rcv_get_physp_link( p_rcv, p_lr, NULL,
+                                         p_dest_physp, comp_mask,
+                                         p_list, p_req_physp );
+        }
+      }
+    }
+    else
+    {
+      /*
+        Process the world (recurse once back into this function).
+      */
+      p_port_tbl = &p_rcv->p_subn->port_guid_tbl;
+      p_src_port = (osm_port_t*)cl_qmap_head( p_port_tbl );
+
+      while( p_src_port != (osm_port_t*)cl_qmap_end( p_port_tbl ) )
+      {
+        __osm_lr_rcv_get_port_links( p_rcv, p_lr, p_src_port,
+                                     NULL, comp_mask, p_list,
+                                     p_req_physp );
+
+        p_src_port = (osm_port_t*)cl_qmap_next(
+          &p_src_port->map_item );
+      }
+    }
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ Returns the SA status to return to the client.
+ **********************************************************************/
+static ib_net16_t
+__osm_lr_rcv_get_end_points(
+  IN osm_lr_rcv_t*         const p_rcv,
+  IN const osm_madw_t*     const p_madw,
+  OUT const osm_port_t**   const pp_src_port,
+  OUT const osm_port_t**   const pp_dest_port )
+{
+  const ib_link_record_t*  p_lr;
+  const ib_sa_mad_t*       p_sa_mad;
+  ib_net64_t               comp_mask;
+  ib_api_status_t          status;
+  ib_net16_t               sa_status = IB_SA_MAD_STATUS_SUCCESS;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_lr_rcv_get_end_points );
+
+  /*
+    Determine what fields are valid and then get a pointer
+    to the source and destination port objects, if possible.
+  */
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_lr = (ib_link_record_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+  comp_mask = p_sa_mad->comp_mask;
+  *pp_src_port = NULL;
+  *pp_dest_port = NULL;
+
+  if( p_sa_mad->comp_mask & IB_LR_COMPMASK_FROM_LID )
+  {
+    status = osm_get_port_by_base_lid( p_rcv->p_subn,
+                                       p_lr->from_lid,
+                                       pp_src_port );
+
+    if( (status != IB_SUCCESS) || (*pp_src_port == NULL) )
+    {
+      /*
+        This 'error' is the client's fault (bad lid) so
+        don't enter it as an error in our own log.
+        Return an error response to the client.
+      */
+      osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+               "__osm_lr_rcv_get_end_points: "
+               "No source port with LID = 0x%X\n",
+               cl_ntoh16( p_lr->from_lid ) );
+
+      sa_status = IB_SA_MAD_STATUS_NO_RECORDS;
+      goto Exit;
+    }
+  }
+
+  if( p_sa_mad->comp_mask & IB_LR_COMPMASK_TO_LID )
+  {
+    status = osm_get_port_by_base_lid( p_rcv->p_subn,
+                                       p_lr->to_lid,
+                                       pp_dest_port );
+
+    if( (status != IB_SUCCESS) || (*pp_dest_port == NULL) )
+    {
+      /*
+        This 'error' is the client's fault (bad lid) so
+        don't enter it as an error in our own log.
+        Return an error response to the client.
+      */
+      osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+               "__osm_lr_rcv_get_end_points: "
+               "No dest port with LID = 0x%X\n",
+               cl_ntoh16( p_lr->to_lid ) );
+
+      sa_status = IB_SA_MAD_STATUS_NO_RECORDS;
+      goto Exit;
+    }
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( sa_status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_lr_rcv_respond(
+  IN osm_lr_rcv_t*      const p_rcv,
+  IN const osm_madw_t*  const p_madw,
+  IN cl_qlist_t*        const p_list )
+{
+  osm_madw_t*           p_resp_madw;
+  const ib_sa_mad_t*    p_sa_mad;
+  ib_sa_mad_t*          p_resp_sa_mad;
+  size_t                num_rec, num_copied;
+#ifndef VENDOR_RMPP_SUPPORT
+  size_t               trim_num_rec;
+#endif
+  ib_link_record_t*     p_resp_lr;
+  ib_api_status_t       status;
+  osm_lr_item_t*        p_lr_item;
+  const ib_sa_mad_t*    p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_lr_rcv_respond );
+
+  num_rec = cl_qlist_count( p_list );
+  /*
+   * C15-0.1.30:
+   * If we do a SubnAdmGet and got more than one record it is an error !
+   */
+  if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) &&
+       (num_rec > 1)) {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_lr_rcv_respond: ERR 1806: "
+             "Got more than one record for SubnAdmGet (%zu)\n",
+             num_rec );
+    osm_sa_send_error( p_rcv->p_resp, p_madw,
+                       IB_SA_MAD_STATUS_TOO_MANY_RECORDS );
+
+    /* need to set the mem free ... */
+    p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list );
+    while( p_lr_item != (osm_lr_item_t*)cl_qlist_end( p_list ) )
+    {
+      cl_qlock_pool_put( &p_rcv->lr_pool, &p_lr_item->pool_item );
+      p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list );
+    }
+
+    goto Exit;
+  }
+
+#ifndef VENDOR_RMPP_SUPPORT
+  trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_link_record_t);
+  if (trim_num_rec < num_rec)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "__osm_lr_rcv_respond: "
+             "Number of records:%u trimmed to:%u to fit in one MAD\n",
+             num_rec, trim_num_rec );
+    num_rec = trim_num_rec;
+  }
+#endif
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_lr_rcv_respond: "
+             "Generating response with %zu records", num_rec );
+  }
+
+  /*
+    Get a MAD to reply. Address of Mad is in the received mad_wrapper
+  */
+  p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, 
+                                  p_madw->h_bind,
+                                  num_rec * sizeof(ib_link_record_t) + IB_SA_MAD_HDR_SIZE,
+                                  &p_madw->mad_addr );
+  if( !p_resp_madw )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_lr_rcv_respond: ERR 1802: "
+             "Unable to allocate MAD\n" );
+    /* Release the quick pool items */
+    p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list );
+    while( p_lr_item != (osm_lr_item_t*)cl_qlist_end( p_list ) )
+    {
+      cl_qlock_pool_put( &p_rcv->lr_pool, &p_lr_item->pool_item );
+      p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list );
+    }
+
+    goto Exit;
+  }
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+  /* Copy the header from the request to response */
+  memcpy( p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+  p_resp_sa_mad->attr_offset =
+    ib_get_attr_offset( sizeof(ib_link_record_t) );
+  /* C15-0.1.5 - always return SM_Key = 0 (table table 185 p 884) */
+  p_resp_sa_mad->sm_key = 0;
+
+#ifndef VENDOR_RMPP_SUPPORT
+  /* we support only one packet RMPP - so we will set the first and
+     last flags for gettable */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+  {
+    p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+  }
+#else
+  /* forcefully define the packet as RMPP one */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+  p_resp_lr = (ib_link_record_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+  if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+  {
+    p_resp_sa_mad->status = IB_SA_MAD_STATUS_NO_RECORDS;
+    memset( p_resp_lr, 0, sizeof(*p_resp_lr) );
+  }
+  else
+  {
+    p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list );
+    /* we need to track the number of copied items so we can
+     * stop the copy - but clear them all
+     */
+    num_copied = 0;
+    while( p_lr_item != (osm_lr_item_t*)cl_qlist_end( p_list ) )
+    {
+      /*  Copy the Link Records from the list into the MAD */
+      /*  only if we did not go over the mad size (since we might trimmed it) */
+      if (num_copied < num_rec)
+      {
+        *p_resp_lr = p_lr_item->link_rec;
+        num_copied++;
+      }
+      cl_qlock_pool_put( &p_rcv->lr_pool, &p_lr_item->pool_item );
+      p_resp_lr++;
+      p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list );
+    }
+  }
+
+  status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw,  FALSE );
+  if (status != IB_SUCCESS)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_lr_rcv_respond: ERR 1803: "
+             "Unable to send MAD (%s)\n", ib_get_err_str( status ) );
+    /*       osm_mad_pool_put( p_rcv->p_mad_pool, p_resp_madw ); */
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lr_rcv_process(
+  IN osm_lr_rcv_t*         const p_rcv,
+  IN const osm_madw_t*     const p_madw )
+{
+  const ib_link_record_t*  p_lr;
+  const ib_sa_mad_t*       p_sa_mad;
+  const osm_port_t*        p_src_port;
+  const osm_port_t*        p_dest_port;
+  cl_qlist_t               lr_list;
+  ib_net16_t               sa_status;
+  osm_physp_t*             p_req_physp;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_lr_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_lr = (ib_link_record_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+  CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_LINK_RECORD );
+
+  /* we only support SubnAdmGet and SubnAdmGetTable methods */
+  if ( (p_sa_mad->method != IB_MAD_METHOD_GET) &&
+       (p_sa_mad->method != IB_MAD_METHOD_GETTABLE)) {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_lr_rcv_process: ERR 1804: "
+             "Unsupported Method (%s)\n",
+             ib_get_sa_method_str( p_sa_mad->method ) );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+    goto Exit;
+  }
+
+  /* update the requester physical port. */
+  p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+                                          p_rcv->p_subn,
+                                          osm_madw_get_mad_addr_ptr(p_madw) );
+  if (p_req_physp == NULL)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_lr_rcv_process: ERR 1805: "
+             "Cannot find requester physical port\n" );
+    goto Exit;
+  }
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+    osm_dump_link_record( p_rcv->p_log, p_lr, OSM_LOG_DEBUG );
+
+  cl_qlist_init( &lr_list );
+
+  /*
+    Most SA functions (including this one) are read-only on the
+    subnet object, so we grab the lock non-exclusively.
+  */
+  cl_plock_acquire( p_rcv->p_lock );
+
+  sa_status = __osm_lr_rcv_get_end_points( p_rcv, p_madw,
+                                           &p_src_port, &p_dest_port );
+
+  if( sa_status == IB_SA_MAD_STATUS_SUCCESS )
+  {
+    __osm_lr_rcv_get_port_links( p_rcv, p_lr, p_src_port, p_dest_port,
+                                 p_sa_mad->comp_mask, &lr_list, p_req_physp );
+  }
+
+  cl_plock_release( p_rcv->p_lock );
+
+  if( (cl_qlist_count( &lr_list ) == 0) &&
+      (p_sa_mad->method == IB_MAD_METHOD_GET) )
+  {
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+    goto Exit;
+  }
+
+  __osm_lr_rcv_respond( p_rcv, p_madw, &lr_list );
+
+ Exit:
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_link_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_link_record_ctrl.c
new file mode 100644 (file)
index 0000000..56b3c7e
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_link_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_lr_rcv_ctrl_t.
+ * This object represents the link record controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_link_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_lr_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_lr_rcv_process( ((osm_lr_rcv_ctrl_t*)context)->p_rcv,
+                      (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lr_rcv_ctrl_construct(
+  IN osm_lr_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lr_rcv_ctrl_destroy(
+  IN osm_lr_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lr_rcv_ctrl_init(
+  IN osm_lr_rcv_ctrl_t* const p_ctrl,
+  IN osm_lr_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_lr_rcv_ctrl_init );
+
+  osm_lr_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_LINK_RECORD,
+    __osm_lr_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_lr_rcv_ctrl_init: ERR 1901: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mad_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mad_ctrl.c
new file mode 100644 (file)
index 0000000..07a389f
--- /dev/null
@@ -0,0 +1,651 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_mad_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_sa_mad_ctrl_t.
+ * This object is part of the SA object.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_sa_mad_ctrl.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_sa_response.h>
+
+/****f* opensm: SA/__osm_sa_mad_ctrl_disp_done_callback
+ * NAME
+ * __osm_sa_mad_ctrl_disp_done_callback
+ *
+ * DESCRIPTION
+ * This function is the Dispatcher callback that indicates
+ * a received MAD has been processed by the recipient.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sa_mad_ctrl_disp_done_callback(
+  IN void* context,
+  IN void* p_data )
+{
+  osm_sa_mad_ctrl_t* const p_ctrl = (osm_sa_mad_ctrl_t*)context;
+  osm_madw_t* const p_madw = (osm_madw_t*)p_data;
+
+  OSM_LOG_ENTER( p_ctrl->p_log, __osm_sa_mad_ctrl_disp_done_callback );
+
+  CL_ASSERT( p_madw );
+  /*
+    Return the MAD & wrapper to the pool.
+  */
+  osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+  OSM_LOG_EXIT( p_ctrl->p_log );
+}
+/************/
+
+/****f* opensm: SA/__osm_sa_mad_ctrl_process
+ * NAME
+ * __osm_sa_mad_ctrl_process
+ *
+ * DESCRIPTION
+ * This function handles known methods for received MADs.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sa_mad_ctrl_process(
+  IN osm_sa_mad_ctrl_t* const p_ctrl,
+  IN osm_madw_t *p_madw )
+{
+  ib_sa_mad_t* p_sa_mad;
+  cl_status_t status;
+  cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
+  uint64_t last_dispatched_msg_queue_time_msec;
+  uint32_t num_messages;
+
+  OSM_LOG_ENTER( p_ctrl->p_log, __osm_sa_mad_ctrl_process );
+
+  /* 
+     If the dispatcher is showing us that it is overloaded
+     there is no point in placing the request in. We should instead provide 
+     immediate response - IB_RESOURCE_BUSY
+     But how do we know? 
+     The dispatcher reports back the number of outstanding messages and the 
+     time the last message stayed in the queue.
+     HACK: Actually, we cannot send a mad from within the receive callback;
+     thus - we will just drop it.
+  */
+  cl_disp_get_queue_status(p_ctrl->h_disp,
+                          &num_messages,
+                          &last_dispatched_msg_queue_time_msec);
+  if ((num_messages > 1) && 
+      (p_ctrl->p_subn->opt.max_msg_fifo_timeout) &&
+      (last_dispatched_msg_queue_time_msec > 
+       p_ctrl->p_subn->opt.max_msg_fifo_timeout))
+  {
+    osm_log( p_ctrl->p_log, OSM_LOG_INFO,
+             "__osm_sa_mad_ctrl_process: "
+             /*             "Responding BUSY status since the dispatcher is already"*/
+             "Dropping MAD since the dispatcher is already"
+            " overloaded with %u messages and queue time of:"
+            "%" PRIu64 "[msec]\n",
+            num_messages, last_dispatched_msg_queue_time_msec );
+
+    /* send a busy response */
+    /*    osm_sa_send_error( p_ctrl->p_resp, p_madw, IB_RESOURCE_BUSY ); */
+    
+    /* return the request to the pool */
+    osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+    
+    goto Exit;
+  }
+  
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+
+  /*
+    Note that attr_id (like the rest of the MAD) is in
+    network byte order.
+  */
+  switch( p_sa_mad->attr_id )
+  {
+  case IB_MAD_ATTR_CLASS_PORT_INFO:
+    msg_id = OSM_MSG_MAD_CLASS_PORT_INFO;
+    break;
+
+  case IB_MAD_ATTR_NODE_RECORD:
+    msg_id = OSM_MSG_MAD_NODE_RECORD;
+    break;
+
+  case IB_MAD_ATTR_PORTINFO_RECORD:
+    msg_id = OSM_MSG_MAD_PORTINFO_RECORD;
+    break;
+
+  case IB_MAD_ATTR_LINK_RECORD:
+    msg_id = OSM_MSG_MAD_LINK_RECORD;
+    break;
+
+  case IB_MAD_ATTR_SMINFO_RECORD:
+    msg_id = OSM_MSG_MAD_SMINFO_RECORD;
+    break;
+
+  case IB_MAD_ATTR_SERVICE_RECORD:
+    msg_id = OSM_MSG_MAD_SERVICE_RECORD;
+    break;
+
+  case IB_MAD_ATTR_PATH_RECORD:
+    msg_id = OSM_MSG_MAD_PATH_RECORD;
+    break;
+
+  case IB_MAD_ATTR_MCMEMBER_RECORD:
+    msg_id = OSM_MSG_MAD_MCMEMBER_RECORD;
+    break;
+
+  case IB_MAD_ATTR_INFORM_INFO:
+    msg_id = OSM_MSG_MAD_INFORM_INFO;
+    break;
+
+  case IB_MAD_ATTR_VLARB_RECORD:
+    msg_id = OSM_MSG_MAD_VL_ARB_RECORD;
+    break;
+
+  case IB_MAD_ATTR_SLVL_RECORD:
+    msg_id = OSM_MSG_MAD_SLVL_TBL_RECORD;
+    break;
+
+  case IB_MAD_ATTR_PKEY_TBL_RECORD:
+    msg_id = OSM_MSG_MAD_PKEY_TBL_RECORD;
+    break;
+
+  case IB_MAD_ATTR_LFT_RECORD:
+    msg_id = OSM_MSG_MAD_LFT_RECORD;
+    break;
+
+  case IB_MAD_ATTR_GUIDINFO_RECORD:
+    msg_id = OSM_MSG_MAD_GUIDINFO_RECORD;
+    break;
+
+  case IB_MAD_ATTR_INFORM_INFO_RECORD:
+    msg_id = OSM_MSG_MAD_INFORM_INFO_RECORD;
+    break;
+
+  case IB_MAD_ATTR_SWITCH_INFO_RECORD:
+    msg_id = OSM_MSG_MAD_SWITCH_INFO_RECORD;
+    break;
+
+  case IB_MAD_ATTR_MFT_RECORD:
+    msg_id = OSM_MSG_MAD_MFT_RECORD;
+    break;
+
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+  case IB_MAD_ATTR_MULTIPATH_RECORD:
+    msg_id = OSM_MSG_MAD_MULTIPATH_RECORD;
+    break;
+#endif
+
+  default:
+    osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+             "__osm_sa_mad_ctrl_process: ERR 1A01: "
+             "Unsupported attribute = 0x%X\n",
+             cl_ntoh16( p_sa_mad->attr_id ) );
+    osm_dump_sa_mad( p_ctrl->p_log, p_sa_mad, OSM_LOG_ERROR );
+  }
+
+  if( msg_id != CL_DISP_MSGID_NONE )
+  {
+    /*
+      Post this MAD to the dispatcher for asynchronous
+      processing by the appropriate controller.
+    */
+    osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+             "__osm_sa_mad_ctrl_process: "
+             "Posting Dispatcher message %s\n",
+             osm_get_disp_msg_str( msg_id ) );
+
+    status = cl_disp_post( p_ctrl->h_disp,
+                           msg_id,
+                           p_madw,
+                           __osm_sa_mad_ctrl_disp_done_callback,
+                           p_ctrl );
+
+    if( status != CL_SUCCESS )
+    {
+      osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+               "__osm_sa_mad_ctrl_process: ERR 1A02: "
+               "Dispatcher post message failed (%s) for attribute = 0x%X\n",
+               CL_STATUS_MSG( status ),
+               cl_ntoh16( p_sa_mad->attr_id ) );
+
+      osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+      goto Exit;
+    }
+  }
+  else
+  {
+    /*
+      There is an unknown MAD attribute type for which there is
+      no recipient.  Simply retire the MAD here.
+    */
+    osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_ctrl->p_log );
+}
+/*
+ * PARAMETERS
+ *
+ * RETURN VALUES
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* opensm: SA/__osm_sa_mad_ctrl_rcv_callback
+ * NAME
+ * __osm_sa_mad_ctrl_rcv_callback
+ *
+ * DESCRIPTION
+ * This is the callback from the transport layer for received MADs.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sa_mad_ctrl_rcv_callback(
+  IN osm_madw_t *p_madw,
+  IN void *bind_context,
+  IN osm_madw_t *p_req_madw )
+{
+  osm_sa_mad_ctrl_t* p_ctrl = (osm_sa_mad_ctrl_t*)bind_context;
+  ib_sa_mad_t* p_sa_mad;
+
+  OSM_LOG_ENTER( p_ctrl->p_log, __osm_sa_mad_ctrl_rcv_callback );
+
+  CL_ASSERT( p_madw );
+
+  /*
+    A MAD was received from the wire, possibly in response to a request.
+  */
+  cl_atomic_inc( &p_ctrl->p_stats->qp1_mads_rcvd );
+
+  if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+             "__osm_sa_mad_ctrl_rcv_callback: "
+             "%u QP1 MADs received\n",
+             p_ctrl->p_stats->qp1_mads_rcvd );
+  }
+
+  /*
+   * C15-0.1.3 requires not responding to any MAD if the SM is
+   * not in active state!
+   * We will not respond if the sm_state is not MASTER, or if the 
+   * first_time_master_sweep flag (of the subnet) is TRUE - this 
+   * flag indicates that the master still didn't finish its first 
+   * sweep, so the subnet is not up and stable yet.
+   */
+  if ( p_ctrl->p_subn->sm_state != IB_SMINFO_STATE_MASTER )
+  {
+    osm_log( p_ctrl->p_log, OSM_LOG_VERBOSE,
+             "__osm_sa_mad_ctrl_rcv_callback: "
+             "Received SA MAD while SM not MASTER. MAD ignored\n");
+    osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+    goto Exit;
+  }
+  if ( p_ctrl->p_subn->first_time_master_sweep == TRUE )
+  {
+    osm_log( p_ctrl->p_log, OSM_LOG_VERBOSE,
+             "__osm_sa_mad_ctrl_rcv_callback: "
+             "Received SA MAD while SM in first sweep. MAD ignored\n");
+    osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+    goto Exit;
+  }
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+
+  if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_FRAMES ) )
+    osm_dump_sa_mad( p_ctrl->p_log, p_sa_mad, OSM_LOG_FRAMES );
+
+  /*
+   * C15-0.1.5 - Table 185: SA Header - p884
+   * SM_key should be either 0 or match the current SM_Key
+   * otherwise discard the MAD.
+   */
+  if ((p_sa_mad->sm_key != 0) &&
+      (p_sa_mad->sm_key != p_ctrl->p_subn->opt.sm_key)) {
+    osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+             "__osm_sa_mad_ctrl_rcv_callback: ERR 1A04: "
+             "Non-Zero SA MAD SM_Key: 0x%" PRIx64 " != SM_Key: 0x%" PRIx64
+             "; MAD ignored\n",
+             cl_ntoh64(p_sa_mad->sm_key),
+             cl_ntoh64(p_ctrl->p_subn->opt.sm_key)
+             );
+    osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+    goto Exit;
+  }
+
+  switch( p_sa_mad->method )
+  {
+  case IB_MAD_METHOD_REPORT_RESP:
+    /* we do not really do anything with report represses -
+       just retire the transaction */
+    osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+             "__osm_sa_mad_ctrl_rcv_callback: "
+             "Received Report Repress. Retiring the transaction\n");
+
+    if (p_req_madw)
+      osm_mad_pool_put( p_ctrl->p_mad_pool, p_req_madw );
+    osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+
+    break;
+
+  case IB_MAD_METHOD_GET:
+  case IB_MAD_METHOD_GETTABLE:
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+  case IB_MAD_METHOD_GETMULTI:
+#endif
+  case IB_MAD_METHOD_SET:
+  case IB_MAD_METHOD_DELETE:
+    __osm_sa_mad_ctrl_process( p_ctrl, p_madw );
+    break;
+
+  default:
+    osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+             "__osm_sa_mad_ctrl_rcv_callback: ERR 1A05: "
+             "Unsupported method = 0x%X\n",
+             p_sa_mad->method );
+    osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_ctrl->p_log );
+}
+/*
+ * PARAMETERS
+ *
+ * RETURN VALUES
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* opensm: SA/__osm_sa_mad_ctrl_send_err_callback
+ * NAME
+ * __osm_sa_mad_ctrl_send_err_callback
+ *
+ * DESCRIPTION
+ * This is the callback from the transport layer for send errors
+ * on MADs that were expecting a response.
+ *
+ * SYNOPSIS
+ */
+void
+__osm_sa_mad_ctrl_send_err_callback(
+  IN void *bind_context,
+  IN osm_madw_t *p_madw )
+{
+  osm_sa_mad_ctrl_t* p_ctrl = (osm_sa_mad_ctrl_t*)bind_context;
+  cl_status_t status;
+
+  OSM_LOG_ENTER( p_ctrl->p_log, __osm_sa_mad_ctrl_send_err_callback );
+
+  osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+           "__osm_sa_mad_ctrl_send_err_callback: ERR 1A06: "
+           "MAD transaction completed in error\n" );
+
+  /*
+    We should never be here since the SA never originates a request.
+    Unless we generated a Report(Notice)
+  */
+
+  CL_ASSERT( p_madw );
+
+  /*
+    An error occurred.  No response was received to a request MAD.
+    Retire the original request MAD.
+  */
+
+  osm_dump_sa_mad(p_ctrl->p_log, osm_madw_get_sa_mad_ptr( p_madw ),
+                  OSM_LOG_ERROR );
+
+  /*  __osm_sm_mad_ctrl_update_wire_stats( p_ctrl ); */
+
+  if( osm_madw_get_err_msg( p_madw ) != CL_DISP_MSGID_NONE )
+  {
+    if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+               "__osm_sa_mad_ctrl_send_err_callback: "
+               "Posting Dispatcher message %s\n",
+               osm_get_disp_msg_str( osm_madw_get_err_msg( p_madw ) ) );
+    }
+
+    status = cl_disp_post( p_ctrl->h_disp,
+                           osm_madw_get_err_msg( p_madw ),
+                           p_madw,
+                           __osm_sa_mad_ctrl_disp_done_callback,
+                           p_ctrl );
+    if( status != CL_SUCCESS )
+    {
+      osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+               "__osm_sa_mad_ctrl_send_err_callback: ERR 1A07: "
+               "Dispatcher post message failed (%s)\n",
+               CL_STATUS_MSG( status ) );
+    }
+  }
+  else
+  {
+    /*
+      No error message was provided, just retire the MAD.
+    */
+    osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+  }
+
+  OSM_LOG_EXIT( p_ctrl->p_log );
+}
+/*
+ * PARAMETERS
+ *
+ * RETURN VALUES
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_mad_ctrl_construct(
+  IN osm_sa_mad_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_mad_ctrl_destroy(
+  IN osm_sa_mad_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sa_mad_ctrl_init(
+  IN osm_sa_mad_ctrl_t* const p_ctrl,
+  IN osm_sa_resp_t*  const p_resp,
+  IN osm_mad_pool_t* const p_mad_pool,
+  IN osm_vendor_t* const p_vendor,
+  IN osm_subn_t* const p_subn,
+  IN osm_log_t* const p_log,
+  IN osm_stats_t* const p_stats,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_sa_mad_ctrl_init );
+
+  osm_sa_mad_ctrl_construct( p_ctrl );
+
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_disp = p_disp;
+  p_ctrl->p_mad_pool = p_mad_pool;
+  p_ctrl->p_vendor = p_vendor;
+  p_ctrl->p_stats = p_stats;
+  p_ctrl->p_subn = p_subn;
+  p_ctrl->p_resp = p_resp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    CL_DISP_MSGID_NONE,
+    NULL,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_sa_mad_ctrl_init: ERR 1A08: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sa_mad_ctrl_bind(
+  IN osm_sa_mad_ctrl_t* const p_ctrl,
+  IN const ib_net64_t port_guid )
+{
+  osm_bind_info_t bind_info;
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_ctrl->p_log, osm_sa_mad_ctrl_bind );
+
+  if( p_ctrl->h_bind != OSM_BIND_INVALID_HANDLE )
+  {
+    osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+             "osm_sa_mad_ctrl_bind: ERR 1A09: "
+             "Multiple binds not allowed\n" );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  bind_info.class_version = 2;
+  bind_info.is_responder = TRUE;
+  bind_info.is_report_processor = FALSE;
+  bind_info.is_trap_processor = FALSE;
+  bind_info.mad_class = IB_MCLASS_SUBN_ADM;
+  bind_info.port_guid = port_guid;
+  bind_info.recv_q_size = OSM_SM_DEFAULT_QP1_RCV_SIZE;
+  bind_info.send_q_size = OSM_SM_DEFAULT_QP1_SEND_SIZE;
+
+  osm_log( p_ctrl->p_log, OSM_LOG_VERBOSE,
+           "osm_sa_mad_ctrl_bind: "
+           "Binding to port GUID 0x%" PRIx64 "\n",
+           cl_ntoh64( port_guid ) );
+
+  p_ctrl->h_bind = osm_vendor_bind( p_ctrl->p_vendor,
+                                    &bind_info,
+                                    p_ctrl->p_mad_pool,
+                                    __osm_sa_mad_ctrl_rcv_callback,
+                                    __osm_sa_mad_ctrl_send_err_callback,
+                                    p_ctrl );
+
+  if( p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE )
+  {
+    status = IB_ERROR;
+    osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+             "osm_sa_mad_ctrl_bind: ERR 1A10: "
+             "Vendor specific bind failed (%s)\n",
+             ib_get_err_str(status) );
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_ctrl->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sa_mad_ctrl_unbind(
+  IN osm_sa_mad_ctrl_t* const p_ctrl)
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_ctrl->p_log, osm_sa_mad_ctrl_unbind );
+
+  if( p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE )
+  {
+    osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+             "osm_sa_mad_ctrl_unbind: ERR 1A11: "
+             "No previous bind\n" );
+    status = IB_ERROR;
+    goto Exit;
+  }
+  
+  osm_vendor_unbind( p_ctrl->h_bind );
+ Exit:
+  OSM_LOG_EXIT( p_ctrl->p_log );
+  return( status );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mcmember_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mcmember_record.c
new file mode 100644 (file)
index 0000000..771bed0
--- /dev/null
@@ -0,0 +1,2383 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_mcmember_record.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_mcmr_recv_t.
+ * This object represents the MCMemberRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.15 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_mcmember_record.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <vendor/osm_vendor.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_inform.h>
+
+#define OSM_MCMR_RCV_POOL_MIN_SIZE     32
+#define OSM_MCMR_RCV_POOL_GROW_SIZE    32
+
+typedef  struct _osm_mcmr_item
+{
+  cl_pool_item_t     pool_item;
+  ib_member_rec_t    rec;
+} osm_mcmr_item_t;
+
+typedef  struct   osm_sa_mcmr_search_ctxt {
+  const ib_member_rec_t  *p_mcmember_rec;
+  osm_mgrp_t      *p_mgrp;
+  osm_mcmr_recv_t *p_rcv;
+  cl_qlist_t      *p_list; /*  hold results */
+  ib_net64_t      comp_mask;
+  const osm_physp_t*    p_req_physp;
+  boolean_t       trusted_req;
+} osm_sa_mcmr_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcmr_rcv_construct(
+  IN osm_mcmr_recv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+  cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcmr_rcv_destroy(
+  IN osm_mcmr_recv_t* const p_rcv )
+{
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_mcmr_rcv_destroy );
+
+  cl_qlock_pool_destroy( &p_rcv->pool );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mcmr_rcv_init(
+  IN osm_sm_t * const p_sm,
+  IN osm_mcmr_recv_t* const p_rcv,
+  IN osm_sa_resp_t* const p_resp,
+  IN osm_mad_pool_t* const p_mad_pool,
+  IN osm_subn_t* const p_subn,
+  IN osm_log_t* const p_log,
+  IN cl_plock_t* const p_lock )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_mcmr_rcv_init );
+
+  osm_mcmr_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_sm = p_sm;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_resp = p_resp;
+  p_rcv->p_mad_pool = p_mad_pool;
+  p_rcv->mlid_ho = 0xC000;
+
+  status = cl_qlock_pool_init( &p_rcv->pool,
+                               OSM_MCMR_RCV_POOL_MIN_SIZE,
+                               0,
+                               OSM_MCMR_RCV_POOL_GROW_SIZE,
+                               sizeof(osm_mcmr_item_t),
+                               NULL, NULL, NULL );
+  if (status != CL_SUCCESS)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_mcmr_rcv_init: ERR 1B02: "
+             "qlock pool init failed (%d)\n",
+             status );
+  }
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ A search function that compares the given mgrp with the search context
+ if there is a match by mgid the p_mgrp is copied to the search context
+ p_mgrp component
+
+ Inputs:
+ p_map_item - which is part of a mgrp object
+ context - points to the osm_sa_mcmr_search_ctxt_t including the mgid
+   looked for and the result p_mgrp
+**********************************************************************/
+static void
+__search_mgrp_by_mgid(
+  IN  cl_map_item_t* const    p_map_item,
+  IN  void*                   context )
+{
+  osm_mgrp_t* p_mgrp = (osm_mgrp_t*)p_map_item;
+  osm_sa_mcmr_search_ctxt_t *p_ctxt = (osm_sa_mcmr_search_ctxt_t *) context;
+  const ib_member_rec_t *p_recvd_mcmember_rec;
+  osm_mcmr_recv_t *p_rcv;
+
+  p_recvd_mcmember_rec = p_ctxt->p_mcmember_rec;
+  p_rcv = p_ctxt->p_rcv;
+
+  /* ignore groups marked for deletion */
+  if (p_mgrp->to_be_deleted)
+    return;
+  /* compare entire MGID so different scope will not sneak in for
+     the same MGID */
+  if (memcmp(&p_mgrp->mcmember_rec.mgid,
+             &p_recvd_mcmember_rec->mgid,
+             sizeof(ib_gid_t)))
+    return;
+
+  if (p_ctxt->p_mgrp)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__search_mgrp_by_mgid: ERR 1B03: "
+             "Multiple MC groups for same MGID\n" );
+    return;
+  }
+
+  p_ctxt->p_mgrp = p_mgrp;
+
+}
+
+/**********************************************************************
+ Look for a MGRP in the mgrp_mlid_tbl by mlid
+**********************************************************************/
+static osm_mgrp_t *
+__get_mgrp_by_mlid(
+  IN osm_mcmr_recv_t* const p_rcv,
+  IN ib_net16_t const mlid)
+{
+  cl_map_item_t *map_item;
+
+  map_item = cl_qmap_get(&p_rcv->p_subn->mgrp_mlid_tbl, mlid);
+  if (map_item == cl_qmap_end(&p_rcv->p_subn->mgrp_mlid_tbl))
+  {
+    return NULL;
+  }
+  return (osm_mgrp_t *)map_item;
+
+}
+
+/**********************************************************************
+Look for a MGRP in the mgrp_mlid_tbl by mgid
+***********************************************************************/
+static ib_api_status_t
+__get_mgrp_by_mgid(
+  IN osm_mcmr_recv_t* const p_rcv,
+  IN ib_member_rec_t* p_recvd_mcmember_rec,
+  OUT osm_mgrp_t **pp_mgrp)
+{
+  osm_sa_mcmr_search_ctxt_t mcmr_search_context;
+
+  mcmr_search_context.p_mcmember_rec = p_recvd_mcmember_rec;
+  mcmr_search_context.p_rcv = p_rcv;
+  mcmr_search_context.p_mgrp = NULL;
+
+  cl_qmap_apply_func( &p_rcv->p_subn->mgrp_mlid_tbl,
+                      __search_mgrp_by_mgid,
+                      &mcmr_search_context);
+
+  if (mcmr_search_context.p_mgrp == NULL)
+  {
+    return IB_NOT_FOUND;
+  }
+
+  *pp_mgrp = mcmr_search_context.p_mgrp;
+  return IB_SUCCESS;
+}
+
+/*********************************************************************
+Copy certain fields between two mcmember records
+used during the process of join request to copy data from the mgrp to the
+port record.
+**********************************************************************/
+static inline void
+__copy_from_create_mc_rec(
+  IN ib_member_rec_t * const dest,
+  IN const ib_member_rec_t *const src)
+{
+  dest->qkey = src->qkey;
+  dest->mlid = src->mlid;
+  dest->tclass = src->tclass;
+  dest->pkey = src->pkey;
+  dest->sl_flow_hop = src->sl_flow_hop;
+  dest->mtu = src->mtu;
+  dest->rate = src->rate;
+  dest->pkt_life = src->pkt_life;
+}
+
+/*********************************************************************
+Return an mlid to the pool of free mlids.
+But this implementation is not a pool - it is simply scanning through
+the MGRP database for unused mlids...
+*********************************************************************/
+static void
+__free_mlid(
+  IN osm_mcmr_recv_t* const p_rcv,
+  IN uint16_t mlid)
+{
+  UNUSED_PARAM(p_rcv);
+  UNUSED_PARAM(mlid);
+}
+
+/*********************************************************************
+Get a new unused mlid by scanning all the used ones in the subnet.
+TODO: Implement a more scalable - O(1) solution based on pool of
+available mlids.
+**********************************************************************/
+static ib_net16_t
+__get_new_mlid(
+  IN osm_mcmr_recv_t* const p_rcv,
+  IN ib_net16_t requested_mlid)
+{
+  osm_subn_t   *p_subn = p_rcv->p_subn;
+  osm_mgrp_t   *p_mgrp;
+  uint8_t      *used_mlids_array;
+  uint16_t      idx;
+  uint16_t      mlid; /* the result */
+  uint16_t      max_num_mlids;
+
+  OSM_LOG_ENTER(p_rcv->p_log, __get_new_mlid);
+
+  if (requested_mlid && cl_ntoh16(requested_mlid) >= IB_LID_MCAST_START_HO &&
+      cl_ntoh16(requested_mlid) < p_subn->max_multicast_lid_ho &&
+      cl_qmap_get(&p_subn->mgrp_mlid_tbl, requested_mlid) ==
+      cl_qmap_end(&p_subn->mgrp_mlid_tbl) ) {
+    mlid = cl_ntoh16(requested_mlid);
+    goto Exit;
+  }
+
+  /* If MCGroups table empty, first return the min mlid */
+  p_mgrp = (osm_mgrp_t*)cl_qmap_head( &p_subn->mgrp_mlid_tbl );
+  if (p_mgrp == (osm_mgrp_t*)cl_qmap_end( &p_subn->mgrp_mlid_tbl ))
+  {
+    mlid = IB_LID_MCAST_START_HO;
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "__get_new_mlid: "
+             "No multicast groups found using minimal mlid:0x%04X\n",
+             mlid );
+    goto Exit;
+  }
+  max_num_mlids =
+    p_rcv->p_subn->max_multicast_lid_ho - IB_LID_MCAST_START_HO;
+  /* track all used mlids in the array (by mlid index) */
+  used_mlids_array =
+    (uint8_t *)malloc(sizeof(uint8_t)*max_num_mlids);
+  if (used_mlids_array)
+    memset(used_mlids_array, 0, sizeof(uint8_t)*max_num_mlids);
+  if (!used_mlids_array)
+    return 0;
+  /* scan all available multicast groups in the DB and fill in the table */
+  while( p_mgrp != (osm_mgrp_t*)cl_qmap_end( &p_subn->mgrp_mlid_tbl ) )
+  {
+    /* ignore mgrps marked for deletion */
+    if (p_mgrp->to_be_deleted == FALSE)
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+               "__get_new_mlid: "
+               "Found mgrp with lid:0x%X MGID: 0x%016" PRIx64 " : "
+               "0x%016" PRIx64 "\n",
+               cl_ntoh16( p_mgrp->mlid),
+               cl_ntoh64( p_mgrp->mcmember_rec.mgid.unicast.prefix ),
+               cl_ntoh64( p_mgrp->mcmember_rec.mgid.unicast.interface_id ) );
+      
+      /* Map in table */
+      if (cl_ntoh16(p_mgrp->mlid) > p_rcv->p_subn->max_multicast_lid_ho)
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                 "__get_new_mlid: ERR 1B27: "
+                 "Found mgrp with mlid:0x%04X > max allowed mlid:0x%04X\n",
+                 cl_ntoh16(p_mgrp->mlid), 
+                 max_num_mlids + IB_LID_MCAST_START_HO );
+      }
+      else
+      {
+        used_mlids_array[cl_ntoh16(p_mgrp->mlid) - IB_LID_MCAST_START_HO] = 1;
+      }
+    }
+    p_mgrp = (osm_mgrp_t*)cl_qmap_next( &p_mgrp->map_item );
+  }
+  /* Find "mlid holes" in the mgrp table */ 
+  for (idx = 0;
+       (idx < max_num_mlids) && (used_mlids_array[idx] == 1);
+       idx++);
+  /* did it go above the maximal mlid allowed */
+  if ( idx < max_num_mlids )
+  {
+    mlid = idx + IB_LID_MCAST_START_HO;
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "__get_new_mlid: "
+             "Found available mlid:0x%04X at idx:%u\n",
+             mlid, idx );
+  }
+  else
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__get_new_mlid: ERR 1B23: "
+             "All available:%u mlids are taken\n",
+             max_num_mlids );   
+    mlid = 0;
+  }
+  free(used_mlids_array);
+ Exit:
+  OSM_LOG_EXIT(p_rcv->p_log);
+  return cl_hton16(mlid);
+}
+
+/*********************************************************************
+This procedure is only invoked to cleanup an INTERMEDIATE mgrp.
+If there is only one port on the mgrp it means that the current
+request was the only member and the group is not really needed. So we
+silently drop it. Since it was an intermediate group no need to
+re-route it.
+**********************************************************************/
+static void
+__cleanup_mgrp(
+  IN osm_mcmr_recv_t* const p_rcv,
+  IN ib_net16_t const mlid)
+{
+  osm_mgrp_t *p_mgrp;
+
+  p_mgrp = __get_mgrp_by_mlid(p_rcv, mlid);
+  if(p_mgrp)
+  {
+    /* Remove MGRP only if osm_mcm_port_t count is 0 and
+     * Not a well known group
+     */
+    if(cl_is_qmap_empty(&p_mgrp->mcm_port_tbl) &&
+       (p_mgrp->well_known == FALSE))
+    {
+      cl_qmap_remove_item(&p_rcv->p_subn->mgrp_mlid_tbl,
+                          (cl_map_item_t *)p_mgrp );
+      osm_mgrp_destroy(p_mgrp);
+    }
+  }
+}
+
+/*********************************************************************
+Add a port to the group. Calculating its PROXY_JOIN by the Port and
+requester gids.
+**********************************************************************/
+static ib_api_status_t
+__add_new_mgrp_port(
+  IN osm_mcmr_recv_t *p_rcv,
+  IN osm_mgrp_t      *p_mgrp,
+  IN ib_member_rec_t *p_recvd_mcmember_rec,
+  IN osm_mad_addr_t  *p_mad_addr,
+  OUT osm_mcm_port_t **pp_mcmr_port)
+{
+  boolean_t proxy_join;
+  ib_gid_t requester_gid;
+  ib_api_status_t res;
+
+  /* set the proxy_join if the requester gid is not identical to the
+     joined gid */
+  res = osm_get_gid_by_mad_addr( p_rcv->p_log,
+                                 p_rcv->p_subn,
+                                 p_mad_addr, &requester_gid );
+  if ( res != IB_SUCCESS )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__add_new_mgrp_port: ERR 1B29: "
+             "Could not find GID for requester\n" );
+    
+    return IB_INVALID_PARAMETER;
+  }
+
+  if (!memcmp(&p_recvd_mcmember_rec->port_gid, &requester_gid,
+              sizeof(ib_gid_t)))
+  {
+    proxy_join = FALSE;
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__add_new_mgrp_port: "
+             "Create new port with proxy_join FALSE\n" );
+  }
+  else
+  {
+    /* The port is not the one specified in PortGID.
+       The check that the requester is in the same partition as
+       the PortGID is done before - just need to update the proxy_join. */
+    proxy_join = TRUE;
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__add_new_mgrp_port: "
+             "Create new port with proxy_join TRUE\n" );
+  }
+
+  *pp_mcmr_port = osm_mgrp_add_port( p_mgrp,
+                                     &p_recvd_mcmember_rec->port_gid,
+                                     p_recvd_mcmember_rec->scope_state,
+                                     proxy_join );
+  if(*pp_mcmr_port == NULL)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__add_new_mgrp_port: ERR 1B06: "
+             "osm_mgrp_add_port failed\n" );
+
+    return IB_INSUFFICIENT_MEMORY;
+  }
+
+  return IB_SUCCESS;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline boolean_t
+__check_join_comp_mask(ib_net64_t comp_mask)
+{
+  return( (comp_mask & JOIN_MC_COMP_MASK) == JOIN_MC_COMP_MASK );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline boolean_t
+__check_create_comp_mask(ib_net64_t comp_mask,
+                         ib_member_rec_t *p_recvd_mcmember_rec)
+{
+  return(
+    ((comp_mask & REQUIRED_MC_CREATE_COMP_MASK) == REQUIRED_MC_CREATE_COMP_MASK)
+    );
+}
+
+/**********************************************************************
+Generate the response MAD
+**********************************************************************/
+static void
+__osm_mcmr_rcv_respond(
+  IN const osm_mcmr_recv_t* const p_rcv,
+  IN const osm_madw_t* const p_madw,
+  IN ib_member_rec_t *p_mcmember_rec )
+{
+  osm_madw_t   *p_resp_madw;
+  ib_sa_mad_t *p_sa_mad, *p_resp_sa_mad;
+  ib_member_rec_t *p_resp_mcmember_rec;
+  ib_api_status_t status;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_mcmr_rcv_respond );
+
+  /* 
+   *  Get a MAD to reply. Address of Mad is in the received mad_wrapper
+   */
+  p_resp_madw = osm_mad_pool_get(p_rcv->p_mad_pool,
+                                 p_madw->h_bind,
+                                 sizeof(ib_member_rec_t)+IB_SA_MAD_HDR_SIZE,
+                                 osm_madw_get_mad_addr_ptr(p_madw) );
+  if ( !p_resp_madw )
+  {
+    goto Exit;
+  }
+
+  p_resp_sa_mad = (ib_sa_mad_t*)p_resp_madw->p_mad;
+  p_sa_mad = (ib_sa_mad_t*)p_madw->p_mad;
+  /*  Copy the MAD header back into the response mad */
+  memcpy(p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE);
+  /*  based on the current method decide about the response: */
+  if ((p_resp_sa_mad->method == IB_MAD_METHOD_GET) ||
+      (p_resp_sa_mad->method == IB_MAD_METHOD_SET)) {
+    p_resp_sa_mad->method = IB_MAD_METHOD_GET_RESP;
+  }
+  else if (p_resp_sa_mad->method == IB_MAD_METHOD_DELETE) {
+    p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+  }
+  else
+  {
+    CL_ASSERT( p_resp_sa_mad->method == 0);
+  }
+
+  /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
+  p_resp_sa_mad->sm_key = 0;
+
+  /* Fill in the offset (paylen will be done by the rmpp SAR) */
+  p_resp_sa_mad->attr_offset =
+    ib_get_attr_offset( sizeof(ib_member_rec_t) );
+  p_resp_mcmember_rec = (ib_member_rec_t*)&p_resp_sa_mad->data;
+
+  *p_resp_mcmember_rec = *p_mcmember_rec;
+
+  /* Fill in the mtu, rate, and packet lifetime selectors */
+  p_resp_mcmember_rec->mtu &= 0x3f;
+  p_resp_mcmember_rec->mtu |= 2<<6; /* exactly */
+  p_resp_mcmember_rec->rate &= 0x3f;
+  p_resp_mcmember_rec->rate |=  2<<6; /* exactly */
+  p_resp_mcmember_rec->pkt_life &= 0x3f;
+  p_resp_mcmember_rec->pkt_life |= 2<<6; /* exactly */
+
+  status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+
+  if(status != IB_SUCCESS)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_mcmr_rcv_respond: ERR 1B07: "
+             "Unable to send MAD (%s) for TID <0x%"PRIx64">\n",
+             ib_get_err_str( status ),
+             p_resp_sa_mad->trans_id );
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return;
+}
+
+/*********************************************************************
+In joining an existing group, or when querying the mc groups,
+we make sure the following components provided match: MTU and RATE
+HACK: Currently we ignore the PKT_LIFETIME field.
+**********************************************************************/
+static boolean_t
+__validate_more_comp_fields(
+  osm_log_t *p_log,
+  const osm_mgrp_t *p_mgrp,
+  const ib_member_rec_t *p_recvd_mcmember_rec,
+  ib_net64_t comp_mask)
+{
+  uint8_t mtu_sel;
+  uint8_t mtu_required;
+  uint8_t mtu_mgrp;
+  uint8_t rate_sel;
+  uint8_t rate_required;
+  uint8_t rate_mgrp;
+
+  if ( comp_mask & IB_MCR_COMPMASK_MTU_SEL)
+  {
+    mtu_sel = (uint8_t)(p_recvd_mcmember_rec->mtu >> 6);
+    /* Clearing last 2 bits */
+    mtu_required = (uint8_t)(p_recvd_mcmember_rec->mtu & 0x3F);
+    mtu_mgrp = (uint8_t)(p_mgrp->mcmember_rec.mtu & 0x3F);
+    switch (mtu_sel)
+    {
+    case 0: /* Greater than MTU specified */
+      if(mtu_mgrp <= mtu_required)
+      {
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__validate_more_comp_fields: "
+                 "Requested MTU %x is not greater than %x\n",
+                 mtu_mgrp, mtu_required );
+        return FALSE;
+      }
+      break;
+    case 1: /* Less than MTU specified */
+      if(mtu_mgrp >= mtu_required)
+      {
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__validate_more_comp_fields: "
+                 "Requested MTU %x is not less than %x\n",
+                 mtu_mgrp, mtu_required );
+        return FALSE;
+      }
+      break;
+    case 2: /* Exactly MTU specified */
+      if(mtu_mgrp != mtu_required)
+      {
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__validate_more_comp_fields: "
+                 "Requested MTU %x is not equal to %x\n",
+                 mtu_mgrp, mtu_required );
+        return FALSE;
+      }
+      break;
+    default:
+      break;
+    }
+  }
+
+  /* what about rate ? */
+  if ( comp_mask & IB_MCR_COMPMASK_RATE_SEL)
+  {
+    rate_sel = (uint8_t)(p_recvd_mcmember_rec->rate >> 6);
+    /* Clearing last 2 bits */
+    rate_required = (uint8_t)(p_recvd_mcmember_rec->rate & 0x3F);
+    rate_mgrp = (uint8_t)(p_mgrp->mcmember_rec.rate & 0x3F);
+    switch (rate_sel)
+    {
+    case 0: /* Greater than RATE specified */
+      if(rate_mgrp <= rate_required)
+      {
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__validate_more_comp_fields: "
+                 "Requested RATE %x is not greater than %x\n",
+                 rate_mgrp, rate_required );
+        return FALSE;
+      }
+      break;
+    case 1: /* Less than RATE specified */
+      if(rate_mgrp >= rate_required)
+      {
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__validate_more_comp_fields: "
+                 "Requested RATE %x is not less than %x\n",
+                 rate_mgrp, rate_required );
+        return FALSE;
+      }
+      break;
+    case 2: /* Exactly RATE specified */
+      if(rate_mgrp != rate_required)
+      {
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__validate_more_comp_fields: "
+                 "Requested RATE %x is not equal to %x\n",
+                 rate_mgrp, rate_required );
+        return FALSE;
+      }
+      break;
+    default:
+      break;
+    }
+  }
+
+  return TRUE;
+}
+
+/*********************************************************************
+In joining an existing group, we make sure the following components
+are physically realizable: MTU and RATE
+**********************************************************************/
+static boolean_t
+__validate_port_caps(
+  osm_log_t * const p_log,
+  const osm_mgrp_t *p_mgrp,
+  const osm_physp_t *p_physp)
+{
+  ib_port_info_t *p_pi;
+  uint8_t mtu_required;
+  uint8_t mtu_mgrp;
+  uint8_t rate_required;
+  uint8_t rate_mgrp;
+
+  p_pi = osm_physp_get_port_info_ptr(p_physp);
+  if (!p_pi)
+  {
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "__validate_port_caps: "
+             "Cannot get Port's 0x%016" PRIx64 " PortInfo\n",
+             cl_ntoh64( osm_physp_get_port_guid(p_physp) ) );
+    return FALSE;
+  }
+
+  mtu_required = ib_port_info_get_mtu_cap(p_pi);
+  mtu_mgrp = (uint8_t)(p_mgrp->mcmember_rec.mtu & 0x3F);
+  if (mtu_required < mtu_mgrp)
+  {
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "__validate_port_caps: "
+             "Port's MTU %x is less than %x\n",
+             mtu_required, mtu_mgrp );
+    return FALSE;
+  }
+
+  rate_required = ib_port_info_compute_rate(p_pi);
+  rate_mgrp = (uint8_t)(p_mgrp->mcmember_rec.rate & 0x3F);
+  if (rate_required < rate_mgrp)
+  {
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "__validate_port_caps: "
+             "Port's RATE %x is less than %x\n",
+             rate_required, rate_mgrp );
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**********************************************************************
+ * o15-0.2.1: If SA supports UD multicast, then if SA receives a SubnAdmSet()
+ * or SubnAdmDelete() method that would modify an existing
+ * MCMemberRecord, SA shall not modify that MCMemberRecord and shall
+ * return an error status of ERR_REQ_INVALID in response in the
+ * following cases:
+ * 1. Saved MCMemberRecord.ProxyJoin is not set and the request is
+ * issued by a requester with a GID other than the Port-GID.
+ * 2. Saved MCMemberRecord.ProxyJoin is set and the requester is not
+ * part of the partition for that MCMemberRecord.
+ **********************************************************************/
+static boolean_t
+__validate_modify(IN osm_mcmr_recv_t* const p_rcv,
+                  IN osm_mgrp_t* p_mgrp,
+                  IN osm_mad_addr_t* p_mad_addr,
+                  IN ib_member_rec_t* p_recvd_mcmember_rec,
+                  OUT osm_mcm_port_t **pp_mcm_port)
+{
+  ib_net64_t portguid;
+  ib_gid_t request_gid;
+  osm_physp_t* p_request_physp;
+  ib_api_status_t res;
+
+  portguid = p_recvd_mcmember_rec->port_gid.unicast.interface_id;
+
+  *pp_mcm_port = NULL;
+
+  /* o15-0.2.1: If this is a new port being added - nothing to check */
+  if (!osm_mgrp_is_port_present(p_mgrp, portguid, pp_mcm_port))
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__validate_modify: "
+             "This is a new port in the MC group\n" );
+    return TRUE;
+  }
+  /* We validate the request according the the proxy_join.
+     Check if the proxy_join is set or not */
+  if ( (*pp_mcm_port)->proxy_join == FALSE )
+  {
+    /* The proxy_join is not set. Modifying can by done only
+       if the requester GID == PortGID */
+    res = osm_get_gid_by_mad_addr(p_rcv->p_log,
+                                  p_rcv->p_subn,
+                                  p_mad_addr,
+                                  &request_gid);
+
+    if ( res != IB_SUCCESS )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+               "__validate_modify: "
+               "Could not find port for requested address\n"
+               );
+      return FALSE;
+    }
+
+    if (memcmp(&((*pp_mcm_port)->port_gid), &request_gid, sizeof(ib_gid_t)))
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+               "__validate_modify: "
+               "No ProxyJoin but different ports: stored:0x%016"PRIx64
+               " request:0x%016"PRIx64"\n",
+               cl_ntoh64((*pp_mcm_port)->port_gid.unicast.interface_id),
+               cl_ntoh64(p_mad_addr->addr_type.gsi.grh_info.src_gid.unicast.interface_id)
+               );
+      return FALSE;
+    }
+  }
+  else
+  {
+    /* the proxy_join is set. Modification allowed only if the
+       requester is part of the partition for this MCMemberRecord */
+    p_request_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+                                                p_rcv->p_subn,
+                                                p_mad_addr);
+    if (p_request_physp == NULL)
+      return FALSE;
+
+    if (!osm_physp_has_pkey(p_rcv->p_log, p_mgrp->mcmember_rec.pkey,
+                            p_request_physp))
+    {
+      /* the request port is not part of the partition for this mgrp */
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+               "__validate_modify: "
+               "ProxyJoin but port not in partition. stored:0x%016"PRIx64
+               " request:0x%016"PRIx64"\n",
+               cl_ntoh64((*pp_mcm_port)->port_gid.unicast.interface_id),
+               cl_ntoh64(p_mad_addr->addr_type.gsi.grh_info.src_gid.unicast.interface_id)
+               );
+      return FALSE;
+    }
+  }
+  return TRUE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ * Check legality of the requested MGID DELETE
+ * o15-0.1.14 = VALID DELETE:
+ * To be a valid delete MAD needs to:
+ * 1 the MADs PortGID and MGID components match the PortGID and
+ *   MGID of a stored MCMemberRecord;
+ * 2 the MADs JoinState component contains at least one bit set to 1
+ *   in the same position as that stored MCMemberRecords JoinState
+ *   has a bit set to 1,
+ *   i.e., the logical AND of the two JoinState components
+ *   is not all zeros;
+ * 3 the MADs JoinState component does not have some bits set
+ *   which are not set in the stored MCMemberRecords JoinState component;
+ * 4 either the stored MCMemberRecord:ProxyJoin is reset (0), and the
+ *   MADs source is the stored PortGID;
+ *   OR
+ *   the stored MCMemberRecord:ProxyJoin is set (1), (see o15-
+ *   0.1.2:); and the MADs source is a member of the partition indicated
+ *   by the stored MCMemberRecord:P_Key.
+ */
+static boolean_t
+__validate_delete(IN osm_mcmr_recv_t* const p_rcv,
+                  IN osm_mgrp_t *p_mgrp,
+                  IN osm_mad_addr_t* p_mad_addr,
+                  IN ib_member_rec_t* p_recvd_mcmember_rec,
+                  OUT osm_mcm_port_t **pp_mcm_port)
+{
+  ib_net64_t portguid;
+
+  portguid = p_recvd_mcmember_rec->port_gid.unicast.interface_id;
+
+  *pp_mcm_port = NULL;
+
+  /* 1 */
+  if (!osm_mgrp_is_port_present(p_mgrp, portguid, pp_mcm_port))
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__validate_delete: "
+             "Failed to find the port in the MC group\n" );
+    return FALSE;
+  }
+
+  /* 2 */
+  if (!(p_recvd_mcmember_rec->scope_state & 0x0F &
+        (*pp_mcm_port)->scope_state))
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__validate_delete: "
+             "Could not find any matching bits in the stored and requested JoinStates\n" );
+    return FALSE;
+  }
+
+  /* 3 */
+  if ( ((p_recvd_mcmember_rec->scope_state & 0x0F) |
+        (0x0F & (*pp_mcm_port)->scope_state)) !=
+       (0x0F & (*pp_mcm_port)->scope_state))
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__validate_delete: "
+             "Some bits in the request JoinState (0x%X) are not set in the stored port (0x%X)\n",
+             (p_recvd_mcmember_rec->scope_state & 0x0F),
+             (0x0F & (*pp_mcm_port)->scope_state)
+             );
+    return FALSE;
+  }
+
+  /* 4 */
+  /* Validate according the the proxy_join (o15-0.1.2) */
+  if ( __validate_modify( p_rcv, p_mgrp, p_mad_addr, p_recvd_mcmember_rec,
+                          pp_mcm_port ) == FALSE )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__validate_delete: "
+             "proxy_join validation failure\n" );
+    return FALSE;
+  }
+  return TRUE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ * Check legality of the requested MGID (note this does not hold for SA
+ * created MGIDs)
+ *
+ * Implementing o15-0.1.5:
+ * A multicast GID is considered to be invalid if:
+ * 1. It does not comply with the rules as specified in 4.1.1 "GID Usage and
+ *    Properties" on page 145:
+ *
+ * 14) The multicast GID format is (bytes are comma sep):
+ *     0xff,<Fl><Sc>,<Si>,<Si>,<P>,<P>,<P>,<P>,<P>,<P>,<P>,<P>,<Id>,<Id>,<Id>,<Id>
+ *     Fl  4bit = Flags (b)
+ *     Sc  4bit = Scope (c)
+ *     Si 16bit = Signature (2)
+ *     P  64bit = GID Prefix (should be a subnet unique ID - normally Subnet Prefix)
+ *     Id 32bit = Unique ID in the Subnet (might be MLID or Pkey ?)
+ *
+ *  a) 8-bits of 11111111 at the start of the GID identifies this as being a
+ *     multicast GID.
+ *  b) Flags is a set of four 1-bit flags: 000T with three flags reserved
+ *     and defined as zero (0). The T flag is defined as follows:
+ *     i) T = 0 indicates this is a permanently assigned (i.e. wellknown)
+ *        multicast GID. See RFC 2373 and RFC 2375 as reference
+ *        for these permanently assigned GIDs.
+ *     ii) T = 1 indicates this is a non-permanently assigned (i.e. transient)
+ *        multicast GID.
+ *  c) Scope is a 4-bit multicast scope value used to limit the scope of
+ *     the multicast group. The following table defines scope value and
+ *     interpretation.
+ *
+ *     Multicast Address Scope Values:
+ *     0x2 Link-local
+ *     0x5 Site-local
+ *     0x8 Organization-local
+ *     0xE Global
+ *
+ * 2. It contains the SA-specific signature of 0xA01B and has the link-local
+ *    scope bits set. (EZ: the idea here is that SA created MGIDs are the
+ *    only source for this signature with link-local scope)
+ */
+ib_api_status_t
+__validate_requested_mgid(IN osm_mcmr_recv_t* const p_rcv,
+                          IN const ib_member_rec_t* p_mcm_rec)
+{
+  uint16_t signature;
+  boolean_t valid = TRUE;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __validate_requested_mgid );
+
+  /* 14-a: mcast GID must start with 0xFF */
+  if (p_mcm_rec->mgid.multicast.header[0] != 0xFF)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__validate_requested_mgid: ERR 1B01: "
+             "Wrong MGID Prefix 0x%02X must be 0xFF\n",
+             cl_ntoh16(p_mcm_rec->mgid.multicast.header[0])
+             );
+    valid = FALSE;
+    goto Exit;
+  }
+
+  /* the MGID signature can mark IPoIB or SA assigned MGIDs */
+  memcpy(&signature, &(p_mcm_rec->mgid.multicast.raw_group_id), sizeof(signature));
+  signature = cl_ntoh16(signature);
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+           "__validate_requested_mgid:  "
+           "MGID Signed as 0x%04X\n",
+           signature
+           );
+
+  /*
+   * We skip any checks for MGIDs that follow IPoIB
+   * GID structure as defined by the IETF ipoib-link-multicast.
+   *
+   * For IPv4 over IB, the signature will be "0x401B".
+   *
+   * |   8    |  4 |  4 |     16 bits     | 16 bits | 48 bits  | 32 bits |
+   * +--------+----+----+-----------------+---------+----------+---------+
+   * |11111111|0001|scop|<IPoIB signature>|< P_Key >|00.......0|<all 1's>|
+   * +--------+----+----+-----------------+---------+----------+---------+
+   *
+   * For IPv6 over IB, the signature will be "0x601B".
+   *
+   * |   8    |  4 |  4 |     16 bits     | 16 bits |       80 bits      |
+   * +--------+----+----+-----------------+---------+--------------------+
+   * |11111111|0001|scop|<IPoIB signature>|< P_Key >|000.............0001|
+   * +--------+----+----+-----------------+---------+--------------------+
+   *
+   */
+  if (signature == 0x401B || signature == 0x601B)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__validate_requested_mgid:  "
+             "Skipping MGID Validation for IPoIB Signed (0x%04X) MGIDs\n",
+             signature
+             );
+    goto Exit;
+  }
+
+  /* 14-b: the 3 upper bits in the "flags" should be zero: */
+  if ( p_mcm_rec->mgid.multicast.header[1] & 0xE0 )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__validate_requested_mgid: ERR 1B28: "
+             "MGID uses Reserved Flags: flags=0x%X\n",
+             (p_mcm_rec->mgid.multicast.header[1] & 0xE0) >> 4
+             );
+    valid = FALSE;
+    goto Exit;
+  }
+
+  /* 2 - now what if the link local format 0xA01B is used -
+     the scope should not be link local */
+  if ( ( signature == 0xA01B ) &&
+       ((p_mcm_rec->mgid.multicast.header[1] & 0x0F) == MC_SCOPE_LINK_LOCAL) ) {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__validate_requested_mgid: ERR 1B24: "
+             "MGID uses 0xA01B signature but with link-local scope\n" );
+    valid = FALSE;
+    goto Exit;
+  }
+
+  /*
+   * For SA assigned MGIDs (signature 0xA01B):
+   * There is no real way to make sure the Unique MGID Prefix is really unique.
+   * If we could enforce using the Subnet Prefix for that purpose it would
+   * have been nice. But the spec does not require it.
+   */
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return (valid);
+}
+
+/**********************************************************************
+ Check if the requested new MC group parameters are realizable.
+ Also set the default MTU and Rate if not provided by the user.
+**********************************************************************/
+boolean_t
+__mgrp_request_is_realizable(
+  IN osm_mcmr_recv_t* const p_rcv,
+  IN ib_net64_t comp_mask,
+  IN ib_member_rec_t * p_mcm_rec,
+  IN const osm_physp_t* const p_physp)
+{
+  uint8_t mtu_sel = 2; /* exactly */
+  uint8_t mtu_required, mtu, port_mtu;
+  uint8_t rate_sel = 2; /* exactly */
+  uint8_t rate_required, rate, port_rate;
+  osm_log_t *p_log = p_rcv->p_log;
+  ib_port_info_t *p_pi = NULL;
+
+  OSM_LOG_ENTER( p_rcv->p_log,  __mgrp_request_is_realizable );
+
+  if (p_physp != NULL)
+     p_pi = osm_physp_get_port_info_ptr(p_physp);
+
+  /*
+   * End of o15-0.2.3 specifies:
+   * ....
+   * The entity may also supply the other components such as HopLimit, MTU,
+   * etc. during group creation time. If these components are not provided
+   * during group creation time, SA will provide them for the group. The values
+   * chosen are vendor-dependent and beyond the scope of the specification.
+   *
+   * so we might also need to assign RATE/MTU if they are not comp masked in.
+   */
+
+  port_mtu = p_pi ? ib_port_info_get_mtu_cap(p_pi) : 0;
+  if (!(comp_mask & IB_MCR_COMPMASK_MTU) ||
+                 !(comp_mask & IB_MCR_COMPMASK_MTU_SEL) ||
+                 (mtu_sel = (p_mcm_rec->mtu >> 6)) == 3)
+    mtu = port_mtu ? port_mtu : p_rcv->p_subn->min_ca_mtu;
+  else
+  {
+    mtu_required = (uint8_t)(p_mcm_rec->mtu & 0x3F);
+    mtu = mtu_required;
+    switch (mtu_sel)
+    {
+    case 0: /* Greater than MTU specified */
+      if (port_mtu && mtu_required >= port_mtu)
+      {
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__mgrp_request_is_realizable: "
+                 "Requested MTU %x >= the port\'s mtu:%x\n",
+                 mtu_required, port_mtu );
+        return FALSE;
+      }
+      /* we provide the largest MTU possible if we can */
+      if (port_mtu)
+       mtu = port_mtu;
+      else if (mtu_required < p_rcv->p_subn->min_ca_mtu)
+        mtu = p_rcv->p_subn->min_ca_mtu;
+      else
+        mtu++;
+      break;
+    case 1: /* Less than MTU specified */
+      /* use the smaller of the two:
+         a. one lower then the required
+         b. the mtu of the requesting port (if exists) */
+      if (port_mtu && mtu_required > port_mtu)
+        mtu = port_mtu;
+      else
+        mtu--;
+      break;
+    case 2: /* Exactly MTU specified */
+    default:
+      break;
+    }
+    /* make sure it still be in the range */
+    if (mtu < IB_MIN_MTU || mtu > IB_MAX_MTU)
+    {
+      osm_log( p_log, OSM_LOG_DEBUG,
+               "__mgrp_request_is_realizable: "
+               "Calculated MTU %x is out of range\n",
+               mtu );
+      return FALSE;
+    }
+  }
+  p_mcm_rec->mtu = (mtu_sel<<6) | mtu;
+
+  port_rate = p_pi ? ib_port_info_compute_rate(p_pi) : 0;
+  if (!(comp_mask & IB_MCR_COMPMASK_RATE) ||
+                 !(comp_mask & IB_MCR_COMPMASK_RATE_SEL) ||
+                 (rate_sel = (p_mcm_rec->rate >> 6)) == 3)
+    rate = port_rate ? port_rate : p_rcv->p_subn->min_ca_rate;
+  else
+  {
+    rate_required = (uint8_t)(p_mcm_rec->rate & 0x3F);
+    rate = rate_required;
+    switch (rate_sel)
+    {
+    case 0: /* Greater than RATE specified */
+      if (port_rate && rate_required >= port_rate)
+      {
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__mgrp_request_is_realizable: "
+                 "Requested RATE %x >= the port\'s rate:%x\n",
+                 rate_required, port_rate );
+        return FALSE;
+      }
+      /* we provide the largest RATE possible if we can */
+      if (port_rate)
+       rate = port_rate;
+      else if (rate_required < p_rcv->p_subn->min_ca_rate)
+        rate = p_rcv->p_subn->min_ca_rate;
+      else
+        rate++;
+      break;
+    case 1: /* Less than RATE specified */
+      /* use the smaller of the two:
+         a. one lower then the required
+         b. the rate of the requesting port (if exists) */
+      if (port_rate && rate_required > port_rate)
+        rate = port_rate;
+      else
+        rate--;
+      break;
+    case 2: /* Exactly RATE specified */
+    default:
+      break;
+    }
+    /* make sure it still is in the range */
+    if (rate < IB_MIN_RATE || rate > IB_MAX_RATE)
+    {
+      osm_log( p_log, OSM_LOG_DEBUG,
+               "__mgrp_request_is_realizable: "
+               "Calculated RATE %x is out of range\n",
+               rate );
+      return FALSE;
+    }
+  }
+  p_mcm_rec->rate = (rate_sel<<6) | rate;
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return TRUE;
+}
+  
+/**********************************************************************
+ Call this function to find or create a new mgrp.
+**********************************************************************/
+ib_api_status_t
+osm_mcmr_rcv_find_or_create_new_mgrp(
+  IN osm_mcmr_recv_t* const p_rcv,
+  IN ib_net64_t comp_mask,
+  IN ib_member_rec_t* const p_recvd_mcmember_rec,
+  OUT osm_mgrp_t **pp_mgrp)
+{
+  ib_api_status_t status;
+
+  status = __get_mgrp_by_mgid(p_rcv, p_recvd_mcmember_rec, pp_mgrp);
+  if (status == IB_SUCCESS)
+     return status;
+  return osm_mcmr_rcv_create_new_mgrp(p_rcv, comp_mask,
+                 p_recvd_mcmember_rec, NULL, pp_mgrp);
+}
+
+/**********************************************************************
+ Call this function to create a new mgrp.
+**********************************************************************/
+ib_api_status_t
+osm_mcmr_rcv_create_new_mgrp(
+  IN osm_mcmr_recv_t* const p_rcv,
+  IN ib_net64_t comp_mask,
+  IN const ib_member_rec_t* const p_recvd_mcmember_rec,
+  IN const osm_physp_t* const p_physp,
+  OUT osm_mgrp_t **pp_mgrp)
+{
+  ib_net16_t mlid;
+  uint8_t zero_mgid, valid;
+  uint8_t scope, i;
+  ib_gid_t *p_mgid;
+  osm_mgrp_t *p_prev_mgrp;
+  ib_api_status_t status = IB_SUCCESS;
+  ib_member_rec_t mcm_rec = *p_recvd_mcmember_rec; /* copy for modifications */
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_mcmr_rcv_create_new_mgrp );
+
+  /* but what if the given MGID was not 0 ? */
+  zero_mgid = 1;
+  for ( i = 0 ; i < sizeof(p_recvd_mcmember_rec->mgid); i++ )
+  {
+    if (p_recvd_mcmember_rec->mgid.raw[i] != 0)
+    {
+      zero_mgid = 0;
+      break;
+    }
+  }
+
+  /*
+    we allocate a new mlid number before we might use it
+    for MGID ...
+  */
+  mlid = __get_new_mlid(p_rcv, mcm_rec.mlid);
+  if ( mlid == 0 )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_mcmr_rcv_create_new_mgrp: ERR 1B19: "
+             "__get_new_mlid failed\n" );
+    status = IB_SA_MAD_STATUS_NO_RESOURCES;
+    goto Exit;
+  }
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+           "osm_mcmr_rcv_create_new_mgrp: "
+           "Obtained new mlid 0x%X\n", cl_ntoh16(mlid) );
+
+  /* we need to create the new MGID if it was not defined */
+  if (zero_mgid)
+  {
+    /* create a new MGID */
+
+    /* use the given scope state only if requested! */
+    if (comp_mask & IB_MCR_COMPMASK_SCOPE)
+    {
+      ib_member_get_scope_state(
+        p_recvd_mcmember_rec->scope_state, &scope, NULL);
+    }
+    else
+    {
+      /* to guarantee no collision with other subnets use local scope! */
+      scope = MC_SCOPE_LINK_LOCAL;
+    }
+
+    p_mgid = &(mcm_rec.mgid);
+    p_mgid->raw[0] = 0xFF;
+    p_mgid->raw[1] = 0x10 | scope;
+    p_mgid->raw[2] = 0xA0;
+    p_mgid->raw[3] = 0x1B;
+
+    /* HACK: use the SA port gid to make it globally unique */
+    memcpy((&p_mgid->raw[4]),
+           &p_rcv->p_subn->opt.subnet_prefix, sizeof(uint64_t));
+
+    /* HACK: how do we get a unique number - use the mlid twice */
+    memcpy(&p_mgid->raw[10], &mlid, sizeof(uint16_t));
+    memcpy(&p_mgid->raw[12], &mlid, sizeof(uint16_t));
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "osm_mcmr_rcv_create_new_mgrp: "
+             "Allocated new MGID:0x%016" PRIx64 " : "
+             "0x%016" PRIx64 "\n",
+             cl_ntoh64(p_mgid->unicast.prefix),
+             cl_ntoh64(p_mgid->unicast.interface_id) );
+  }
+  else
+  {
+    /* a specific MGID was requested so validate the resulting MGID */
+    valid = __validate_requested_mgid(p_rcv, &mcm_rec);
+    if (!valid)
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_mcmr_rcv_create_new_mgrp: ERR 1B22: "
+               "Invalid requested MGID\n" );
+      __free_mlid(p_rcv, mlid);
+      status = IB_SA_MAD_STATUS_REQ_INVALID;
+      goto Exit;
+    }
+  }
+
+  /* check the requested parameters are realizable */
+  if (__mgrp_request_is_realizable(p_rcv, comp_mask, &mcm_rec, p_physp) == FALSE)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_mcmr_rcv_create_new_mgrp: ERR 1B26: "
+             "Requested MGRP parameters are not realizable\n" );
+    __free_mlid(p_rcv, mlid);
+    status = IB_SA_MAD_STATUS_REQ_INVALID;
+    goto Exit;
+  }
+
+  /* create a new MC Group */
+  *pp_mgrp = osm_mgrp_new(mlid);
+  if (*pp_mgrp == NULL)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_mcmr_rcv_create_new_mgrp: ERR 1B08: "
+             "osm_mgrp_new failed\n" );
+    __free_mlid(p_rcv, mlid);
+    status =  IB_SA_MAD_STATUS_NO_RESOURCES;
+    goto Exit;
+  }
+
+  /* Initialize the mgrp */
+  (*pp_mgrp)->mcmember_rec = mcm_rec;
+  (*pp_mgrp)->mcmember_rec.mlid = mlid;
+
+  /* the mcmember_record should have mtu_sel, rate_sel, and pkt_lifetime_sel = 2 */
+  (*pp_mgrp)->mcmember_rec.mtu &= 0x3f;
+  (*pp_mgrp)->mcmember_rec.mtu |= 2<<6; /* exactly */
+  (*pp_mgrp)->mcmember_rec.rate &= 0x3f;
+  (*pp_mgrp)->mcmember_rec.rate |= 2<<6; /* exactly */
+  (*pp_mgrp)->mcmember_rec.pkt_life &= 0x3f;
+  (*pp_mgrp)->mcmember_rec.pkt_life |= 2<<6; /* exactly */
+
+  /* Insert the new group in the data base */
+  
+  /* since we might have an old group by that mlid
+     one whose deletion was delayed for an idle time
+     we need to deallocate it first */
+  p_prev_mgrp = (osm_mgrp_t *)cl_qmap_get(&p_rcv->p_subn->mgrp_mlid_tbl, mlid);
+  if (p_prev_mgrp != (osm_mgrp_t *)cl_qmap_end(&p_rcv->p_subn->mgrp_mlid_tbl))
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "osm_mcmr_rcv_create_new_mgrp: "
+             "Found previous group for mlid:0x%04x - Need to destroy it\n",
+             cl_ntoh16(mlid) );
+    cl_qmap_remove_item(&p_rcv->p_subn->mgrp_mlid_tbl,
+                        (cl_map_item_t *)p_prev_mgrp );
+    osm_mgrp_destroy( p_prev_mgrp );
+  }
+
+  cl_qmap_insert(&p_rcv->p_subn->mgrp_mlid_tbl,
+                 mlid,
+                 &(*pp_mgrp)->map_item);
+
+  /* Send a Report to any InformInfo registerd for
+     Trap 66: MCGroup create */
+  osm_mgrp_send_create_notice(p_rcv->p_subn, p_rcv->p_log, *pp_mgrp);
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return status;
+
+}
+
+/*********************************************************************
+Process a request for leaving the group
+**********************************************************************/
+static void
+__osm_mcmr_rcv_leave_mgrp(
+  IN osm_mcmr_recv_t* const p_rcv,
+  IN const osm_madw_t* const p_madw )
+{
+  boolean_t valid;
+  osm_mgrp_t *p_mgrp;
+  ib_api_status_t status;
+  ib_sa_mad_t *p_sa_mad;
+  ib_member_rec_t*p_recvd_mcmember_rec;
+  ib_member_rec_t mcmember_rec;
+  ib_net16_t mlid;
+  ib_net16_t sa_status;
+  ib_net64_t portguid;
+  osm_mcm_port_t *p_mcm_port;
+  uint8_t port_join_state;
+  uint8_t new_join_state;
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_mcmr_rcv_leave_mgrp );
+
+  p_mgrp = NULL;
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_recvd_mcmember_rec =
+    (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+  mcmember_rec = *p_recvd_mcmember_rec;
+
+  if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_mcmr_rcv_leave_mgrp: Dump of record\n" );
+    osm_dump_mc_record( p_rcv->p_log, &mcmember_rec, OSM_LOG_DEBUG );
+  }
+
+  CL_PLOCK_EXCL_ACQUIRE(p_rcv->p_lock);
+  status = __get_mgrp_by_mgid(p_rcv,p_recvd_mcmember_rec, &p_mgrp);
+  if (status == IB_SUCCESS)
+  {
+    mlid = p_mgrp->mlid;
+    portguid = p_recvd_mcmember_rec->port_gid.unicast.interface_id;
+
+    /* check validity of the delete request o15-0.1.14 */
+    valid =  __validate_delete(p_rcv,
+                               p_mgrp,
+                               osm_madw_get_mad_addr_ptr(p_madw),
+                               p_recvd_mcmember_rec,
+                               &p_mcm_port);
+
+    if (valid)
+    {
+      /*
+       * according to the same o15-0.1.14 we get the stored JoinState and the
+       * request JoinState and they must be opposite to leave -
+       * otherwise just update it
+       */
+      port_join_state = p_mcm_port->scope_state & 0x0F;
+      new_join_state =
+        port_join_state & ~(p_recvd_mcmember_rec->scope_state & 0x0F);
+      if (new_join_state)
+      {
+        /* Just update the result JoinState */
+        p_mcm_port->scope_state =
+          new_join_state | (p_mcm_port->scope_state & 0xf0);
+
+        mcmember_rec.scope_state = p_mcm_port->scope_state;
+
+        CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+        osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+                 "__osm_mcmr_rcv_leave_mgrp: "
+                 "After update JoinState != 0. Updating from 0x%X to 0x%X\n",
+                 port_join_state,
+                 new_join_state
+                 );
+      }
+      else
+      {
+        /* we need to return the stored scope state */
+        mcmember_rec.scope_state = p_mcm_port->scope_state;
+
+        /* OK we can leave */
+       /* note: osm_sm_mcgrp_leave() will release p_rcv->p_lock */
+
+        status = osm_sm_mcgrp_leave(p_rcv->p_sm, mlid, portguid);
+        if(status != IB_SUCCESS)
+        {
+          osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                   "__osm_mcmr_rcv_leave_mgrp: ERR 1B09: "
+                   "osm_sm_mcgrp_leave failed\n" );
+        }
+      }
+    }
+    else
+    {
+      CL_PLOCK_RELEASE( p_rcv->p_lock );
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_mcmr_rcv_leave_mgrp: ERR 1B25: "
+               "Received an invalid delete request for "
+               "MGID: 0x%016" PRIx64 " : "
+               "0x%016" PRIx64 " for "
+               "PortGID: 0x%016" PRIx64 " : "
+               "0x%016" PRIx64 "\n",
+               cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.prefix ),
+               cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.interface_id ),
+               cl_ntoh64( p_recvd_mcmember_rec->port_gid.unicast.prefix ),
+               cl_ntoh64( p_recvd_mcmember_rec->port_gid.unicast.interface_id ) );
+      sa_status   = IB_SA_MAD_STATUS_REQ_INVALID;
+      osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+      goto Exit;
+    }
+  }
+  else
+  {
+    CL_PLOCK_RELEASE( p_rcv->p_lock );
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_mcmr_rcv_leave_mgrp: "
+             "Failed since multicast group not present\n" );
+    sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+    osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+    goto Exit;
+  }
+
+  /* Send an SA response */
+  __osm_mcmr_rcv_respond( p_rcv, p_madw, &mcmember_rec );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return;
+}
+
+/**********************************************************************
+ Handle a join (or create) request
+**********************************************************************/
+static void
+__osm_mcmr_rcv_join_mgrp(
+  IN osm_mcmr_recv_t* const p_rcv,
+  IN const osm_madw_t* const p_madw )
+{
+  boolean_t valid;
+  osm_mgrp_t *p_mgrp = NULL;
+  ib_api_status_t status;
+  ib_sa_mad_t *p_sa_mad;
+  ib_member_rec_t*p_recvd_mcmember_rec;
+  ib_member_rec_t mcmember_rec;
+  ib_net16_t sa_status;
+  ib_net16_t mlid;
+  osm_mcm_port_t *p_mcmr_port;
+  ib_net64_t portguid;
+  osm_port_t * p_port;
+  osm_physp_t* p_physp;
+  osm_physp_t* p_request_physp;
+  uint8_t is_new_group; /*  TRUE = there is a need to create a group */
+  osm_mcast_req_type_t req_type;
+  uint8_t join_state;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_mcmr_rcv_join_mgrp );
+
+  p_mgrp = NULL;
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_recvd_mcmember_rec =
+    (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+  portguid = p_recvd_mcmember_rec->port_gid.unicast.interface_id;
+
+  mcmember_rec = *p_recvd_mcmember_rec;
+
+  if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_mcmr_rcv_join_mgrp: "
+             "Dump of incoming record\n" );
+    osm_dump_mc_record( p_rcv->p_log, &mcmember_rec, OSM_LOG_DEBUG );
+  }
+
+  CL_PLOCK_EXCL_ACQUIRE(p_rcv->p_lock);
+
+  /* make sure the requested port guid is known to the SM */
+  p_port = (osm_port_t *)cl_qmap_get(&p_rcv->p_subn->port_guid_tbl,
+                                     portguid);
+
+  if (p_port == (osm_port_t *)cl_qmap_end(&p_rcv->p_subn->port_guid_tbl))
+  {
+    CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_mcmr_rcv_join_mgrp: "
+             "Unknown port GUID 0x%016" PRIx64 "\n",
+             portguid );
+    sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+    osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+    goto Exit;
+  }
+
+  p_physp = osm_port_get_default_phys_ptr(p_port);
+  /* Check that the p_physp and the requester physp are in the same
+     partition. */
+  p_request_physp =
+    osm_get_physp_by_mad_addr(p_rcv->p_log,
+                              p_rcv->p_subn,
+                              osm_madw_get_mad_addr_ptr(p_madw) );
+  if (p_request_physp == NULL)
+  {
+    CL_PLOCK_RELEASE( p_rcv->p_lock );
+    goto Exit;
+  }
+
+  if (!osm_physp_share_pkey( p_rcv->p_log, p_physp, p_request_physp))
+  {
+    CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_mcmr_rcv_join_mgrp: "
+             "Port and requester don't share pkey\n" );
+    sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+    osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+    goto Exit;
+  }
+  ib_member_get_scope_state(
+    p_recvd_mcmember_rec->scope_state, NULL, &join_state);
+
+  /* do we need to create a new group? */
+  status = __get_mgrp_by_mgid(p_rcv, p_recvd_mcmember_rec, &p_mgrp);
+  if ((status == IB_NOT_FOUND) || p_mgrp->to_be_deleted)
+  {
+    /* check for JoinState.FullMember = 1 o15.0.1.9 */
+    if ((join_state & 0x01) != 0x01)
+    {
+      CL_PLOCK_RELEASE( p_rcv->p_lock );
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_mcmr_rcv_join_mgrp: ERR 1B10: "
+               "Provided Join State != FullMember - required for create, "
+               "MGID: 0x%016" PRIx64 " : "
+               "0x%016" PRIx64 "\n",
+               cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.prefix ),
+               cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.interface_id ) );
+      sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+      osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+      goto Exit;
+    }
+
+    /* check for the comp_mask */
+    valid = __check_create_comp_mask(p_sa_mad->comp_mask,
+                                     p_recvd_mcmember_rec);
+    if (valid)
+    {
+      status = osm_mcmr_rcv_create_new_mgrp(p_rcv,
+                                            p_sa_mad->comp_mask,
+                                            p_recvd_mcmember_rec,
+                                            p_physp,
+                                            &p_mgrp);
+      if (status != IB_SUCCESS)
+      {
+        CL_PLOCK_RELEASE( p_rcv->p_lock );
+        sa_status = status;
+        osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+        goto Exit;
+      }
+      /* copy the MGID to the result */
+      mcmember_rec.mgid = p_mgrp->mcmember_rec.mgid;
+    }
+    else
+    {
+      CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_mcmr_rcv_join_mgrp: ERR 1B11: "
+               "method = %s, "
+               "scope_state = 0x%x, "
+               "component mask = 0x%016" PRIx64 ", "
+               "expected comp mask = 0x%016" PRIx64 ", "
+               "MGID: 0x%016" PRIx64 " : "
+               "0x%016" PRIx64 " from port 0x%016" PRIx64 "\n",
+               ib_get_sa_method_str(p_sa_mad->method),
+               p_recvd_mcmember_rec->scope_state,
+               cl_ntoh64(p_sa_mad->comp_mask),
+               CL_NTOH64(REQUIRED_MC_CREATE_COMP_MASK),
+               cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.prefix ),
+               cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.interface_id ),
+               cl_ntoh64( portguid ) );
+
+      sa_status = IB_SA_MAD_STATUS_INSUF_COMPS;
+      osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+      goto Exit;
+    }
+    is_new_group = 1;
+    req_type = OSM_MCAST_REQ_TYPE_CREATE;
+  }
+  else
+  {
+    /* no need for a new group */
+    is_new_group = 0;
+    req_type = OSM_MCAST_REQ_TYPE_JOIN;
+  }
+
+  CL_ASSERT(p_mgrp);
+  mlid = p_mgrp->mlid;
+
+  /*
+   * o15-0.2.4: If SA supports UD multicast, then SA shall cause an
+   * endport to join an existing multicast group if:
+   * 1. It receives a SubnAdmSet() method for a MCMemberRecord, and
+   *    - WE KNOW THAT ALREADY
+   * 2. The MGID is specified and matches an existing multicast
+   *    group, and
+   *    - WE KNOW THAT ALREADY
+   * 3. The MCMemberRecord:JoinState is not all 0s, and
+   * 4. PortGID is specified and
+   *    - WE KNOW THAT ALREADY (as it matched a real one)
+   * 5. All other components match that existing group, either by
+   *    being wildcarded or by having values identical to those specified
+   *    by the component mask and in use by the group with the exception
+   *    of components such as ProxyJoin and Reserved, which are ignored
+   *    by SA.
+   *
+   * We need to check #3 and #5 here:
+   */
+  valid = __validate_more_comp_fields(
+    p_rcv->p_log,
+    p_mgrp,
+    p_recvd_mcmember_rec,
+    p_sa_mad->comp_mask) && __validate_port_caps(
+    p_rcv->p_log,
+    p_mgrp,
+    p_physp) && (join_state != 0);
+  if (!valid)
+  {
+    /* since we might have created the new group we need to cleanup */
+    __cleanup_mgrp(p_rcv, mlid);
+
+    CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_mcmr_rcv_join_mgrp: ERR 1B12: "
+             "__validate_more_comp_fields, __validate_port_caps, "
+             "or JoinState = 0 failed from port 0x%016" PRIx64 ", "
+             "sending IB_SA_MAD_STATUS_REQ_INVALID\n",
+             cl_ntoh64( portguid ) );
+
+    sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+    osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+    goto Exit;
+  }
+
+  /*
+   * Do some validation of the modification
+   */
+  if (!is_new_group)
+  {
+    /*
+     * o15-0.2.1 requires validation of the requesting port
+     * in the case of modification:
+     */
+    valid = __validate_modify(p_rcv,
+                              p_mgrp,
+                              osm_madw_get_mad_addr_ptr(p_madw),
+                              p_recvd_mcmember_rec,
+                              &p_mcmr_port);
+    if (!valid)
+    {
+      CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_mcmr_rcv_join_mgrp: ERR 1B13: "
+               "__validate_modify failed, "
+               "sending IB_SA_MAD_STATUS_REQ_INVALID\n" );
+
+      sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+      osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+      goto Exit;
+    }
+  }
+
+  /* create or update existing port (join-state will be updated) */
+  status = __add_new_mgrp_port(
+    p_rcv,
+    p_mgrp,
+    p_recvd_mcmember_rec,
+    osm_madw_get_mad_addr_ptr(p_madw),
+    &p_mcmr_port);
+
+  if (status != IB_SUCCESS)
+  {
+    /* we fail to add the port so we might need to delete the group */
+    __cleanup_mgrp(p_rcv, mlid);
+
+    CL_PLOCK_RELEASE( p_rcv->p_lock );
+    if (status == IB_INVALID_PARAMETER) 
+      sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+    else
+      sa_status = IB_SA_MAD_STATUS_NO_RESOURCES;
+
+    osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+    goto Exit;
+  }
+
+  /* o15.0.1.11: copy the join state */
+  mcmember_rec.scope_state = p_mcmr_port->scope_state;
+
+  /* copy qkey mlid tclass pkey sl_flow_hop mtu rate pkt_life sl_flow_hop */
+  __copy_from_create_mc_rec(&mcmember_rec, &p_mgrp->mcmember_rec);
+
+  /* Release the lock as we don't need it. */
+  CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+  /* do the actual routing (actually schedule the update) */
+  status =
+    osm_sm_mcgrp_join(p_rcv->p_sm,
+                      mlid,
+                      p_recvd_mcmember_rec->port_gid.unicast.interface_id,
+                      req_type);
+
+  if (status != IB_SUCCESS)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_mcmr_rcv_join_mgrp: ERR 1B14: "
+             "osm_sm_mcgrp_join failed, "
+             "sending IB_SA_MAD_STATUS_NO_RESOURCES\n" );
+
+    CL_PLOCK_EXCL_ACQUIRE(p_rcv->p_lock);
+
+    /* the request for routing failed so we need to remove the port */
+    p_mgrp = __get_mgrp_by_mlid(p_rcv, mlid);
+    if (p_mgrp != NULL)
+    {
+      osm_mgrp_remove_port(
+        p_rcv->p_subn,
+        p_rcv->p_log,
+        p_mgrp,
+        p_recvd_mcmember_rec->port_gid.unicast.interface_id);
+      __cleanup_mgrp(p_rcv, mlid);
+    }
+    CL_PLOCK_RELEASE( p_rcv->p_lock );
+    sa_status = IB_SA_MAD_STATUS_NO_RESOURCES;
+    osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+    goto Exit;
+
+  } /* failed to route */
+
+  if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+    osm_dump_mc_record( p_rcv->p_log, &mcmember_rec, OSM_LOG_DEBUG );
+
+  __osm_mcmr_rcv_respond( p_rcv, p_madw, &mcmember_rec );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return;
+}
+
+/**********************************************************************
+ Add a patched multicast group to the results list
+**********************************************************************/
+static ib_api_status_t
+__osm_mcmr_rcv_new_mcmr(
+  IN osm_mcmr_recv_t*         const p_rcv,
+  IN const ib_member_rec_t*   p_rcvd_rec,
+  IN cl_qlist_t*              const p_list )
+{
+  osm_mcmr_item_t*            p_rec_item;
+  ib_api_status_t             status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_mcmr_rcv_new_mcmr );
+
+  p_rec_item = (osm_mcmr_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+  if( p_rec_item == NULL )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_mcmr_rcv_new_mcmr: ERR 1B15: "
+             "cl_qlock_pool_get failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+  memset( &p_rec_item->rec, 0, sizeof( p_rec_item->rec ) );
+
+  /* HACK: Not trusted requesters should result with 0 Join
+     State, Port Guid, and Proxy */
+  p_rec_item->rec = *p_rcvd_rec;
+  cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ Match the given mgrp to the requested mcmr
+**********************************************************************/
+void
+__osm_sa_mcm_by_comp_mask_cb(
+  IN cl_map_item_t*           const p_map_item,
+  IN void*                    context )
+{
+  const osm_mgrp_t *          const p_mgrp = (osm_mgrp_t *)p_map_item;
+  osm_sa_mcmr_search_ctxt_t*  const p_ctxt =
+    (osm_sa_mcmr_search_ctxt_t *)context;
+  osm_mcmr_recv_t*            const p_rcv  = p_ctxt->p_rcv;
+  const ib_member_rec_t*      p_rcvd_rec   = p_ctxt->p_mcmember_rec;
+  const osm_physp_t*          p_req_physp  = p_ctxt->p_req_physp;
+
+  /* since we might change scope_state */
+  ib_member_rec_t             match_rec;
+  ib_net64_t                  comp_mask    = p_ctxt->comp_mask;
+  osm_mcm_port_t*             p_mcm_port;
+  ib_net64_t portguid = p_rcvd_rec->port_gid.unicast.interface_id;
+  /* will be used for group or port info */
+  uint8_t scope_state; 
+  uint8_t scope_state_mask = 0;
+  cl_map_item_t *p_item;
+  ib_gid_t     port_gid;
+  boolean_t proxy_join;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_mcm_by_comp_mask_cb );
+
+  osm_log(p_rcv->p_log, OSM_LOG_DEBUG,
+          "__osm_sa_mcm_by_comp_mask_cb: "
+          "Checking mlid:0x%X\n",
+          cl_ntoh16(p_mgrp->mlid));
+
+  /* the group might be marked for deletion */
+  if (p_mgrp->to_be_deleted)
+  {
+    osm_log(p_rcv->p_log, OSM_LOG_DEBUG,
+            "__osm_sa_mcm_by_comp_mask_cb: "
+            "Group mlid:0x%X is marked to be deleted\n",
+            cl_ntoh16(p_mgrp->mlid));
+    goto Exit;
+  }
+
+  /* first try to eliminate the group by MGID, MLID, or P_Key */
+  if ((IB_MCR_COMPMASK_MGID & comp_mask) &&
+      memcmp(&p_rcvd_rec->mgid, &p_mgrp->mcmember_rec.mgid, sizeof(ib_gid_t)))
+    goto Exit;
+
+  if ((IB_MCR_COMPMASK_MLID & comp_mask) &&
+      memcmp(&p_rcvd_rec->mlid, &p_mgrp->mcmember_rec.mlid, sizeof(uint16_t)))
+    goto Exit;
+
+  /* if the requester physical port doesn't have the pkey that is defined for
+     the group - exit. */
+  if (!osm_physp_has_pkey( p_rcv->p_log, p_mgrp->mcmember_rec.pkey,
+                           p_req_physp ))
+    goto Exit;
+
+  /* now do the rest of the match */
+  if ((IB_MCR_COMPMASK_QKEY & comp_mask) &&
+      (p_rcvd_rec->qkey != p_mgrp->mcmember_rec.qkey))
+    goto Exit;
+
+  if ((IB_MCR_COMPMASK_PKEY & comp_mask) &&
+      (p_rcvd_rec->pkey != p_mgrp->mcmember_rec.pkey))
+    goto Exit;
+
+  if ((IB_MCR_COMPMASK_TCLASS & comp_mask) &&
+      (p_rcvd_rec->tclass != p_mgrp->mcmember_rec.tclass))
+    goto Exit;
+  /* check SL, Flow, and Hop limit */
+  {
+    uint8_t mgrp_sl, query_sl;
+    uint32_t mgrp_flow, query_flow;
+    uint8_t mgrp_hop, query_hop;
+
+    ib_member_get_sl_flow_hop(p_rcvd_rec->sl_flow_hop,
+                              &query_sl, &query_flow, &query_hop);
+
+    ib_member_get_sl_flow_hop(p_mgrp->mcmember_rec.sl_flow_hop,
+                              &mgrp_sl, &mgrp_flow, &mgrp_hop);
+
+    if (IB_MCR_COMPMASK_SL & comp_mask )
+      if (query_sl != mgrp_sl)
+        goto Exit;
+
+    if (IB_MCR_COMPMASK_FLOW & comp_mask)
+      if (query_flow != mgrp_flow)
+        goto Exit;
+
+    if (IB_MCR_COMPMASK_HOP & comp_mask)
+      if (query_hop != mgrp_hop)
+        goto Exit;
+  }
+
+  if ((IB_MCR_COMPMASK_PROXY & comp_mask) &&
+      (p_rcvd_rec->proxy_join != p_mgrp->mcmember_rec.proxy_join))
+    goto Exit;
+
+  if (IB_MCR_COMPMASK_SCOPE & comp_mask)
+    scope_state_mask = 0xF0;
+
+  if (IB_MCR_COMPMASK_JOIN_STATE & comp_mask)
+    scope_state_mask = scope_state_mask | 0x0F;
+
+  /* need to validate mtu, rate, and pkt_lifetime fields. */
+  if (__validate_more_comp_fields( p_rcv->p_log,
+                                   p_mgrp,
+                                   p_rcvd_rec,
+                                   comp_mask ) == FALSE)
+    goto Exit;
+
+  /* Port specific fields */
+  /* so did we get the PortGUID mask */
+  if (IB_MCR_COMPMASK_PORT_GID & comp_mask)
+  {
+     /* try to find this port */
+     if (osm_mgrp_is_port_present(p_mgrp, portguid, &p_mcm_port))
+     {
+       scope_state = p_mcm_port->scope_state;
+       memcpy(&port_gid, &(p_mcm_port->port_gid), sizeof(ib_gid_t));
+       proxy_join = p_mcm_port->proxy_join;
+     }
+     else
+     {
+       /* port not in group */
+       goto Exit;
+     }
+  }
+  else
+  {
+     /* point to the group information */
+     scope_state = p_mgrp->mcmember_rec.scope_state;
+  }
+
+  /* Many MC records returned */
+  if ( (p_ctxt->trusted_req == TRUE) && !(IB_MCR_COMPMASK_PORT_GID & comp_mask) )
+  {
+     osm_log(p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_sa_mcm_by_comp_mask_cb: "
+             "Trusted req is TRUE and no specific port defined\n");
+
+     /* return all the ports that match in this MC group */
+     p_item = cl_qmap_head(&(p_mgrp->mcm_port_tbl));
+     while( p_item != cl_qmap_end(&(p_mgrp->mcm_port_tbl)) )
+     {
+        p_mcm_port=(osm_mcm_port_t *)p_item;
+
+        if ((scope_state_mask & p_rcvd_rec->scope_state) ==
+            (scope_state_mask & p_mcm_port->scope_state)) 
+       {
+           /* add to the list */
+           match_rec = p_mgrp->mcmember_rec;
+           match_rec.scope_state = p_mcm_port->scope_state;
+           memcpy( &(match_rec.port_gid), &(p_mcm_port->port_gid),
+                      sizeof(ib_gid_t));
+           osm_log(p_rcv->p_log, OSM_LOG_DEBUG,
+                   "__osm_sa_mcm_by_comp_mask_cb: "
+                   "Record of port_gid: 0x%016" PRIx64 "0x%016" PRIx64 
+                   " in multicast_lid: 0x%X is returned\n",
+                   cl_ntoh64(match_rec.port_gid.unicast.prefix),
+                   cl_ntoh64(match_rec.port_gid.unicast.interface_id),
+                   cl_ntoh16(p_mgrp->mlid)
+                   );
+
+           match_rec.proxy_join = (uint8_t)(p_mcm_port->proxy_join);
+
+           __osm_mcmr_rcv_new_mcmr(p_rcv, &match_rec, p_ctxt->p_list);
+         }
+         p_item = cl_qmap_next(p_item);
+      }
+  }
+  /* One MC record returned */
+  else
+  {
+    if ((scope_state_mask & p_rcvd_rec->scope_state) !=
+        (scope_state_mask & scope_state))
+      goto Exit;
+
+    /* add to the list */
+    match_rec = p_mgrp->mcmember_rec;
+    match_rec.scope_state = scope_state;
+    memcpy(&(match_rec.port_gid), &port_gid, sizeof(ib_gid_t));
+    match_rec.proxy_join = (uint8_t)proxy_join;
+
+    __osm_mcmr_rcv_new_mcmr(p_rcv, &match_rec, p_ctxt->p_list);
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ Handle a query request
+**********************************************************************/
+static void
+__osm_mcmr_query_mgrp(IN osm_mcmr_recv_t*  const p_rcv,
+                      IN const osm_madw_t* const p_madw)
+{
+  const ib_sa_mad_t*       p_rcvd_mad;
+  const ib_member_rec_t*   p_rcvd_rec;
+  cl_qlist_t               rec_list;
+  osm_madw_t*              p_resp_madw;
+  ib_sa_mad_t*             p_resp_sa_mad;
+  ib_member_rec_t*         p_resp_rec;
+  uint32_t                 num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  uint32_t                 trim_num_rec;
+#endif
+  uint32_t                 i;
+  osm_sa_mcmr_search_ctxt_t   context;
+  osm_mcmr_item_t*         p_rec_item;
+  ib_api_status_t          status;
+  ib_net64_t               comp_mask;
+  osm_physp_t*             p_req_physp;
+  boolean_t                trusted_req;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_mcmr_query_mgrp );
+
+  p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_rcvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+  comp_mask = p_rcvd_mad->comp_mask;
+
+  /*
+    if sm_key is not zero and does not match we never get here
+    see main SA receiver
+   */
+  trusted_req = (p_rcvd_mad->sm_key != 0);
+
+  /* update the requester physical port. */
+  p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+                                          p_rcv->p_subn,
+                                          osm_madw_get_mad_addr_ptr(p_madw) );
+  if (p_req_physp == NULL)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_mcmr_query_mgrp: ERR 1B04: "
+             "Cannot find requester physical port\n" );
+    goto Exit;
+  }
+
+  cl_qlist_init( &rec_list );
+
+  context.p_mcmember_rec = p_rcvd_rec;
+  context.p_list = &rec_list;
+  context.comp_mask = p_rcvd_mad->comp_mask;
+  context.p_rcv = p_rcv;
+  context.p_req_physp = p_req_physp;
+  context.trusted_req = trusted_req;
+
+  CL_PLOCK_ACQUIRE( p_rcv->p_lock );
+
+  /* simply go over all MCGs and match */
+  cl_qmap_apply_func( &p_rcv->p_subn->mgrp_mlid_tbl,
+                      __osm_sa_mcm_by_comp_mask_cb,
+                      &context);
+
+  CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+  num_rec = cl_qlist_count( &rec_list );
+
+  /*
+   * C15-0.1.30:
+   * If we do a SubnAdmGet and got more than one record it is an error !
+   */
+  if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) &&
+       (num_rec > 1)) {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_mcmr_query_mgrp: ERR 1B05: "
+             "Got more than one record for SubnAdmGet (%u)\n",
+             num_rec );
+    osm_sa_send_error( p_rcv->p_resp, p_madw,
+                       IB_SA_MAD_STATUS_TOO_MANY_RECORDS );
+
+    /* need to set the mem free ... */
+    p_rec_item = (osm_mcmr_item_t*)cl_qlist_remove_head( &rec_list );
+    while( p_rec_item != (osm_mcmr_item_t*)cl_qlist_end( &rec_list ) )
+    {
+      cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+      p_rec_item = (osm_mcmr_item_t*)cl_qlist_remove_head( &rec_list );
+    }
+
+    goto Exit;
+  }
+
+  pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_member_rec_t);
+  if (trim_num_rec < num_rec)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "__osm_mcmr_query_mgrp: "
+             "Number of records:%u trimmed to:%u to fit in one MAD\n",
+             num_rec, trim_num_rec );
+    num_rec = trim_num_rec;
+  }
+#endif
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+           "__osm_mcmr_query_mgrp: "
+           "Returning %u records\n", num_rec );
+
+  if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+  {
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+    goto Exit;
+  }
+
+  /*
+   * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+   */
+  p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+                                  p_madw->h_bind,
+                                  num_rec * sizeof(ib_member_rec_t) + IB_SA_MAD_HDR_SIZE,
+                                  osm_madw_get_mad_addr_ptr(p_madw) );
+
+  if( !p_resp_madw )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_mcmr_query_mgrp: ERR 1B16: "
+             "osm_mad_pool_get failed\n" );
+
+    for( i = 0; i < num_rec; i++ )
+    {
+      p_rec_item = (osm_mcmr_item_t*)cl_qlist_remove_head( &rec_list );
+      cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    }
+
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES );
+    goto Exit;
+  }
+
+  p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+  /*
+    Copy the MAD header back into the response mad.
+    Set the 'R' bit and the payload length,
+    Then copy all records from the list into the response payload.
+  */
+
+  memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+  /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
+  p_resp_sa_mad->sm_key = 0;
+
+  /* Fill in the offset (paylen will be done by the rmpp SAR) */
+  p_resp_sa_mad->attr_offset =
+    ib_get_attr_offset( sizeof(ib_member_rec_t) );
+
+#ifndef VENDOR_RMPP_SUPPORT
+  /* we support only one packet RMPP - so we will set the first and
+     last flags for gettable */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+  {
+    p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+  }
+#else
+  /* forcefully define the packet as RMPP one */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+  p_resp_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+  /*
+    p923 - The PortGID, JoinState and ProxyJoin shall be zero,
+    except in the case of a trusted request.
+    Note: In the mad controller we check that the SM_Key received on
+    the mad is valid. Meaning - is either zero or equal to the local
+    sm_key.
+  */
+
+  for ( i = 0; i < pre_trim_num_rec; i++ )
+  {
+    p_rec_item = (osm_mcmr_item_t*)cl_qlist_remove_head( &rec_list );
+    /* copy only if not trimmed */
+    if (i < num_rec)
+    {
+      *p_resp_rec = p_rec_item->rec;
+      if (trusted_req == FALSE)
+      {
+        memset(&p_resp_rec->port_gid, 0, sizeof(ib_gid_t));
+        ib_member_set_join_state(p_resp_rec, 0);
+        p_resp_rec->proxy_join = 0;
+      }
+    }
+    cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    p_resp_rec++;
+  }
+
+  CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+  status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+  if(status != IB_SUCCESS)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_mcmr_query_mgrp: ERR 1B17: "
+             "osm_vendor_send status = %s\n",
+             ib_get_err_str(status) );
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcmr_rcv_process(
+  IN osm_mcmr_recv_t* const p_rcv,
+  const IN osm_madw_t* const p_madw )
+{
+  ib_sa_mad_t *p_sa_mad;
+  ib_net16_t sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+  ib_member_rec_t *p_recvd_mcmember_rec;
+  boolean_t valid;
+
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_mcmr_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_recvd_mcmember_rec =
+    (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+  CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_MCMEMBER_RECORD );
+
+  switch (p_sa_mad->method)
+  {
+  case IB_MAD_METHOD_SET:
+    valid = __check_join_comp_mask(p_sa_mad->comp_mask);
+    if(!valid)
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_mcmr_rcv_process: ERR 1B18: "
+               "component mask = 0x%016" PRIx64 ", "
+               "expected comp mask = 0x%016" PRIx64 " ,"
+               "MGID: 0x%016" PRIx64 " : "
+               "0x%016" PRIx64 " for "
+               "PortGID: 0x%016" PRIx64 " : "
+               "0x%016" PRIx64 "\n",
+               cl_ntoh64(p_sa_mad->comp_mask),
+               CL_NTOH64(JOIN_MC_COMP_MASK),
+               cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.prefix ),
+               cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.interface_id ),
+               cl_ntoh64( p_recvd_mcmember_rec->port_gid.unicast.prefix ),
+               cl_ntoh64( p_recvd_mcmember_rec->port_gid.unicast.interface_id ) );
+
+      osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+      goto Exit;
+    }
+
+    /*
+     * Join or Create Multicast Group
+     */
+    __osm_mcmr_rcv_join_mgrp(p_rcv, p_madw);
+    break;
+  case IB_MAD_METHOD_DELETE:
+    valid = __check_join_comp_mask(p_sa_mad->comp_mask);
+    if(!valid)
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_mcmr_rcv_process: ERR 1B20: "
+               "component mask = 0x%016" PRIx64 ", "
+               "expected comp mask = 0x%016" PRIx64 "\n",
+               cl_ntoh64(p_sa_mad->comp_mask),
+               CL_NTOH64(JOIN_MC_COMP_MASK) );
+
+      osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+      goto Exit;
+    }
+
+    /*
+     * Leave Multicast Group
+     */
+    __osm_mcmr_rcv_leave_mgrp(p_rcv, p_madw);
+    break;
+  case IB_MAD_METHOD_GET:
+  case IB_MAD_METHOD_GETTABLE:
+    /*
+     * Querying a Multicast Group
+     */
+    __osm_mcmr_query_mgrp(p_rcv, p_madw);
+    break;
+  default:
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_mcmr_rcv_process: ERR 1B21: "
+             "Unsupported Method (%s)\n",
+             ib_get_sa_method_str( p_sa_mad->method ) );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+    break;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return;
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mcmember_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mcmember_record_ctrl.c
new file mode 100644 (file)
index 0000000..ce6d88f
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_mcmember_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_mcmr_rcv_ctrl_t.
+ * This object represents the Multicast member record controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_sa_mcmember_record_ctrl.h>
+#include <opensm/osm_sa_mcmember_record.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_mcmr_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_mcmr_rcv_process( ((osm_mcmr_rcv_ctrl_t*)context)->p_rcv,
+                        (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcmr_rcv_ctrl_construct(
+  IN osm_mcmr_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcmr_rcv_ctrl_destroy(
+  IN osm_mcmr_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mcmr_rcv_ctrl_init(
+  IN osm_mcmr_rcv_ctrl_t* const p_ctrl,
+  IN osm_mcmr_recv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_mcmr_rcv_ctrl_init );
+
+  osm_mcmr_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_MCMEMBER_RECORD,
+    __osm_mcmr_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_mcmr_rcv_ctrl_init: ERR 1C01: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mft_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mft_record.c
new file mode 100644 (file)
index 0000000..5cd6efa
--- /dev/null
@@ -0,0 +1,547 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_mftr_rcv_t.
+ *   This object represents the MulticastForwardingTable Receiver object.
+ *   This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_mft_record.h>
+#include <opensm/osm_switch.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_MFTR_RCV_POOL_MIN_SIZE      32
+#define OSM_MFTR_RCV_POOL_GROW_SIZE     32
+
+typedef   struct _osm_mftr_item
+{
+  cl_pool_item_t          pool_item;
+  ib_mft_record_t         rec;
+} osm_mftr_item_t;
+
+typedef   struct _osm_mftr_search_ctxt
+{
+  const ib_mft_record_t*      p_rcvd_rec;
+  ib_net64_t                  comp_mask;
+  cl_qlist_t*                 p_list;
+  osm_mftr_rcv_t*             p_rcv;
+  const osm_physp_t*          p_req_physp;
+} osm_mftr_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mftr_rcv_construct(
+  IN osm_mftr_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+  cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mftr_rcv_destroy(
+  IN osm_mftr_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_mftr_rcv_destroy );
+  cl_qlock_pool_destroy( &p_rcv->pool );
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mftr_rcv_init(
+  IN osm_mftr_rcv_t* const p_rcv,
+  IN osm_sa_resp_t*  const p_resp,
+  IN osm_mad_pool_t* const p_mad_pool,
+  IN osm_subn_t*     const p_subn,
+  IN osm_log_t*      const p_log,
+  IN cl_plock_t*     const p_lock )
+{
+  ib_api_status_t            status;
+
+  OSM_LOG_ENTER( p_log, osm_mftr_rcv_init );
+
+  osm_mftr_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_resp = p_resp;
+  p_rcv->p_mad_pool = p_mad_pool;
+
+  status = cl_qlock_pool_init( &p_rcv->pool,
+                               OSM_MFTR_RCV_POOL_MIN_SIZE,
+                               0,
+                               OSM_MFTR_RCV_POOL_GROW_SIZE,
+                               sizeof(osm_mftr_item_t),
+                               NULL, NULL, NULL );
+
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_mftr_rcv_new_mftr(
+  IN osm_mftr_rcv_t*         const p_rcv,
+  IN osm_switch_t*           const p_sw,
+  IN cl_qlist_t*             const p_list,
+  IN ib_net16_t              const lid,
+  IN uint16_t                const block,
+  IN uint8_t                 const position )
+{
+  osm_mftr_item_t*           p_rec_item;
+  ib_api_status_t            status = IB_SUCCESS;
+  uint16_t                   position_block_num;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_mftr_rcv_new_mftr );
+
+  p_rec_item = (osm_mftr_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+  if( p_rec_item == NULL )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_mftr_rcv_new_mftr: ERR 4A02: "
+             "cl_qlock_pool_get failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_mftr_rcv_new_mftr: "
+             "New MulticastForwardingTable: sw 0x%016" PRIx64
+             "\n\t\t\t\tblock %u position %u lid 0x%02X\n",
+             cl_ntoh64( osm_node_get_node_guid( p_sw->p_node ) ),
+             block, position, cl_ntoh16( lid )
+             );
+  }
+
+  position_block_num = ((uint16_t)position << 12) |
+                       (block & IB_MCAST_BLOCK_ID_MASK_HO);
+
+  memset( &p_rec_item->rec, 0, sizeof(ib_mft_record_t) );
+
+  p_rec_item->rec.lid = lid;
+  p_rec_item->rec.position_block_num = cl_hton16( position_block_num );
+
+  /* copy the mft block */
+  osm_switch_get_mft_block( p_sw, block, position, p_rec_item->rec.mft );
+
+  cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static osm_port_t*
+__osm_mftr_get_port_by_guid(
+  IN osm_mftr_rcv_t*  const p_rcv,
+  IN uint64_t         port_guid )
+{
+  osm_port_t*         p_port;
+
+  CL_PLOCK_ACQUIRE(p_rcv->p_lock);
+
+  p_port = (osm_port_t *)cl_qmap_get(&p_rcv->p_subn->port_guid_tbl,
+                                     port_guid);
+  if (p_port == (osm_port_t *)cl_qmap_end(&p_rcv->p_subn->port_guid_tbl))
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_mftr_get_port_by_guid ERR 4A04: "
+             "Invalid port GUID 0x%016" PRIx64 "\n",
+             port_guid );
+    p_port = NULL;
+  }
+
+  CL_PLOCK_RELEASE(p_rcv->p_lock);
+  return p_port;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mftr_rcv_by_comp_mask(
+  IN cl_map_item_t*         const p_map_item,
+  IN void*                  context )
+{
+  const osm_mftr_search_ctxt_t* const p_ctxt =
+    (osm_mftr_search_ctxt_t *)context;
+  osm_switch_t*             const p_sw = (osm_switch_t*)p_map_item;
+  const ib_mft_record_t*    const p_rcvd_rec = p_ctxt->p_rcvd_rec;
+  osm_mftr_rcv_t*           const p_rcv = p_ctxt->p_rcv;
+  ib_net64_t                const comp_mask = p_ctxt->comp_mask;
+  const osm_physp_t*        const p_req_physp = p_ctxt->p_req_physp;
+  osm_port_t*               p_port;
+  uint16_t                  min_lid_ho, max_lid_ho;
+  uint16_t                  position_block_num_ho;
+  uint16_t                  min_block, max_block, block;
+  const osm_physp_t*        p_physp;
+  uint8_t                   min_position, max_position, position;
+
+  /* In switches, the port guid is the node guid. */
+  p_port =
+    __osm_mftr_get_port_by_guid( p_rcv, p_sw->p_node->node_info.port_guid );
+  if (! p_port)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_mftr_rcv_by_comp_mask: ERR 4A05: "
+             "Failed to find Port by Node Guid:0x%016" PRIx64
+             "\n",
+             cl_ntoh64( p_sw->p_node->node_info.node_guid )
+             );
+    return;
+  }
+
+  /* check that the requester physp and the current physp are under
+     the same partition. */
+  p_physp = osm_port_get_default_phys_ptr( p_port );
+  if (! p_physp)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_mftr_rcv_by_comp_mask: ERR 4A06: "
+             "Failed to find default physical Port by Node Guid:0x%016" PRIx64
+             "\n",
+             cl_ntoh64( p_sw->p_node->node_info.node_guid )
+             );
+    return;
+  }
+  if (! osm_physp_share_pkey( p_rcv->p_log, p_req_physp, p_physp ))
+    return;
+
+  /* get the port 0 of the switch */
+  osm_port_get_lid_range_ho( p_port, &min_lid_ho, &max_lid_ho );
+
+  /* compare the lids - if required */
+  if( comp_mask & IB_MFTR_COMPMASK_LID )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_mftr_rcv_by_comp_mask: "
+             "Comparing lid:0x%02X to port lid range: 0x%02X .. 0x%02X\n",
+             cl_ntoh16( p_rcvd_rec->lid ), min_lid_ho, max_lid_ho
+             );
+    /* ok we are ready for range check */
+    if (min_lid_ho > cl_ntoh16(p_rcvd_rec->lid) ||
+        max_lid_ho < cl_ntoh16(p_rcvd_rec->lid))
+      return;
+  }
+
+  if ( !osm_switch_supports_mcast ( p_sw ) )
+    return;
+
+  /* Are there any blocks in use ? */
+  if ( osm_switch_get_mft_max_block_in_use( p_sw ) == -1 )
+    return;
+
+  position_block_num_ho = cl_ntoh16( p_rcvd_rec->position_block_num );
+
+  /* now we need to decide which blocks to output */
+  if( comp_mask & IB_MFTR_COMPMASK_BLOCK )
+  {
+    max_block = min_block = position_block_num_ho & IB_MCAST_BLOCK_ID_MASK_HO;
+    if ( max_block > osm_switch_get_mft_max_block_in_use( p_sw ) )
+      return;
+  }
+  else
+  {
+    /* use as many blocks as needed */
+    min_block = 0;
+    max_block = osm_switch_get_mft_max_block_in_use( p_sw );
+  }
+
+  /* need to decide which positions to output */
+  if ( comp_mask & IB_MFTR_COMPMASK_POSITION )
+  {
+    min_position = max_position = (position_block_num_ho & 0xF000) >> 12;
+    if (max_position > osm_switch_get_mft_max_position( p_sw ) )
+      return; 
+  }
+  else
+  {
+    /* use as many positions as needed */
+    min_position = 0;
+    max_position = osm_switch_get_mft_max_position( p_sw );
+  }
+
+  /* so we can add these one by one ... */
+  for (block = min_block; block <= max_block; block++)
+    for (position = min_position; position <= max_position; position++)
+      __osm_mftr_rcv_new_mftr( p_rcv, p_sw, p_ctxt->p_list,
+                               osm_port_get_base_lid(p_port),
+                               block, position );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mftr_rcv_process(
+  IN osm_mftr_rcv_t*        const p_rcv,
+  IN const osm_madw_t*      const p_madw )
+{
+  const ib_sa_mad_t*        p_rcvd_mad;
+  const ib_mft_record_t*    p_rcvd_rec;
+  ib_mft_record_t*          p_resp_rec;
+  cl_qlist_t                rec_list;
+  osm_madw_t*               p_resp_madw;
+  ib_sa_mad_t*              p_resp_sa_mad;
+  uint32_t                  num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  uint32_t                  trim_num_rec;
+#endif
+  uint32_t                  i;
+  osm_mftr_search_ctxt_t    context;
+  osm_mftr_item_t*          p_rec_item;
+  ib_api_status_t           status = IB_SUCCESS;
+  osm_physp_t*              p_req_physp;
+
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_mftr_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_rcvd_rec = (ib_mft_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+
+  CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_MFT_RECORD );
+
+  /* we only support SubnAdmGet and SubnAdmGetTable methods */
+  if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) &&
+       (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) ) {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_mftr_rcv_process: ERR 4A08: "
+             "Unsupported Method (%s)\n",
+             ib_get_sa_method_str( p_rcvd_mad->method ) );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+    goto Exit;
+  }
+
+  /* update the requester physical port. */
+  p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+                                          p_rcv->p_subn,
+                                          osm_madw_get_mad_addr_ptr(p_madw) );
+  if (p_req_physp == NULL)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_mftr_rcv_process: ERR 4A07: "
+             "Cannot find requester physical port\n" );
+    goto Exit;
+  }
+
+  cl_qlist_init( &rec_list );
+
+  context.p_rcvd_rec     = p_rcvd_rec;
+  context.p_list         = &rec_list;
+  context.comp_mask      = p_rcvd_mad->comp_mask;
+  context.p_rcv          = p_rcv;
+  context.p_req_physp    = p_req_physp;
+
+  cl_plock_acquire( p_rcv->p_lock );
+
+  /* Go over all switches */
+  cl_qmap_apply_func( &p_rcv->p_subn->sw_guid_tbl,
+                      __osm_mftr_rcv_by_comp_mask,
+                      &context );
+
+  cl_plock_release( p_rcv->p_lock );
+
+  num_rec = cl_qlist_count( &rec_list );
+
+  /*
+   * C15-0.1.30:
+   * If we do a SubnAdmGet and got more than one record it is an error !
+   */
+  if (p_rcvd_mad->method == IB_MAD_METHOD_GET)
+  {
+    if (num_rec == 0)
+    {
+      osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+      goto Exit;
+    }
+    if (num_rec > 1)
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_mftr_rcv_process: ERR 4A09: "
+               "Got more than one record for SubnAdmGet (%u)\n",
+               num_rec );
+      osm_sa_send_error( p_rcv->p_resp, p_madw,
+                         IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+
+      /* need to set the mem free ... */
+      p_rec_item = (osm_mftr_item_t*)cl_qlist_remove_head( &rec_list );
+      while( p_rec_item != (osm_mftr_item_t*)cl_qlist_end( &rec_list ) )
+      {
+        cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+        p_rec_item = (osm_mftr_item_t*)cl_qlist_remove_head( &rec_list );
+      }
+
+      goto Exit;
+    }
+  }
+
+  pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  /* we limit the number of records to a single packet */
+  trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_mft_record_t);
+  if (trim_num_rec < num_rec)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "osm_mftr_rcv_process: "
+             "Number of records:%u trimmed to:%u to fit in one MAD\n",
+             num_rec, trim_num_rec );
+    num_rec = trim_num_rec;
+  }
+#endif
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+           "osm_mftr_rcv_process: "
+           "Returning %u records\n", num_rec );
+
+  if ((p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) &&
+      (num_rec == 0))
+  {
+    osm_sa_send_error( p_rcv->p_resp, p_madw,
+                       IB_SA_MAD_STATUS_NO_RECORDS );
+    goto Exit;
+  }
+
+  /* 
+   * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+   */
+  p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+                                  p_madw->h_bind,
+                                  num_rec * sizeof(ib_mft_record_t) + IB_SA_MAD_HDR_SIZE,
+                                  &p_madw->mad_addr );
+
+  if( !p_resp_madw )
+  {
+    osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+            "osm_mftr_rcv_process: ERR 4A10: "
+            "osm_mad_pool_get failed\n" );
+
+    for( i = 0; i < num_rec; i++ )
+    {
+      p_rec_item = (osm_mftr_item_t*)cl_qlist_remove_head( &rec_list );
+      cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    }
+
+    osm_sa_send_error( p_rcv->p_resp, p_madw,
+                       IB_SA_MAD_STATUS_NO_RESOURCES );
+
+    goto Exit;
+  }
+
+  p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+  /*
+    Copy the MAD header back into the response mad.
+    Set the 'R' bit and the payload length,
+    Then copy all records from the list into the response payload.
+  */
+
+  memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+  /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
+  p_resp_sa_mad->sm_key = 0;
+  /* Fill in the offset (paylen will be done by the rmpp SAR) */
+  p_resp_sa_mad->attr_offset =
+    ib_get_attr_offset( sizeof(ib_mft_record_t) );
+
+  p_resp_rec = (ib_mft_record_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+#ifndef VENDOR_RMPP_SUPPORT
+  /* we support only one packet RMPP - so we will set the first and
+     last flags for gettable */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+  {
+    p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+  }
+#else
+  /* forcefully define the packet as RMPP one */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+  for( i = 0; i < pre_trim_num_rec; i++ )
+  {
+    p_rec_item = (osm_mftr_item_t*)cl_qlist_remove_head( &rec_list );
+    /* copy only if not trimmed */
+    if (i < num_rec)
+    {
+      *p_resp_rec = p_rec_item->rec;
+    }
+    cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    p_resp_rec++;
+  }
+
+  CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+  status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+  if (status != IB_SUCCESS)
+  {
+    osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+            "osm_mftr_rcv_process: ERR 4A11: "
+            "osm_vendor_send status = %s\n",
+            ib_get_err_str(status));
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mft_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_mft_record_ctrl.c
new file mode 100644 (file)
index 0000000..3c0c39c
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_mftr_rcv_ctrl_t.
+ * This object represents the MulticastForwardingTable request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_mft_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_mftr_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_mftr_rcv_process( ((osm_mftr_rcv_ctrl_t*)context)->p_rcv,
+                        (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mftr_rcv_ctrl_construct(
+  IN osm_mftr_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mftr_rcv_ctrl_destroy(
+  IN osm_mftr_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mftr_rcv_ctrl_init(
+  IN osm_mftr_rcv_ctrl_t* const p_ctrl,
+  IN osm_mftr_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_mftr_rcv_ctrl_init );
+
+  osm_mftr_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_MFT_RECORD,
+    __osm_mftr_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_mftr_rcv_ctrl_init: ERR 4A01: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_multipath_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_multipath_record.c
new file mode 100644 (file)
index 0000000..83404e0
--- /dev/null
@@ -0,0 +1,1652 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ *     Implementation of osm_mpr_rcv_t.
+ *     This object represents the MultiPath Record Receiver object.
+ *     This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ */
+
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_multipath_record.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_partition.h>
+#include <vendor/osm_vendor.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+
+#define OSM_MPR_RCV_POOL_MIN_SIZE      64
+#define OSM_MPR_RCV_POOL_GROW_SIZE     64
+
+#define OSM_SA_MPR_MAX_NUM_PATH        127
+
+typedef        struct  _osm_mpr_item
+{
+       cl_pool_item_t           pool_item;
+       const osm_port_t        *p_src_port;
+       const osm_port_t        *p_dest_port;
+       int                      hops;
+       ib_path_rec_t            path_rec;
+} osm_mpr_item_t;
+
+typedef struct _osm_path_parms
+{
+       ib_net16_t              pkey;
+       uint8_t                 mtu;
+       uint8_t                 rate;
+       uint8_t                 sl;
+       uint8_t                 pkt_life;
+       boolean_t               reversible;
+       int                     hops;
+} osm_path_parms_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mpr_rcv_construct(
+  IN osm_mpr_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+  cl_qlock_pool_construct( &p_rcv->pr_pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mpr_rcv_destroy(
+  IN osm_mpr_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_mpr_rcv_destroy );
+  cl_qlock_pool_destroy( &p_rcv->pr_pool );
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mpr_rcv_init(
+  IN osm_mpr_rcv_t*    const p_rcv,
+  IN osm_sa_resp_t*    const p_resp,
+  IN osm_mad_pool_t*   const p_mad_pool,
+  IN osm_subn_t*       const p_subn,
+  IN osm_log_t*                const p_log,
+  IN cl_plock_t*       const p_lock )
+{
+  ib_api_status_t       status;
+
+  OSM_LOG_ENTER( p_log, osm_mpr_rcv_init );
+
+  osm_mpr_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_resp = p_resp;
+  p_rcv->p_mad_pool = p_mad_pool;
+
+  status = cl_qlock_pool_init( &p_rcv->pr_pool,
+                              OSM_MPR_RCV_POOL_MIN_SIZE,
+                              0,
+                              OSM_MPR_RCV_POOL_GROW_SIZE,
+                              sizeof(osm_mpr_item_t),
+                              NULL, NULL, NULL );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline boolean_t
+__osm_sa_multipath_rec_is_tavor_port(
+  IN const osm_port_t*     const p_port)
+{
+  osm_node_t const* p_node;
+  ib_net32_t vend_id;
+
+  p_node = osm_port_get_parent_node( p_port );
+  vend_id = ib_node_info_get_vendor_id( &p_node->node_info );
+
+  return( (p_node->node_info.device_id == CL_HTON16(23108)) &&
+         ((vend_id == CL_HTON32(OSM_VENDOR_ID_MELLANOX)) || 
+          (vend_id == CL_HTON32(OSM_VENDOR_ID_TOPSPIN)) || 
+          (vend_id == CL_HTON32(OSM_VENDOR_ID_SILVERSTORM)) || 
+          (vend_id == CL_HTON32(OSM_VENDOR_ID_VOLTAIRE))) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+ __osm_sa_multipath_rec_apply_tavor_mtu_limit(
+  IN const ib_multipath_rec_t*  const p_mpr,
+  IN const osm_port_t*          const p_src_port,
+  IN const osm_port_t*          const p_dest_port,
+  IN const ib_net64_t           comp_mask)
+{
+  uint8_t   required_mtu;
+       
+  /* only if at least one of the ports is a Tavor device */
+  if (! __osm_sa_multipath_rec_is_tavor_port(p_src_port) && 
+      ! __osm_sa_multipath_rec_is_tavor_port(p_dest_port) )
+    return( FALSE );
+       
+  /*
+    we can apply the patch if either:
+    1. No MTU required
+    2. Required MTU < 
+    3. Required MTU = 1K or 512 or 256
+    4. Required MTU > 256 or 512
+  */
+  required_mtu = ib_multipath_rec_mtu( p_mpr );
+  if ( ( comp_mask & IB_MPR_COMPMASK_MTUSELEC ) &&
+       ( comp_mask & IB_PR_COMPMASK_MTU ) )
+  {
+    switch( ib_multipath_rec_mtu_sel( p_mpr ) )
+    {
+    case 0:    /* must be greater than */
+    case 2:    /* exact match */
+      if( IB_MTU_LEN_1024 < required_mtu )
+       return(FALSE);
+      break;
+
+    case 1:    /* must be less than */
+              /* can't be disqualified by this one */
+      break;
+
+    case 3:    /* largest available */
+               /* the ULP intentionally requested */
+               /* the largest MTU possible */
+      return(FALSE);
+      break;
+                       
+    default:
+      /* if we're here, there's a bug in ib_multipath_rec_mtu_sel() */
+      CL_ASSERT( FALSE );
+      break;
+    }
+  }
+
+  return(TRUE);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_mpr_rcv_get_path_parms(
+  IN osm_mpr_rcv_t*            const p_rcv,
+  IN const ib_multipath_rec_t* const p_mpr,
+  IN const osm_port_t*         const p_src_port,
+  IN const osm_port_t*         const p_dest_port,
+  IN const uint16_t            dest_lid_ho,
+  IN const ib_net64_t          comp_mask,
+  OUT osm_path_parms_t*                const p_parms )
+{
+  const osm_node_t*            p_node;
+  const osm_physp_t*           p_physp;
+  const osm_physp_t*           p_dest_physp;
+  const osm_prtn_t*            p_prtn;
+  const ib_port_info_t*                p_pi;
+  ib_slvl_table_t*             p_slvl_tbl;
+  ib_api_status_t              status = IB_SUCCESS;
+  uint8_t                      mtu;
+  uint8_t                      rate;
+  uint8_t                      pkt_life;
+  uint8_t                      required_mtu;
+  uint8_t                      required_rate;
+  uint16_t                     required_pkey;
+  uint8_t                      required_sl;
+  uint8_t                      required_pkt_life;
+  ib_net16_t                   dest_lid;
+  int                          hops = 0;
+  int                          in_port_num = 0;
+  uint8_t                      vl;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_get_path_parms );
+
+  dest_lid = cl_hton16( dest_lid_ho );
+
+  p_dest_physp = osm_port_get_default_phys_ptr( p_dest_port );
+  p_physp = osm_port_get_default_phys_ptr( p_src_port );
+  p_pi = osm_physp_get_port_info_ptr( p_physp );
+
+  mtu = ib_port_info_get_mtu_cap( p_pi );
+  rate = ib_port_info_compute_rate( p_pi );
+
+  /* 
+    Mellanox Tavor device performance is better using 1K MTU.
+    If required MTU and MTU selector are such that 1K is OK 
+    and at least one end of the path is Tavor we override the
+    port MTU with 1K.
+  */
+  if ( p_rcv->p_subn->opt.enable_quirks &&
+       __osm_sa_multipath_rec_apply_tavor_mtu_limit(
+               p_mpr, p_src_port, p_dest_port, comp_mask) )
+    if (mtu > IB_MTU_LEN_1024) 
+    {
+      mtu = IB_MTU_LEN_1024;
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+              "__osm_mpr_rcv_get_path_parms: "
+              "Optimized Path MTU to 1K for Mellanox Tavor device\n");
+    }
+
+  if ( comp_mask & IB_MPR_COMPMASK_RAWTRAFFIC &&
+       cl_ntoh32( p_mpr->hop_flow_raw ) & ( 1<<31 ) )
+    required_pkey = osm_physp_find_common_pkey( p_physp, p_dest_physp );
+  else if ( comp_mask & IB_MPR_COMPMASK_PKEY ) {
+    required_pkey = p_mpr->pkey;
+    if( !osm_physp_share_this_pkey( p_physp, p_dest_physp, required_pkey ) ) {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+              "__osm_mpr_rcv_get_path_parms: ERR 4518: "
+              "Ports do not share specified PKey 0x%04x\n"
+              "\t\tsrc %" PRIx64 " dst %" PRIx64 "\n",
+              cl_ntoh16( required_pkey ),
+              cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+              cl_ntoh64( osm_physp_get_port_guid( p_dest_physp ) ) );
+      status = IB_NOT_FOUND;
+      goto Exit;
+    }
+  } else {
+    required_pkey = osm_physp_find_common_pkey( p_physp, p_dest_physp );
+    if ( !required_pkey ) {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_mpr_rcv_get_path_parms: ERR 4519: "
+               "Ports do not have any shared PKeys\n"
+               "\t\tsrc %" PRIx64 " dst %" PRIx64 "\n",
+               cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+               cl_ntoh64( osm_physp_get_port_guid( p_dest_physp ) ) );
+      status = IB_NOT_FOUND;
+      goto Exit;
+    }
+  }
+
+  required_sl = OSM_DEFAULT_SL;
+
+  if (required_pkey) {
+    p_prtn = (osm_prtn_t *)cl_qmap_get(&p_rcv->p_subn->prtn_pkey_tbl,
+                                      required_pkey & cl_ntoh16((uint16_t)~0x8000));
+    if ( p_prtn == (osm_prtn_t *)cl_qmap_end(&p_rcv->p_subn->prtn_pkey_tbl) )
+    {
+      /* this may be possible when pkey tables are created somehow in
+         previous runs or things are going wrong here */
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_mpr_rcv_get_path_parms: ERR 451A: "
+               "No partition found for PKey 0x%04x - using default SL %d\n", cl_ntoh16(required_pkey), required_sl );
+    }
+    else
+      required_sl = p_prtn->sl;
+
+    /* reset pkey when raw traffic */
+    if( comp_mask & IB_PR_COMPMASK_RAWTRAFFIC &&
+        cl_ntoh32( p_mpr->hop_flow_raw ) & ( 1<<31 ) )
+      required_pkey = 0;
+  }
+
+  if ( ( comp_mask & IB_MPR_COMPMASK_SL ) && ib_multipath_rec_sl( p_mpr ) != required_sl )
+  {
+    status = IB_NOT_FOUND;
+    goto Exit;
+  }
+
+  /*
+    Walk the subnet object from source to destination,
+    tracking the most restrictive rate and mtu values along the way...
+
+    If source port node is a switch, then p_physp should
+    point to the port that routes the destination lid
+  */
+
+  p_node = osm_physp_get_node_ptr( p_physp );
+
+  if ( p_node->sw )
+  {
+
+    /*
+     * If the dest_lid_ho is equal to the lid of the switch pointed by
+     * p_sw then p_physp will be the physical port of the switch port zero.
+     */
+    p_physp = osm_switch_get_route_by_lid( p_node->sw, cl_ntoh16( dest_lid_ho ) );
+    if ( p_physp == 0 )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_mpr_rcv_get_path_parms: ERR 4514: "
+               "Can't find routing to LID 0x%X from switch for GUID 0x%016" PRIx64 "\n",
+               dest_lid_ho,
+               cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+      status = IB_ERROR;
+      goto Exit;
+    }
+  }
+
+  /*
+   * Same as above
+   */
+  p_node = osm_physp_get_node_ptr( p_dest_physp );
+       
+  if ( p_node->sw )
+  {
+
+    p_dest_physp = osm_switch_get_route_by_lid( p_node->sw, cl_ntoh16( dest_lid_ho ) );
+
+    if ( p_dest_physp == 0 )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_mpr_rcv_get_path_parms: ERR 4515: "
+               "Can't find routing to LID 0x%X from switch for GUID 0x%016" PRIx64 "\n",
+               dest_lid_ho,
+               cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  }
+
+  while ( p_physp != p_dest_physp )
+  {
+    p_physp = osm_physp_get_remote( p_physp );
+
+    if ( p_physp == 0 )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_mpr_rcv_get_path_parms: ERR 4505: "
+               "Can't find remote phys port when routing to LID 0x%X from node GUID 0x%016" PRIx64 "\n",
+               dest_lid_ho,
+               cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+    hops++;
+
+    /*
+      This is point to point case (no switch in between)
+    */
+    if ( p_physp == p_dest_physp )
+      break;
+
+    p_node = osm_physp_get_node_ptr( p_physp );
+
+    if ( !p_node->sw )
+    {
+      /*
+        There is some sort of problem in the subnet object!
+        If this isn't a switch, we should have reached
+        the destination by now!
+      */
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+              "__osm_mpr_rcv_get_path_parms: ERR 4503: "
+              "Internal error, bad path\n" );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+    /*
+      Check parameters for the ingress port in this switch.
+    */
+    p_pi = osm_physp_get_port_info_ptr( p_physp );
+
+    if ( mtu > ib_port_info_get_mtu_cap( p_pi ) )
+    {
+      mtu = ib_port_info_get_mtu_cap( p_pi );
+      if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+                "__osm_mpr_rcv_get_path_parms: "
+                "New smallest MTU = %u at intervening port 0x%016" PRIx64
+                " port num 0x%X\n",
+                mtu,
+                cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+                osm_physp_get_port_num( p_physp ) );
+      }
+    }
+
+    if ( rate > ib_port_info_compute_rate( p_pi ) )
+    {
+      rate = ib_port_info_compute_rate( p_pi );
+      if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+                 "__osm_mpr_rcv_get_path_parms: "
+                "New smallest rate = %u at intervening port 0x%016" PRIx64
+                " port num 0x%X\n",
+                rate,
+                cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+                osm_physp_get_port_num( p_physp ) );
+      }
+    }
+
+    /*
+      Continue with the egress port on this switch.
+    */
+    p_physp = osm_switch_get_route_by_lid( p_node->sw, dest_lid );
+
+    if ( p_physp == 0 )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_mpr_rcv_get_path_parms: ERR 4516: "
+               "Dead end on path to LID 0x%X from switch for GUID 0x%016" PRIx64 "\n",
+               dest_lid_ho,
+               cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+    CL_ASSERT( p_physp );
+    CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+    if ( comp_mask & IB_MPR_COMPMASK_SL ) {
+      in_port_num = osm_physp_get_port_num( p_physp );
+      p_slvl_tbl = osm_physp_get_slvl_tbl( p_physp, in_port_num );
+      vl = ib_slvl_table_get( p_slvl_tbl, required_sl );
+      if (vl == IB_DROP_VL) {  /* discard packet */
+        osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+                 "__osm_mpr_rcv_get_path_parms: Path not found for SL %d\n"
+                "\t\tin_port_num %d port_guid %" PRIx64 "\n",
+                required_sl, in_port_num,
+                cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) );
+        status = IB_NOT_FOUND;
+        goto Exit;
+      }
+    }
+
+    p_pi = osm_physp_get_port_info_ptr( p_physp );
+
+    if ( mtu > ib_port_info_get_mtu_cap( p_pi ) )
+    {
+      mtu = ib_port_info_get_mtu_cap( p_pi );
+      if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+                "__osm_mpr_rcv_get_path_parms: "
+                "New smallest MTU = %u at intervening port 0x%016" PRIx64
+                " port num 0x%X\n",
+                mtu,
+                cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+                osm_physp_get_port_num( p_physp ) );
+      }
+    }
+
+    if ( rate > ib_port_info_compute_rate( p_pi ) )
+    {
+      rate = ib_port_info_compute_rate( p_pi );
+      if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+                "__osm_mpr_rcv_get_path_parms: "
+                "New smallest rate = %u at intervening port 0x%016" PRIx64
+                " port num 0x%X\n",
+                rate,
+                cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+                osm_physp_get_port_num( p_physp ) );
+      }
+    }
+
+  }
+
+  /*
+    p_physp now points to the destination
+  */
+  p_pi = osm_physp_get_port_info_ptr( p_physp );
+
+  if ( mtu > ib_port_info_get_mtu_cap( p_pi ) )
+  {
+    mtu = ib_port_info_get_mtu_cap( p_pi );
+    if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+              "__osm_mpr_rcv_get_path_parms: "
+              "New smallest MTU = %u at destination port 0x%016" PRIx64 "\n",
+              mtu,
+              cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) );
+    }
+  }
+
+  if ( rate > ib_port_info_compute_rate( p_pi ) )
+  {
+    rate = ib_port_info_compute_rate( p_pi );
+    if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+              "__osm_mpr_rcv_get_path_parms: "
+              "New smallest rate = %u at destination port 0x%016" PRIx64 "\n",
+              rate,
+              cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) );
+    }
+  }
+
+  if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+            "__osm_mpr_rcv_get_path_parms: "
+            "Path min MTU = %u, min rate = %u\n", mtu, rate );
+  }
+
+  /*
+    Determine if these values meet the user criteria
+  */
+
+  /* we silently ignore cases where only the MTU selector is defined */
+  if ( ( comp_mask & IB_MPR_COMPMASK_MTUSELEC ) &&
+       ( comp_mask & IB_MPR_COMPMASK_MTU ) )
+  {
+    required_mtu = ib_multipath_rec_mtu( p_mpr );
+    switch ( ib_multipath_rec_mtu_sel( p_mpr ) )
+    {
+      case 0:  /* must be greater than */
+        if ( mtu <= required_mtu )
+          status = IB_NOT_FOUND;
+        break;
+
+      case 1:  /* must be less than */
+        if ( mtu >= required_mtu )
+        {
+          /* adjust to use the highest mtu
+             lower then the required one */
+          if ( required_mtu > 1 )
+            mtu = required_mtu - 1;
+          else
+            status = IB_NOT_FOUND;
+        }
+        break;
+
+      case 2:  /* exact match */
+        if ( mtu < required_mtu )
+          status = IB_NOT_FOUND;
+        else
+          mtu = required_mtu;
+        break;
+
+      case 3:  /* largest available */
+        /* can't be disqualified by this one */
+        break;
+
+      default:
+        /* if we're here, there's a bug in ib_multipath_rec_mtu_sel() */
+        CL_ASSERT( FALSE );
+        status = IB_ERROR;
+        break;
+    }
+  }
+
+  /* we silently ignore cases where only the Rate selector is defined */
+  if ( ( comp_mask & IB_MPR_COMPMASK_RATESELEC ) &&
+       ( comp_mask & IB_PR_COMPMASK_RATE ) )
+  {
+    required_rate = ib_multipath_rec_rate( p_mpr );
+    switch ( ib_multipath_rec_rate_sel( p_mpr ) )
+    {
+      case 0:  /* must be greater than */
+        if ( rate <= required_rate )
+          status = IB_NOT_FOUND;
+        break;
+
+      case 1:  /* must be less than */
+        if ( rate >= required_rate )
+        {
+          /* adjust the rate to use the highest rate
+             lower then the required one */
+          if ( required_rate > 2 )
+            rate = required_rate - 1;
+          else
+            status = IB_NOT_FOUND;
+        }
+        break;
+
+      case 2:  /* exact match */
+        if ( rate < required_rate )
+          status = IB_NOT_FOUND;
+        else
+           rate = required_rate;
+        break;
+
+      case 3:  /* largest available */
+        /* can't be disqualified by this one */
+        break;
+
+      default:
+        /* if we're here, there's a bug in ib_multipath_rec_mtu_sel() */
+        CL_ASSERT( FALSE );
+        status = IB_ERROR;
+        break;
+    }
+  }
+
+  /* Verify the pkt_life_time */
+  /* According to spec definition IBA 1.2 Table 205 PacketLifeTime description,
+     for loopback paths, packetLifeTime shall be zero. */
+  if ( p_src_port == p_dest_port )
+    pkt_life = 0;      /* loopback */
+  else
+    pkt_life = OSM_DEFAULT_SUBNET_TIMEOUT;
+
+  /* we silently ignore cases where only the PktLife selector is defined */
+  if ( ( comp_mask & IB_MPR_COMPMASK_PKTLIFETIMESELEC ) &&
+       ( comp_mask & IB_MPR_COMPMASK_PKTLIFETIME ) )
+  {
+    required_pkt_life = ib_multipath_rec_pkt_life( p_mpr );
+    switch ( ib_multipath_rec_pkt_life_sel( p_mpr ) )
+    {
+    case 0:    /* must be greater than */
+      if ( pkt_life <= required_pkt_life )
+        status = IB_NOT_FOUND;
+      break;
+
+    case 1:    /* must be less than */
+       if ( pkt_life >= required_pkt_life )
+       {
+          /* adjust the lifetime to use the highest possible
+             lower then the required one */
+          if ( required_pkt_life > 1 )
+             pkt_life = required_pkt_life - 1;
+          else
+             status = IB_NOT_FOUND;
+       }
+       break;
+
+    case 2:    /* exact match */
+       if ( pkt_life < required_pkt_life )
+          status = IB_NOT_FOUND;
+       else
+          pkt_life = required_pkt_life;
+      break;
+
+    case 3:    /* smallest available */
+      /* can't be disqualified by this one */
+      break;
+
+    default:
+      /* if we're here, there's a bug in ib_path_rec_pkt_life_sel() */
+      CL_ASSERT( FALSE );
+      status = IB_ERROR;
+      break;
+    }
+  }
+
+  if (status != IB_SUCCESS)
+    goto Exit;
+
+  p_parms->mtu = mtu;
+  p_parms->rate = rate;
+  p_parms->pkey = required_pkey;
+  p_parms->pkt_life = pkt_life;
+  p_parms->sl = required_sl;
+  p_parms->hops = hops;
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mpr_rcv_build_pr(
+  IN osm_mpr_rcv_t*            const p_rcv,
+  IN const osm_port_t*         const p_src_port,
+  IN const osm_port_t*         const p_dest_port,
+  IN const uint16_t            src_lid_ho,
+  IN const uint16_t            dest_lid_ho,
+  IN const uint8_t             preference,
+  IN const osm_path_parms_t*   const p_parms,
+  OUT ib_path_rec_t*           const p_pr )
+{
+  const osm_physp_t*           p_src_physp;
+  const osm_physp_t*           p_dest_physp;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_build_pr );
+
+  p_src_physp = osm_port_get_default_phys_ptr( p_src_port );
+  p_dest_physp = osm_port_get_default_phys_ptr( p_dest_port );
+
+  p_pr->dgid.unicast.prefix = osm_physp_get_subnet_prefix( p_dest_physp );
+  p_pr->dgid.unicast.interface_id = osm_physp_get_port_guid( p_dest_physp );
+
+  p_pr->sgid.unicast.prefix = osm_physp_get_subnet_prefix( p_src_physp );
+  p_pr->sgid.unicast.interface_id = osm_physp_get_port_guid( p_src_physp );
+
+  p_pr->dlid = cl_hton16( dest_lid_ho );
+  p_pr->slid = cl_hton16( src_lid_ho );
+
+  p_pr->hop_flow_raw &= cl_hton32(1<<31);
+
+  p_pr->pkey = p_parms->pkey;
+  p_pr->sl = cl_hton16( p_parms->sl );
+  p_pr->mtu = (uint8_t)( p_parms->mtu | 0x80 );
+  p_pr->rate = (uint8_t)( p_parms->rate | 0x80 );
+
+  /* According to 1.2 spec definition Table 205 PacketLifeTime description,
+     for loopback paths, packetLifeTime shall be zero. */
+  if ( p_src_port == p_dest_port )
+    p_pr->pkt_life = 0x80;     /* loopback */
+  else
+    p_pr->pkt_life = (uint8_t)( p_parms->pkt_life | 0x80 );
+
+  p_pr->preference = preference;
+
+  /* always return num_path = 0 so this is only the reversible component */
+  if ( p_parms->reversible )
+    p_pr->num_path = 0x80;
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static osm_mpr_item_t*
+__osm_mpr_rcv_get_lid_pair_path(
+  IN osm_mpr_rcv_t*            const p_rcv,
+  IN const ib_multipath_rec_t* const p_mpr,
+  IN const osm_port_t*         const p_src_port,
+  IN const osm_port_t*         const p_dest_port,
+  IN const uint16_t            src_lid_ho,
+  IN const uint16_t            dest_lid_ho,
+  IN const ib_net64_t          comp_mask,
+  IN const uint8_t             preference )
+{
+  osm_path_parms_t             path_parms;
+  osm_path_parms_t             rev_path_parms;
+  osm_mpr_item_t               *p_pr_item;
+  ib_api_status_t              status, rev_path_status;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_get_lid_pair_path );
+
+  if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+            "__osm_mpr_rcv_get_lid_pair_path: "
+            "Src LID 0x%X, Dest LID 0x%X\n",
+            src_lid_ho, dest_lid_ho );
+  }
+
+  p_pr_item = (osm_mpr_item_t*)cl_qlock_pool_get( &p_rcv->pr_pool );
+  if ( p_pr_item == NULL )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+            "__osm_mpr_rcv_get_lid_pair_path: ERR 4501: "
+            "Unable to allocate path record\n" );
+    goto Exit;
+  }
+
+  status = __osm_mpr_rcv_get_path_parms( p_rcv, p_mpr, p_src_port,
+                                        p_dest_port, dest_lid_ho,
+                                         comp_mask, &path_parms );
+
+  if ( status != IB_SUCCESS )
+  {
+    cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item );
+    p_pr_item = NULL;
+    goto Exit;
+  }
+
+  /* now try the reversible path */
+  rev_path_status = __osm_mpr_rcv_get_path_parms( p_rcv, p_mpr, p_dest_port,
+                                                  p_src_port, src_lid_ho,
+                                                  comp_mask, &rev_path_parms );
+  path_parms.reversible = ( rev_path_status == IB_SUCCESS );
+
+  /* did we get a Reversible Path compmask ? */
+  /* 
+     NOTE that if the reversible component = 0, it is a don't care
+     rather then requiring non-reversible paths ... 
+     see Vol1 Ver1.2 p900 l16
+  */
+  if ( comp_mask & IB_MPR_COMPMASK_REVERSIBLE )
+  {
+    if ( (! path_parms.reversible && ( p_mpr->num_path & 0x80 ) ) )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+               "__osm_mpr_rcv_get_lid_pair_path: "
+               "Requested reversible path but failed to get one\n");
+
+      cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item );
+      p_pr_item = NULL;
+      goto Exit;
+    }
+  }
+
+  p_pr_item->p_src_port = p_src_port;
+  p_pr_item->p_dest_port = p_dest_port;
+  p_pr_item->hops = path_parms.hops;
+
+  __osm_mpr_rcv_build_pr( p_rcv, p_src_port, p_dest_port, src_lid_ho,
+                         dest_lid_ho, preference, &path_parms,
+                          &p_pr_item->path_rec );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( p_pr_item );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static uint32_t 
+__osm_mpr_rcv_get_port_pair_paths(
+  IN osm_mpr_rcv_t*            const p_rcv,
+  IN const ib_multipath_rec_t*  const p_mpr,
+  IN const osm_port_t*         const p_req_port,
+  IN const osm_port_t*         const p_src_port,
+  IN const osm_port_t*         const p_dest_port,
+  IN const uint32_t            rem_paths,
+  IN const ib_net64_t          comp_mask,
+  IN cl_qlist_t*               const p_list )
+{
+  osm_mpr_item_t*              p_pr_item;
+  uint16_t                     src_lid_min_ho;
+  uint16_t                     src_lid_max_ho;
+  uint16_t                     dest_lid_min_ho;
+  uint16_t                     dest_lid_max_ho;
+  uint16_t                     src_lid_ho;
+  uint16_t                     dest_lid_ho;
+  uint32_t                     path_num = 0;
+  uint8_t                      preference;
+  uintn_t                      src_offset;
+  uintn_t                      dest_offset;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_get_port_pair_paths );
+
+  if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+            "__osm_mpr_rcv_get_port_pair_paths: "
+            "Src port 0x%016" PRIx64 ", "
+            "Dst port 0x%016" PRIx64 "\n",
+            cl_ntoh64( osm_port_get_guid( p_src_port ) ),
+            cl_ntoh64( osm_port_get_guid( p_dest_port ) ) );
+  }
+
+  /* Check that the req_port, src_port and dest_port all share a
+     pkey. The check is done on the default physical port of the ports. */
+  if ( osm_port_share_pkey(p_rcv->p_log, p_req_port, p_src_port ) == FALSE ||
+       osm_port_share_pkey(p_rcv->p_log, p_req_port, p_dest_port ) == FALSE ||
+       osm_port_share_pkey(p_rcv->p_log, p_src_port, p_dest_port ) == FALSE )
+  {
+    /* One of the pairs doesn't share a pkey so the path is disqualified. */
+    goto Exit;
+  }
+
+  /*
+    We shouldn't be here if the paths are disqualified in some way...
+    Thus, we assume every possible connection is valid.
+
+    We desire to return high-quality paths first.
+    In OpenSM, higher quality mean least overlap with other paths.
+    This is acheived in practice by returning paths with
+    different LID value on each end, which means these
+    paths are more redundant that paths with the same LID repeated
+    on one side.  For example, in OpenSM the paths between two
+    endpoints with LMC = 1 might be as follows:
+
+    Port A, LID 1 <-> Port B, LID 3
+    Port A, LID 1 <-> Port B, LID 4
+    Port A, LID 2 <-> Port B, LID 3
+    Port A, LID 2 <-> Port B, LID 4
+
+    The OpenSM unicast routing algorithms attempt to disperse each path
+    to as varied a physical path as is reasonable.  1<->3 and 1<->4 have
+    more physical overlap (hence less redundancy) than 1<->3 and 2<->4.
+
+    OpenSM ranks paths in three preference groups:
+
+    Preference Value           Description
+    ----------------           -------------------------------------------
+    0                  Redundant in both directions with other
+    pref value = 0 paths
+
+    1                  Redundant in one direction with other
+    pref value = 0 and pref value = 1 paths
+
+    2                  Not redundant in either direction with
+    other paths
+
+    3-FF                       Unused
+
+
+    SA clients don't need to know these details, only that the lower
+    preference paths are preferred, as stated in the spec.  The paths
+    may not actually be physically redundant depending on the topology
+    of the subnet, but the point of LMC > 0 is to offer redundancy,
+    so I assume the subnet is physically appropriate for the specified
+    LMC value.  A more advanced implementation could inspect for physical
+    redundancy, but I'm not going to bother with that now.
+  */
+
+  osm_port_get_lid_range_ho( p_src_port, &src_lid_min_ho, &src_lid_max_ho );
+  osm_port_get_lid_range_ho( p_dest_port, &dest_lid_min_ho, &dest_lid_max_ho );
+
+  if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+            "__osm_mpr_rcv_get_port_pair_paths: "
+            "Src LID [0x%X-0x%X], "
+            "Dest LID [0x%X-0x%X]\n",
+            src_lid_min_ho, src_lid_max_ho,
+            dest_lid_min_ho, dest_lid_max_ho );
+  }
+
+  src_lid_ho = src_lid_min_ho;
+  dest_lid_ho = dest_lid_min_ho;
+
+  /*
+    Preferred paths come first in OpenSM
+  */
+  preference = 0;
+
+  while ( path_num < rem_paths )
+  {
+    /*
+      These paths are "fully redundant"
+    */
+     p_pr_item = __osm_mpr_rcv_get_lid_pair_path( p_rcv, p_mpr,
+                                                 p_src_port, p_dest_port,
+                                                  src_lid_ho, dest_lid_ho,
+                                                 comp_mask, preference );
+
+    if ( p_pr_item )
+    {
+      cl_qlist_insert_tail( p_list,
+                           (cl_list_item_t*)&p_pr_item->pool_item );
+      ++path_num;
+    }
+
+    if ( ++src_lid_ho > src_lid_max_ho )
+      break;
+
+    if ( ++dest_lid_ho > dest_lid_max_ho )
+      break;
+  }
+
+  /*
+    Check if we've accumulated all the paths that the user cares to see
+  */
+  if ( path_num == rem_paths )
+    goto Exit;
+
+  /*
+    Don't bother reporting preference 1 paths for now.
+    It's more trouble than it's worth and can only occur
+    if ports have different LMC values, which isn't supported
+    by OpenSM right now anyway.
+  */
+  preference = 2;
+  src_lid_ho = src_lid_min_ho;
+  dest_lid_ho = dest_lid_min_ho;
+  src_offset = 0;
+  dest_offset = 0;
+
+  /*
+    Iterate over the remaining paths
+  */
+  while ( path_num < rem_paths )
+  {
+    dest_offset++;
+    dest_lid_ho++;
+
+    if ( dest_lid_ho > dest_lid_max_ho )
+    {
+      src_offset++;
+      src_lid_ho++;
+
+      if ( src_lid_ho > src_lid_max_ho )
+        break; /* done */
+
+      dest_offset = 0;
+      dest_lid_ho = dest_lid_min_ho;
+    }
+
+    /*
+      These paths are "fully non-redundant" with paths already
+      identified above and consequently not of much value.
+
+      Don't return paths we already identified above, as indicated
+      by the offset values being equal.
+    */
+    if ( src_offset == dest_offset )
+      continue;        /* already reported */
+
+    p_pr_item = __osm_mpr_rcv_get_lid_pair_path( p_rcv, p_mpr,
+                                                p_src_port, p_dest_port,
+                                                 src_lid_ho, dest_lid_ho,
+                                                comp_mask, preference );
+
+    if ( p_pr_item )
+    {
+      cl_qlist_insert_tail( p_list,
+                           (cl_list_item_t*)&p_pr_item->pool_item );
+      ++path_num;
+    }
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return path_num;
+}
+
+#undef min
+#define min(x,y)       (((x) < (y)) ? (x) : (y))
+
+/**********************************************************************
+ **********************************************************************/
+static osm_mpr_item_t*
+__osm_mpr_rcv_get_apm_port_pair_paths(
+  IN osm_mpr_rcv_t*            const p_rcv,
+  IN const ib_multipath_rec_t* const p_mpr,
+  IN const osm_port_t*         const p_src_port,
+  IN const osm_port_t*         const p_dest_port,
+  IN int                       base_offs,
+  IN const ib_net64_t          comp_mask,
+  IN cl_qlist_t*               const p_list )
+{
+  osm_mpr_item_t*              p_pr_item = 0;
+  uint16_t                     src_lid_min_ho;
+  uint16_t                     src_lid_max_ho;
+  uint16_t                     dest_lid_min_ho;
+  uint16_t                     dest_lid_max_ho;
+  uint16_t                     src_lid_ho;
+  uint16_t                     dest_lid_ho;
+  uintn_t                      iterations;
+  int                          src_lids, dest_lids;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_get_apm_port_pair_paths );
+  if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+            "__osm_mpr_rcv_get_apm_port_pair_paths: "
+            "Src port 0x%016" PRIx64 ", "
+            "Dst port 0x%016" PRIx64 ", base offs %d\n",
+            cl_ntoh64( osm_port_get_guid( p_src_port ) ),
+            cl_ntoh64( osm_port_get_guid( p_dest_port ) ),
+            base_offs );
+  }
+
+  osm_port_get_lid_range_ho( p_src_port, &src_lid_min_ho, &src_lid_max_ho );
+  osm_port_get_lid_range_ho( p_dest_port, &dest_lid_min_ho, &dest_lid_max_ho );
+
+  src_lid_ho = src_lid_min_ho;
+  dest_lid_ho = dest_lid_min_ho;
+
+  src_lids = src_lid_max_ho - src_lid_min_ho + 1;
+  dest_lids = dest_lid_max_ho - dest_lid_min_ho + 1;
+
+  src_lid_ho += base_offs % src_lids;
+  dest_lid_ho += base_offs % dest_lids;
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+         "__osm_mpr_rcv_get_apm_port_pair_paths: "
+         "Src LIDs [0x%X-0x%X] hashed %d, "
+         "Dest LIDs [0x%X-0x%X] hashed %d\n",
+         src_lid_min_ho, src_lid_max_ho, src_lid_ho,
+         dest_lid_min_ho, dest_lid_max_ho, dest_lid_ho );
+
+  iterations = min( src_lids, dest_lids );
+
+  while ( iterations-- )
+  {
+    /*
+      These paths are "fully redundant"
+    */
+    p_pr_item = __osm_mpr_rcv_get_lid_pair_path( p_rcv, p_mpr,
+                                                p_src_port, p_dest_port,
+                                                src_lid_ho, dest_lid_ho,
+                                                comp_mask, 0 );
+
+    if ( p_pr_item )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+              "__osm_mpr_rcv_get_apm_port_pair_paths: "
+              "Found matching path from Src LID 0x%X to Dest LID 0x%X with %d hops\n",
+              src_lid_ho, dest_lid_ho, p_pr_item->hops);
+      break;
+    }
+
+    if ( ++src_lid_ho > src_lid_max_ho )
+      src_lid_ho = src_lid_min_ho;
+
+    if ( ++dest_lid_ho > dest_lid_max_ho )
+      dest_lid_ho = dest_lid_min_ho;
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return p_pr_item;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_net16_t
+__osm_mpr_rcv_get_gids(
+  IN osm_mpr_rcv_t*    const p_rcv,
+  IN const ib_gid_t *  gids,
+  IN int               ngids,
+  IN int                is_sgid,
+  OUT osm_port_t**     pp_port )
+{
+  osm_port_t           *p_port;
+  ib_net16_t            ib_status = IB_SUCCESS;
+  int                   i;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_get_gids );
+
+  for ( i = 0; i < ngids; i++, gids++ ) {
+    if ( !ib_gid_is_link_local ( gids ) ) {
+      if ( ( is_sgid && ib_gid_is_multicast( gids ) ) || 
+           ( ib_gid_get_subnet_prefix ( gids ) != p_rcv->p_subn->opt.subnet_prefix ) ) {
+        /*
+          This 'error' is the client's fault (bad gid) so
+          don't enter it as an error in our own log.
+          Return an error response to the client.
+        */
+        osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+                 "__osm_mpr_rcv_get_gids: ERR 451B: "
+                 "Non local %sGID subnet prefix 0x%016" PRIx64 "\n",
+                 is_sgid ? "S" : "D",
+                 cl_ntoh64( gids->unicast.prefix ) );
+
+        ib_status = IB_SA_MAD_STATUS_INVALID_GID;
+        goto Exit;
+      }
+    }
+
+    p_port = (osm_port_t *)cl_qmap_get( &p_rcv->p_subn->port_guid_tbl,
+                                        gids->unicast.interface_id );
+    if ( !p_port ||
+         p_port == (osm_port_t *)cl_qmap_end( &p_rcv->p_subn->port_guid_tbl ) ) {
+      /*
+        This 'error' is the client's fault (bad gid) so
+        don't enter it as an error in our own log.
+        Return an error response to the client.
+      */
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+              "__osm_mpr_rcv_get_gids: ERR 4506: "
+              "No port with GUID 0x%016" PRIx64 "\n",
+              cl_ntoh64( gids->unicast.interface_id ) );
+
+      ib_status = IB_SA_MAD_STATUS_INVALID_GID;
+      goto Exit;
+    }
+
+    pp_port[i] = p_port;
+  }
+
+ Exit:
+  OSM_LOG_EXIT(p_rcv->p_log);
+
+  return ib_status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_net16_t
+__osm_mpr_rcv_get_end_points(
+  IN osm_mpr_rcv_t*    const p_rcv,
+  IN const osm_madw_t* const p_madw,
+  OUT osm_port_t **    pp_ports,
+  OUT int *            nsrc,
+  OUT int *            ndest )
+{
+  const ib_multipath_rec_t*    p_mpr;
+  const ib_sa_mad_t*           p_sa_mad;
+  ib_net64_t                   comp_mask;
+  ib_net16_t                   sa_status = IB_SA_MAD_STATUS_SUCCESS;
+  ib_gid_t *                   gids;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_get_end_points );
+
+  /*
+    Determine what fields are valid and then get a pointer
+    to the source and destination port objects, if possible.
+  */
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_mpr = (ib_multipath_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+  gids = (ib_gid_t *)p_mpr->gids;
+
+  comp_mask = p_sa_mad->comp_mask;
+
+  /*
+    Check a few easy disqualifying cases up front before getting
+    into the endpoints.
+  */
+  *nsrc = *ndest = 0;
+
+  if ( comp_mask & IB_MPR_COMPMASK_SGIDCOUNT ) {
+    *nsrc = p_mpr->sgid_count;
+    if ( *nsrc > IB_MULTIPATH_MAX_GIDS )
+      *nsrc = IB_MULTIPATH_MAX_GIDS;
+    sa_status = __osm_mpr_rcv_get_gids( p_rcv, gids, *nsrc, 1, pp_ports );
+    if ( sa_status != IB_SUCCESS )
+      goto Exit;
+  }
+
+  if ( comp_mask & IB_MPR_COMPMASK_DGIDCOUNT ) {
+    *ndest = p_mpr->dgid_count;
+    if ( *ndest + *nsrc > IB_MULTIPATH_MAX_GIDS )
+      *ndest = IB_MULTIPATH_MAX_GIDS - *nsrc;
+    sa_status = __osm_mpr_rcv_get_gids( p_rcv, gids + *nsrc, *ndest, 0,
+                                       pp_ports + *nsrc );
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( sa_status );
+}
+
+#define __hash_lids(a, b, lmc) \
+       (((((a) >> (lmc)) << 4) | ((b) >> (lmc))) % 103)
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mpr_rcv_get_apm_paths(
+  IN osm_mpr_rcv_t*            const p_rcv,
+  IN const ib_multipath_rec_t* const p_mpr,
+  IN const osm_port_t*         const p_req_port,
+  IN osm_port_t **             _pp_ports,
+  IN const ib_net64_t          comp_mask,
+  IN cl_qlist_t*               const p_list )
+{
+  osm_port_t *pp_ports[4];
+  osm_mpr_item_t *matrix[2][2];
+  int base_offs, src_lid_ho, dest_lid_ho;
+  int sumA, sumB, minA, minB;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_get_apm_paths );
+
+  /*
+   * We want to:
+   *   1. use different lid offsets (from base) for the resultant paths
+   *   to increase the probability of redundant paths or in case
+   *   of Clos - to ensure it (different offset => different spine!)
+   *   2. keep consistent paths no matter of direction and order of ports
+   *   3. distibute the lid offsets to balance the load
+   * So, we sort the ports (within the srcs, and within the dests),
+   * hash the lids of S0, D0 (after the sort), and call __osm_mpr_rcv_get_apm_port_pair_paths
+   * with base_lid for S0, D0 and base_lid + 1 for S1, D1. This way we will get
+   * always the same offsets - order indepentent, and make sure different spines are used.
+   * Note that the diagonals on a Clos have the same number of hops, so it doesn't
+   * really matter which diagonal we use.
+   */
+  if ( _pp_ports[0]->guid < _pp_ports[1]->guid ) {
+    pp_ports[0] = _pp_ports[0];
+    pp_ports[1] = _pp_ports[1];
+  }
+  else
+  {
+    pp_ports[0] = _pp_ports[1];
+    pp_ports[1] = _pp_ports[0];
+  }
+  if ( _pp_ports[2]->guid < _pp_ports[3]->guid ) {
+    pp_ports[2] = _pp_ports[2];
+    pp_ports[3] = _pp_ports[3];
+  }
+  else
+  {
+    pp_ports[2] = _pp_ports[3];
+    pp_ports[3] = _pp_ports[2];
+  }
+
+  src_lid_ho = osm_port_get_base_lid( pp_ports[0] );
+  dest_lid_ho = osm_port_get_base_lid( pp_ports[2] );
+
+  base_offs = src_lid_ho < dest_lid_ho ?
+             __hash_lids( src_lid_ho, dest_lid_ho, p_rcv->p_subn->opt.lmc ) :
+             __hash_lids( dest_lid_ho, src_lid_ho, p_rcv->p_subn->opt.lmc );
+
+  matrix[0][0] = __osm_mpr_rcv_get_apm_port_pair_paths( p_rcv, p_mpr, pp_ports[0],
+                                                       pp_ports[2], base_offs, comp_mask , p_list );
+  matrix[0][1] = __osm_mpr_rcv_get_apm_port_pair_paths( p_rcv, p_mpr, pp_ports[0],
+                                                       pp_ports[3], base_offs, comp_mask, p_list );
+  matrix[1][0] = __osm_mpr_rcv_get_apm_port_pair_paths( p_rcv, p_mpr, pp_ports[1],
+                                                       pp_ports[2], base_offs+1, comp_mask, p_list );
+  matrix[1][1] = __osm_mpr_rcv_get_apm_port_pair_paths( p_rcv, p_mpr, pp_ports[1],
+                                                       pp_ports[3], base_offs+1, comp_mask, p_list );
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG, "__osm_mpr_rcv_get_apm_paths: "
+          "APM matrix:\n"
+          "\t{0,0} 0x%X->0x%X (%d)\t| {0,1} 0x%X->0x%X (%d)\n"
+          "\t{1,0} 0x%X->0x%X (%d)\t| {1,1} 0x%X->0x%X (%d)\n",
+          matrix[0][0]->path_rec.slid, matrix[0][0]->path_rec.dlid, matrix[0][0]->hops,
+          matrix[0][1]->path_rec.slid, matrix[0][1]->path_rec.dlid, matrix[0][1]->hops,
+          matrix[1][0]->path_rec.slid, matrix[1][0]->path_rec.dlid, matrix[1][0]->hops,
+          matrix[1][1]->path_rec.slid, matrix[1][1]->path_rec.dlid, matrix[1][1]->hops );
+
+  /* check diagonal A {(0,0), (1,1)} */
+  sumA = matrix[0][0]->hops + matrix[1][1]->hops;
+  minA = min( matrix[0][0]->hops, matrix[1][1]->hops );
+
+  /* check diagonal B {(0,1), (1,0)} */
+  sumB = matrix[0][1]->hops + matrix[1][0]->hops;
+  minB = min( matrix[0][1]->hops, matrix[1][0]->hops );
+
+  /* and the winner is... */
+  if ( minA <= minB || ( minA == minB && sumA < sumB ) ) {
+    /* Diag A */
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG, "__osm_mpr_rcv_get_apm_paths: "
+            "Diag {0,0} & {1,1} is the best:\n"
+            "\t{0,0} 0x%X->0x%X (%d)\t & {1,1} 0x%X->0x%X (%d)\n",
+            matrix[0][0]->path_rec.slid, matrix[0][0]->path_rec.dlid, matrix[0][0]->hops,
+            matrix[1][1]->path_rec.slid, matrix[1][1]->path_rec.dlid, matrix[1][1]->hops );
+    cl_qlist_insert_tail( p_list,
+                        (cl_list_item_t*)&matrix[0][0]->pool_item );
+    cl_qlist_insert_tail( p_list,
+                        (cl_list_item_t*)&matrix[1][1]->pool_item );
+    cl_qlock_pool_put( &p_rcv->pr_pool, &matrix[0][1]->pool_item );
+    cl_qlock_pool_put( &p_rcv->pr_pool, &matrix[1][0]->pool_item );
+  }
+  else
+  {
+    /* Diag B */
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG, "__osm_mpr_rcv_get_apm_paths: "
+            "Diag {0,1} & {1,0} is the best:\n"
+            "\t{0,1} 0x%X->0x%X (%d)\t & {1,0} 0x%X->0x%X (%d)\n",
+            matrix[0][1]->path_rec.slid, matrix[0][1]->path_rec.dlid, matrix[0][1]->hops,
+            matrix[1][0]->path_rec.slid, matrix[1][0]->path_rec.dlid, matrix[1][0]->hops );
+    cl_qlist_insert_tail( p_list,
+                        (cl_list_item_t*)&matrix[0][1]->pool_item );
+    cl_qlist_insert_tail( p_list,
+                        (cl_list_item_t*)&matrix[1][0]->pool_item );
+    cl_qlock_pool_put( &p_rcv->pr_pool, &matrix[0][0]->pool_item );
+    cl_qlock_pool_put( &p_rcv->pr_pool, &matrix[1][1]->pool_item );
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mpr_rcv_process_pairs(
+  IN osm_mpr_rcv_t*            const p_rcv,
+  IN const ib_multipath_rec_t* const p_mpr,
+  IN osm_port_t*               const p_req_port,
+  IN osm_port_t **             pp_ports,
+  IN const int                 nsrc,
+  IN const int                 ndest,
+  IN const ib_net64_t          comp_mask,
+  IN cl_qlist_t*               const p_list )
+{
+  osm_port_t **pp_src_port, **pp_es;
+  osm_port_t **pp_dest_port, **pp_ed;
+  uint32_t max_paths, num_paths, total_paths = 0;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_process_pairs );
+
+  if ( comp_mask & IB_MPR_COMPMASK_NUMBPATH )
+    max_paths = p_mpr->num_path & 0x7F;
+  else
+    max_paths = OSM_SA_MPR_MAX_NUM_PATH;
+
+  for ( pp_src_port = pp_ports, pp_es = pp_ports + nsrc; pp_src_port < pp_es; pp_src_port++ )
+  {
+    for ( pp_dest_port = pp_es, pp_ed = pp_es + ndest; pp_dest_port < pp_ed; pp_dest_port++ )
+    {
+      num_paths = __osm_mpr_rcv_get_port_pair_paths( p_rcv, p_mpr, p_req_port,
+                                                    *pp_src_port, *pp_dest_port,
+                                                     max_paths - total_paths,
+                                                    comp_mask, p_list );
+      total_paths += num_paths;
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+               "__osm_mpr_rcv_process_pairs: "
+               "%d paths %d total paths %d max paths\n",
+               num_paths, total_paths, max_paths );
+      /* Just take first NumbPaths found */
+      if (total_paths >= max_paths)
+        goto Exit;
+    }
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mpr_rcv_respond(
+  IN osm_mpr_rcv_t*            const p_rcv,
+  IN const osm_madw_t*         const p_madw,
+  IN cl_qlist_t*               const p_list )
+{
+  osm_madw_t*                  p_resp_madw;
+  const ib_sa_mad_t*           p_sa_mad;
+  ib_sa_mad_t*                 p_resp_sa_mad;
+  size_t                       num_rec;
+  size_t                       mad_size;
+  ib_path_rec_t*               p_resp_pr;
+  ib_multipath_rec_t*          p_mpr;
+  ib_api_status_t              status;
+  osm_mpr_item_t*              p_mpr_item;
+  uint32_t                     i;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_respond );
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_mpr = (ib_multipath_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+  num_rec = cl_qlist_count( p_list );
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+          "__osm_mpr_rcv_respond: "
+          "Generating response with %zu records\n", num_rec );
+
+  mad_size =  IB_SA_MAD_HDR_SIZE + num_rec * sizeof(ib_path_rec_t);
+
+  /*
+    Get a MAD to reply. Address of Mad is in the received mad_wrapper
+  */
+  p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, p_madw->h_bind,
+                                 mad_size, &p_madw->mad_addr );
+
+  if ( !p_resp_madw )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+            "__osm_mpr_rcv_respond: "
+            "ERR 4502: Unable to allocate MAD\n" );
+
+    for ( i = 0; i < num_rec; i++ )
+    {
+      p_mpr_item = (osm_mpr_item_t*)cl_qlist_remove_head( p_list );
+      cl_qlock_pool_put( &p_rcv->pr_pool, &p_mpr_item->pool_item );
+    }
+
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES );
+    goto Exit;
+  }
+
+  p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+  memcpy( p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+  /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
+  p_resp_sa_mad->sm_key = 0;
+
+  /*
+    o15-0.2.7: If MultiPath is supported, then SA shall respond to a
+    SubnAdmGetMulti() containing a valid MultiPathRecord attribute with
+    a set of zero or more PathRecords satisfying the constraints indicated
+    in the MultiPathRecord received. The PathRecord Attribute ID shall be
+    used in the response.
+  */
+  p_resp_sa_mad->attr_id = IB_MAD_ATTR_PATH_RECORD;
+  p_resp_sa_mad->attr_offset = ib_get_attr_offset( sizeof(ib_path_rec_t) );
+
+  p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+
+  p_resp_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+  for ( i = 0; i < num_rec; i++ )
+  {
+    p_mpr_item = (osm_mpr_item_t*)cl_qlist_remove_head( p_list );
+
+    /* Copy the Path Records from the list into the MAD */
+    *p_resp_pr = p_mpr_item->path_rec;
+
+    cl_qlock_pool_put( &p_rcv->pr_pool, &p_mpr_item->pool_item );
+    p_resp_pr++;
+  }
+
+  CL_ASSERT( cl_is_qlist_empty( p_list ) );
+
+  osm_dump_sa_mad( p_rcv->p_log, p_resp_sa_mad, OSM_LOG_FRAMES );
+
+  status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+
+  if ( status != IB_SUCCESS )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+            "__osm_mpr_rcv_respond: ERR 4507: "
+            "Unable to send MAD (%s)\n", ib_get_err_str( status ) );
+    /*  osm_mad_pool_put( p_rcv->p_mad_pool, p_resp_madw ); */
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mpr_rcv_process(
+  IN osm_mpr_rcv_t*            const p_rcv,
+  IN osm_madw_t*               const p_madw )
+{
+  const ib_multipath_rec_t*    p_mpr;
+  const ib_sa_mad_t*           p_sa_mad;
+  osm_port_t*                  requester_port;
+  osm_port_t*                  pp_ports[IB_MULTIPATH_MAX_GIDS];
+  cl_qlist_t                   pr_list;
+  ib_net16_t                   sa_status;
+  int                          nsrc, ndest;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_mpr_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_mpr = (ib_multipath_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+  CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_MULTIPATH_RECORD );
+
+  if ( ( p_sa_mad->rmpp_flags & IB_RMPP_FLAG_ACTIVE ) != IB_RMPP_FLAG_ACTIVE )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_mpr_rcv_process: ERR 4510: "
+             "Invalid request since RMPP_FLAG_ACTIVE is not set\n" );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID );
+    goto Exit;
+  }
+
+  /* we only support SubnAdmGetMulti method */
+  if ( p_sa_mad->method != IB_MAD_METHOD_GETMULTI ) {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+            "osm_mpr_rcv_process: ERR 4513: "
+            "Unsupported Method (%s)\n",
+            ib_get_sa_method_str( p_sa_mad->method ) );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+    goto Exit;
+  }
+
+  /* update the requester physical port. */
+  requester_port = osm_get_port_by_mad_addr( p_rcv->p_log,  p_rcv->p_subn,
+                                             osm_madw_get_mad_addr_ptr( p_madw ) );
+  if ( requester_port == NULL )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_mpr_rcv_process: ERR 4517: "
+             "Cannot find requester physical port\n" );
+    goto Exit;
+  }
+
+  if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+    osm_dump_multipath_record( p_rcv->p_log, p_mpr, OSM_LOG_DEBUG );
+
+  cl_qlist_init( &pr_list ); 
+
+  /*
+    Most SA functions (including this one) are read-only on the
+    subnet object, so we grab the lock non-exclusively.
+   */
+  cl_plock_acquire( p_rcv->p_lock );
+
+  sa_status = __osm_mpr_rcv_get_end_points( p_rcv, p_madw, pp_ports,
+                                            &nsrc, &ndest );
+    
+  if ( sa_status != IB_SA_MAD_STATUS_SUCCESS || !nsrc || !ndest )
+  {
+    if ( sa_status == IB_SA_MAD_STATUS_SUCCESS && ( !nsrc || !ndest ) )
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_mpr_rcv_process_cb: ERR 4512: "
+               "__osm_mpr_rcv_get_end_points failed, not enough GIDs "
+               "(nsrc %d ndest %d)\n",
+               nsrc, ndest);
+    cl_plock_release( p_rcv->p_lock );
+    if ( sa_status == IB_SA_MAD_STATUS_SUCCESS )
+      osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID );
+    else
+      osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+    goto Exit;
+  }
+
+  /* APM request */
+  if ( nsrc == 2 && ndest == 2 && ( p_mpr->num_path & 0x7F ) == 2 )
+    __osm_mpr_rcv_get_apm_paths( p_rcv, p_mpr, requester_port, pp_ports,
+                                p_sa_mad->comp_mask, &pr_list );
+  else
+    __osm_mpr_rcv_process_pairs( p_rcv, p_mpr, requester_port, pp_ports,
+                                nsrc, ndest,
+                                p_sa_mad->comp_mask, &pr_list );
+
+  cl_plock_release( p_rcv->p_lock );
+  __osm_mpr_rcv_respond( p_rcv, p_madw, &pr_list );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+#endif
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_multipath_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_multipath_record_ctrl.c
new file mode 100644 (file)
index 0000000..6a30be9
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_mpr_rcv_ctrl_t.
+ * This object represents the MultiPathRecord request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ */
+
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_multipath_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mpr_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_mpr_rcv_process( ((osm_mpr_rcv_ctrl_t*)context)->p_rcv,
+                      (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mpr_rcv_ctrl_construct(
+  IN osm_mpr_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mpr_rcv_ctrl_destroy(
+  IN osm_mpr_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mpr_rcv_ctrl_init(
+  IN osm_mpr_rcv_ctrl_t* const p_ctrl,
+  IN osm_mpr_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_mpr_rcv_ctrl_init );
+
+  osm_mpr_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_MULTIPATH_RECORD,
+    __osm_mpr_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_mpr_rcv_ctrl_init: ERR 4B01: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+#endif
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_node_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_node_record.c
new file mode 100644 (file)
index 0000000..1d78ee8
--- /dev/null
@@ -0,0 +1,600 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_node_record.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_nr_rcv_t.
+ * This object represents the NodeInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.8 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_node_record.h>
+#include <opensm/osm_node.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_NR_RCV_POOL_MIN_SIZE    32
+#define OSM_NR_RCV_POOL_GROW_SIZE   32
+
+typedef  struct _osm_nr_item
+{
+  cl_pool_item_t           pool_item;
+  ib_node_record_t         rec;
+} osm_nr_item_t;
+
+typedef  struct _osm_nr_search_ctxt
+{
+  const ib_node_record_t*     p_rcvd_rec;
+  ib_net64_t               comp_mask;
+  cl_qlist_t*              p_list;
+  osm_nr_rcv_t*            p_rcv;
+  const osm_physp_t*       p_req_physp;
+} osm_nr_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nr_rcv_construct(
+  IN osm_nr_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+  cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nr_rcv_destroy(
+  IN osm_nr_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_nr_rcv_destroy );
+  cl_qlock_pool_destroy( &p_rcv->pool );
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_nr_rcv_init(
+  IN osm_nr_rcv_t*         const p_rcv,
+  IN osm_sa_resp_t*        const p_resp,
+  IN osm_mad_pool_t*       const p_mad_pool,
+  IN const osm_subn_t*     const p_subn,
+  IN osm_log_t*            const p_log,
+  IN cl_plock_t*           const p_lock )
+{
+  ib_api_status_t          status;
+
+  OSM_LOG_ENTER( p_log, osm_nr_rcv_init );
+
+  osm_nr_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_resp = p_resp;
+  p_rcv->p_mad_pool = p_mad_pool;
+
+  status = cl_qlock_pool_init( &p_rcv->pool,
+                               OSM_NR_RCV_POOL_MIN_SIZE,
+                               0,
+                               OSM_NR_RCV_POOL_GROW_SIZE,
+                               sizeof(osm_nr_item_t),
+                               NULL, NULL, NULL );
+
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_nr_rcv_new_nr(
+  IN osm_nr_rcv_t*         const p_rcv,
+  IN const osm_node_t*     const p_node,
+  IN cl_qlist_t*           const p_list,
+  IN ib_net64_t            const port_guid,
+  IN ib_net16_t            const lid )
+{
+  osm_nr_item_t*           p_rec_item;
+  ib_api_status_t          status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_nr_rcv_new_nr );
+
+  p_rec_item = (osm_nr_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+  if( p_rec_item == NULL )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_nr_rcv_new_nr: ERR 1D02: "
+             "cl_qlock_pool_get failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_nr_rcv_new_nr: "
+             "New NodeRecord: node 0x%016" PRIx64
+             "\n\t\t\t\tport 0x%016" PRIx64 ", lid 0x%X\n",
+             cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+             cl_ntoh64( port_guid ), cl_ntoh16( lid )
+             );
+  }
+
+  memset( &p_rec_item->rec, 0, sizeof(ib_node_record_t) );
+
+  p_rec_item->rec.lid = lid;
+
+  p_rec_item->rec.node_info = p_node->node_info;
+  p_rec_item->rec.node_info.port_guid = port_guid;
+  memcpy(&(p_rec_item->rec.node_desc), &(p_node->node_desc),
+         IB_NODE_DESCRIPTION_SIZE);
+  cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_nr_rcv_create_nr(
+  IN osm_nr_rcv_t*         const p_rcv,
+  IN const osm_node_t*     const p_node,
+  IN cl_qlist_t*           const p_list,
+  IN ib_net64_t            const match_port_guid,
+  IN ib_net16_t            const match_lid,
+  IN const osm_physp_t*    const p_req_physp )
+{
+  const osm_physp_t*       p_physp;
+  uint8_t                  port_num;
+  uint8_t                  num_ports;
+  uint16_t                 match_lid_ho;
+  ib_net16_t               base_lid;
+  ib_net16_t               base_lid_ho;
+  ib_net16_t               max_lid_ho;
+  uint8_t                  lmc;
+  ib_net64_t               port_guid;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_nr_rcv_create_nr );
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_nr_rcv_create_nr: "
+             "Looking for NodeRecord with LID: 0x%X GUID:0x%016" PRIx64 "\n",
+             cl_ntoh16( match_lid ),
+             cl_ntoh64( match_port_guid )
+             );
+  }
+
+  /*
+    For switches, do not return the NodeInfo record
+    for each port on the switch, just for port 0.
+  */
+  if( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH )
+    num_ports = 1;
+  else
+    num_ports = osm_node_get_num_physp( p_node );
+
+  for( port_num = 0; port_num < num_ports; port_num++ )
+  {
+    p_physp = osm_node_get_physp_ptr( p_node, port_num );
+
+    if( !osm_physp_is_valid( p_physp ) )
+      continue;
+
+    /* Check to see if the found p_physp and the requester physp
+       share a pkey. If not - continue */
+    if (!osm_physp_share_pkey( p_rcv->p_log, p_physp, p_req_physp ) )
+      continue;
+
+    port_guid = osm_physp_get_port_guid( p_physp );
+
+    if( match_port_guid && ( port_guid != match_port_guid ) )
+      continue;
+
+    base_lid = osm_physp_get_base_lid( p_physp );
+    base_lid_ho = cl_ntoh16( base_lid );
+    lmc = osm_physp_get_lmc( p_physp );
+    max_lid_ho = (uint16_t)( base_lid_ho + (1 << lmc) - 1 );
+    match_lid_ho = cl_ntoh16( match_lid );
+
+    if( match_lid_ho )
+    {
+      /*
+        We validate that the lid belongs to this node.
+      */
+      if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+                 "__osm_nr_rcv_create_nr: "
+                 "Comparing LID: 0x%X <= 0x%X <= 0x%X\n",
+                 base_lid_ho, match_lid_ho, max_lid_ho
+                 );
+      }
+
+      if ( match_lid_ho < base_lid_ho || match_lid_ho > max_lid_ho )
+        continue;
+    }
+
+    __osm_nr_rcv_new_nr( p_rcv, p_node, p_list, port_guid, base_lid );
+
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_nr_rcv_by_comp_mask(
+  IN cl_map_item_t*        const p_map_item,
+  IN void*                 context )
+{
+  const osm_nr_search_ctxt_t* const p_ctxt = (osm_nr_search_ctxt_t *)context;
+  const osm_node_t*        const p_node = (osm_node_t*)p_map_item;
+  const ib_node_record_t*  const p_rcvd_rec = p_ctxt->p_rcvd_rec;
+  const osm_physp_t*       const p_req_physp = p_ctxt->p_req_physp;
+  osm_nr_rcv_t*            const p_rcv = p_ctxt->p_rcv;
+  ib_net64_t               const comp_mask = p_ctxt->comp_mask;
+  ib_net64_t               match_port_guid = 0;
+  ib_net16_t               match_lid = 0;
+
+  OSM_LOG_ENTER( p_ctxt->p_rcv->p_log, __osm_nr_rcv_by_comp_mask );
+
+  osm_dump_node_info(
+    p_ctxt->p_rcv->p_log,
+    &p_node->node_info,
+    OSM_LOG_VERBOSE );    
+
+  if( comp_mask & IB_NR_COMPMASK_LID )
+    match_lid = p_rcvd_rec->lid;
+
+  if( comp_mask & IB_NR_COMPMASK_NODEGUID)
+  {
+    /*
+      DEBUG TOP
+    */
+    if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+               "__osm_nr_rcv_by_comp_mask: "
+               "Looking for node 0x%016" PRIx64
+               ", found 0x%016" PRIx64 "\n",
+               cl_ntoh64( p_rcvd_rec->node_info.node_guid ),
+               cl_ntoh64( osm_node_get_node_guid( p_node ) )
+               );
+    }
+    /*
+      DEBUG BOTTOM
+    */
+    if( (p_node->node_info.node_guid != p_rcvd_rec->node_info.node_guid) )
+      goto Exit;
+  }
+  if( comp_mask & IB_NR_COMPMASK_PORTGUID )
+  {
+    match_port_guid = p_rcvd_rec->node_info.port_guid;
+  }
+  if( comp_mask & IB_NR_COMPMASK_SYSIMAGEGUID )
+  {
+    if( (p_node->node_info.sys_guid != p_rcvd_rec->node_info.sys_guid) )
+      goto Exit;
+  }
+  if( comp_mask & IB_NR_COMPMASK_BASEVERSION )
+  {
+    if( (p_node->node_info.base_version != p_rcvd_rec->node_info.base_version) )
+      goto Exit;
+  }
+  if( comp_mask & IB_NR_COMPMASK_CLASSVERSION )
+  {
+    if( (p_node->node_info.class_version != p_rcvd_rec->node_info.class_version) )
+      goto Exit;
+  }
+  if( comp_mask & IB_NR_COMPMASK_NODETYPE )
+  {
+    if( (p_node->node_info.node_type != p_rcvd_rec->node_info.node_type) )
+      goto Exit;
+  }
+  if( comp_mask & IB_NR_COMPMASK_NUMPORTS )
+  {
+    if( (p_node->node_info.num_ports != p_rcvd_rec->node_info.num_ports) )
+      goto Exit;
+  }
+  if( comp_mask & IB_NR_COMPMASK_PARTCAP )
+  {
+    if( (p_node->node_info.partition_cap != p_rcvd_rec->node_info.partition_cap) )
+      goto Exit;
+  }
+  if( comp_mask & IB_NR_COMPMASK_DEVID )
+  {
+    if( (p_node->node_info.device_id != p_rcvd_rec->node_info.device_id) )
+      goto Exit;
+  }
+  if( comp_mask & IB_NR_COMPMASK_REV )
+  {
+    if( (p_node->node_info.revision != p_rcvd_rec->node_info.revision) )
+      goto Exit;
+  }
+  if( comp_mask & IB_NR_COMPMASK_PORTNUM )
+  {
+    if( ib_node_info_get_local_port_num(&p_node->node_info) !=
+        ib_node_info_get_local_port_num(&p_rcvd_rec->node_info) )
+      goto Exit;
+  }
+  if( comp_mask & IB_NR_COMPMASK_VENDID )
+  {
+    if( ib_node_info_get_vendor_id(&p_node->node_info) !=
+        ib_node_info_get_vendor_id(&p_rcvd_rec->node_info) )
+      goto Exit;
+  }
+  if( comp_mask & IB_NR_COMPMASK_NODEDESC )
+  {
+    if( strncmp((char*) &p_node->node_desc,
+                (char*) &p_rcvd_rec->node_desc, sizeof(ib_node_desc_t)) )
+      goto Exit;
+  }
+
+  __osm_nr_rcv_create_nr( p_rcv, p_node, p_ctxt->p_list,
+                          match_port_guid, match_lid, p_req_physp );
+
+ Exit:
+  OSM_LOG_EXIT( p_ctxt->p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nr_rcv_process(
+  IN osm_nr_rcv_t*         const p_rcv,
+  IN const osm_madw_t*     const p_madw )
+{
+  const ib_sa_mad_t*       p_rcvd_mad;
+  const ib_node_record_t*  p_rcvd_rec;
+  ib_node_record_t*        p_resp_rec;
+  cl_qlist_t               rec_list;
+  osm_madw_t*              p_resp_madw;
+  ib_sa_mad_t*             p_resp_sa_mad;
+  uint32_t                 num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  uint32_t                trim_num_rec;
+#endif
+  uint32_t                 i;
+  osm_nr_search_ctxt_t     context;
+  osm_nr_item_t*           p_rec_item;
+  ib_api_status_t          status;
+  osm_physp_t*             p_req_physp;
+
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_nr_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_rcvd_rec = (ib_node_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+
+  CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_NODE_RECORD );
+
+  /* we only support SubnAdmGet and SubnAdmGetTable methods */
+  if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) &&
+       (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) ) {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_nr_rcv_process: ERR 1D05: "
+             "Unsupported Method (%s)\n",
+             ib_get_sa_method_str( p_rcvd_mad->method ) );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+    goto Exit;
+  }
+
+  /* update the requester physical port. */
+  p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+                                          p_rcv->p_subn,
+                                          osm_madw_get_mad_addr_ptr(p_madw) );
+  if (p_req_physp == NULL)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_nr_rcv_process: ERR 1D04: "
+             "Cannot find requester physical port\n" );
+    goto Exit;
+  }
+
+  if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+    osm_dump_node_record( p_rcv->p_log, p_rcvd_rec, OSM_LOG_DEBUG );
+
+  cl_qlist_init( &rec_list );
+
+  context.p_rcvd_rec    = p_rcvd_rec;
+  context.p_list        = &rec_list;
+  context.comp_mask     = p_rcvd_mad->comp_mask;
+  context.p_rcv         = p_rcv;
+  context.p_req_physp   = p_req_physp;
+
+  cl_plock_acquire( p_rcv->p_lock );
+
+  cl_qmap_apply_func( &p_rcv->p_subn->node_guid_tbl,
+                      __osm_nr_rcv_by_comp_mask,
+                      &context );
+
+  cl_plock_release( p_rcv->p_lock );
+
+  num_rec = cl_qlist_count( &rec_list );
+
+  /*
+   * C15-0.1.30:
+   * If we do a SubnAdmGet and got more than one record it is an error !
+   */
+  if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec > 1) ) {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_nr_rcv_process: ERR 1D03: "
+             "Got more than one record for SubnAdmGet (%u)\n",
+             num_rec );
+    osm_sa_send_error( p_rcv->p_resp, p_madw,
+                       IB_SA_MAD_STATUS_TOO_MANY_RECORDS );
+
+    /* need to set the mem free ... */
+    p_rec_item = (osm_nr_item_t*)cl_qlist_remove_head( &rec_list );
+    while( p_rec_item != (osm_nr_item_t*)cl_qlist_end( &rec_list ) )
+    {
+      cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+      p_rec_item = (osm_nr_item_t*)cl_qlist_remove_head( &rec_list );
+    }
+
+    goto Exit;
+  }
+
+  pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  /* we limit the number of records to a single packet */
+  trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_node_record_t);
+  if (trim_num_rec < num_rec)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "osm_nr_rcv_process: "
+             "Number of records:%u trimmed to:%u to fit in one MAD\n",
+             num_rec, trim_num_rec );
+    num_rec = trim_num_rec;
+  }
+#endif
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+           "osm_nr_rcv_process: "
+           "Returning %u records\n", num_rec );
+
+  if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+  {
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+    goto Exit;
+  }
+
+  /* 
+   * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+   */
+  p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+                                  p_madw->h_bind,
+                                  num_rec * sizeof(ib_node_record_t) + IB_SA_MAD_HDR_SIZE,
+                                  &p_madw->mad_addr );
+
+  if( !p_resp_madw )
+  {
+    osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+            "osm_nr_rcv_process: ERR 1D06: "
+            "osm_mad_pool_get failed\n" );
+
+    for( i = 0; i < num_rec; i++ )
+    {
+      p_rec_item = (osm_nr_item_t*)cl_qlist_remove_head( &rec_list );
+      cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    }
+
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES );
+    goto Exit;
+  }
+
+  p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+  /*
+    Copy the MAD header back into the response mad.
+    Set the 'R' bit and the payload length,
+    Then copy all records from the list into the response payload.
+  */
+
+  memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+  /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
+  p_resp_sa_mad->sm_key = 0;
+  /* Fill in the offset (paylen will be done by the rmpp SAR) */
+  p_resp_sa_mad->attr_offset =
+    ib_get_attr_offset( sizeof(ib_node_record_t) );
+
+  p_resp_rec = (ib_node_record_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+#ifndef VENDOR_RMPP_SUPPORT
+  /* we support only one packet RMPP - so we will set the first and
+     last flags for gettable */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+  {
+    p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+  }
+#else
+  /* forcefully define the packet as RMPP one */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+  for( i = 0; i < pre_trim_num_rec; i++ )
+  {
+    p_rec_item = (osm_nr_item_t*)cl_qlist_remove_head( &rec_list );
+    /* copy only if not trimmed */
+    if (i < num_rec)
+    {
+      *p_resp_rec = p_rec_item->rec;
+    }
+    cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    p_resp_rec++;
+  }
+
+  CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+  status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+  if (status != IB_SUCCESS)
+  {
+    osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+            "osm_nr_rcv_process: ERR 1D07: "
+            "osm_vendor_send status = %s\n",
+            ib_get_err_str(status));
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_node_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_node_record_ctrl.c
new file mode 100644 (file)
index 0000000..d40c131
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_node_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_nr_rcv_ctrl_t.
+ * This object represents the Node Record controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_node_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_nr_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_nr_rcv_process( ((osm_nr_rcv_ctrl_t*)context)->p_rcv,
+                      (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nr_rcv_ctrl_construct(
+  IN osm_nr_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nr_rcv_ctrl_destroy(
+  IN osm_nr_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_nr_rcv_ctrl_init(
+  IN osm_nr_rcv_ctrl_t* const p_ctrl,
+  IN osm_nr_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_nr_rcv_ctrl_init );
+
+  osm_nr_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_NODE_RECORD,
+    __osm_nr_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_nr_rcv_ctrl_init: ERR 1E01: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_path_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_path_record.c
new file mode 100644 (file)
index 0000000..9377fda
--- /dev/null
@@ -0,0 +1,2006 @@
+/*\r
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.\r
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.\r
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: osm_sa_path_record.c 1929 2009-02-04 15:24:59Z tzachid $\r
+ */\r
+\r
+\r
+/*\r
+ * Abstract:\r
+ *    Implementation of osm_pr_rcv_t.\r
+ * This object represents the PathRecord Receiver object.\r
+ * This object is part of the opensm family of objects.\r
+ *\r
+ * Environment:\r
+ *    Linux User Mode\r
+ *\r
+ * $Revision: 1.10 $\r
+ */\r
+\r
+#if HAVE_CONFIG_H\r
+#  include <config.h>\r
+#endif /* HAVE_CONFIG_H */\r
+\r
+#include <string.h>\r
+#include <iba/ib_types.h>\r
+#include <complib/cl_qmap.h>\r
+#include <complib/cl_passivelock.h>\r
+#include <complib/cl_debug.h>\r
+#include <complib/cl_qlist.h>\r
+#include <opensm/osm_base.h>\r
+#include <opensm/osm_sa_path_record.h>\r
+#include <opensm/osm_port.h>\r
+#include <opensm/osm_node.h>\r
+#include <opensm/osm_switch.h>\r
+#include <vendor/osm_vendor.h>\r
+#include <vendor/osm_vendor_api.h>\r
+#include <opensm/osm_helper.h>\r
+#include <opensm/osm_pkey.h>\r
+#include <opensm/osm_multicast.h>\r
+#include <opensm/osm_partition.h>\r
+\r
+#define OSM_PR_RCV_POOL_MIN_SIZE    64\r
+#define OSM_PR_RCV_POOL_GROW_SIZE   64\r
+\r
+typedef  struct   _osm_pr_item\r
+{\r
+  cl_pool_item_t     pool_item;\r
+  ib_path_rec_t      path_rec;\r
+} osm_pr_item_t;\r
+\r
+typedef struct _osm_path_parms\r
+{\r
+  ib_net16_t         pkey;\r
+  uint8_t            mtu;\r
+  uint8_t            rate;\r
+  uint8_t            sl;\r
+  uint8_t            pkt_life;\r
+  boolean_t          reversible;\r
+} osm_path_parms_t;\r
+\r
+typedef  struct   osm_sa_pr_mcmr_search_ctxt {\r
+  ib_gid_t        *p_mgid;\r
+  osm_mgrp_t      *p_mgrp;\r
+  osm_pr_rcv_t    *p_rcv;\r
+} osm_sa_pr_mcmr_search_ctxt_t;\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_pr_rcv_construct(\r
+  IN osm_pr_rcv_t* const p_rcv )\r
+{\r
+  memset( p_rcv, 0, sizeof(*p_rcv) );\r
+  cl_qlock_pool_construct( &p_rcv->pr_pool );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_pr_rcv_destroy(\r
+  IN osm_pr_rcv_t* const p_rcv )\r
+{\r
+  OSM_LOG_ENTER( p_rcv->p_log, osm_pr_rcv_destroy );\r
+  cl_qlock_pool_destroy( &p_rcv->pr_pool );\r
+  OSM_LOG_EXIT( p_rcv->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osm_pr_rcv_init(\r
+  IN osm_pr_rcv_t*      const p_rcv,\r
+  IN osm_sa_resp_t*     const p_resp,\r
+  IN osm_mad_pool_t*    const p_mad_pool,\r
+  IN osm_subn_t*        const p_subn,\r
+  IN osm_log_t*         const p_log,\r
+  IN cl_plock_t*        const p_lock )\r
+{\r
+  ib_api_status_t       status;\r
+\r
+  OSM_LOG_ENTER( p_log, osm_pr_rcv_init );\r
+\r
+  osm_pr_rcv_construct( p_rcv );\r
+\r
+  p_rcv->p_log = p_log;\r
+  p_rcv->p_subn = p_subn;\r
+  p_rcv->p_lock = p_lock;\r
+  p_rcv->p_resp = p_resp;\r
+  p_rcv->p_mad_pool = p_mad_pool;\r
+\r
+  status = cl_qlock_pool_init( &p_rcv->pr_pool,\r
+                               OSM_PR_RCV_POOL_MIN_SIZE,\r
+                               0,\r
+                               OSM_PR_RCV_POOL_GROW_SIZE,\r
+                               sizeof(osm_pr_item_t),\r
+                               NULL, NULL, NULL );\r
+\r
+  OSM_LOG_EXIT( p_rcv->p_log );\r
+  return( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static inline boolean_t\r
+__osm_sa_path_rec_is_tavor_port(\r
+  IN const osm_port_t*     const p_port)\r
+{\r
+  osm_node_t const* p_node;\r
+  ib_net32_t vend_id;\r
+\r
+  p_node = osm_port_get_parent_node( p_port );\r
+  vend_id = ib_node_info_get_vendor_id( &p_node->node_info );\r
+       \r
+  return( (p_node->node_info.device_id == CL_HTON16(23108)) &&\r
+         ((vend_id == CL_HTON32(OSM_VENDOR_ID_MELLANOX)) || \r
+          (vend_id == CL_HTON32(OSM_VENDOR_ID_TOPSPIN)) || \r
+          (vend_id == CL_HTON32(OSM_VENDOR_ID_SILVERSTORM)) || \r
+          (vend_id == CL_HTON32(OSM_VENDOR_ID_VOLTAIRE))) );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static boolean_t\r
+ __osm_sa_path_rec_apply_tavor_mtu_limit(\r
+  IN const ib_path_rec_t*  const p_pr,\r
+  IN const osm_port_t*     const p_src_port,\r
+  IN const osm_port_t*     const p_dest_port,\r
+  IN const ib_net64_t      comp_mask)\r
+{\r
+  uint8_t required_mtu;\r
+       \r
+  /* only if at least one of the ports is a Tavor device */\r
+  if (! __osm_sa_path_rec_is_tavor_port(p_src_port) && \r
+      ! __osm_sa_path_rec_is_tavor_port(p_dest_port) )\r
+    return( FALSE );\r
+\r
+  /*\r
+    we can apply the patch if either:\r
+    1. No MTU required\r
+    2. Required MTU < \r
+    3. Required MTU = 1K or 512 or 256\r
+    4. Required MTU > 256 or 512\r
+  */\r
+  required_mtu = ib_path_rec_mtu( p_pr );\r
+  if ( ( comp_mask & IB_PR_COMPMASK_MTUSELEC ) &&\r
+       ( comp_mask & IB_PR_COMPMASK_MTU ) )\r
+  {\r
+    switch( ib_path_rec_mtu_sel( p_pr ) )\r
+    {\r
+    case 0:    /* must be greater than */\r
+    case 2:    /* exact match */\r
+      if( IB_MTU_LEN_1024 < required_mtu )\r
+        return(FALSE);\r
+      break;\r
+\r
+    case 1:    /* must be less than */\r
+               /* can't be disqualified by this one */\r
+      break;\r
+\r
+    case 3:    /* largest available */\r
+               /* the ULP intentionally requested */\r
+               /* the largest MTU possible */\r
+      return(FALSE);\r
+      break;\r
+                       \r
+    default:\r
+      /* if we're here, there's a bug in ib_path_rec_mtu_sel() */\r
+      CL_ASSERT( FALSE );\r
+      break;\r
+    }\r
+  }\r
+\r
+  return(TRUE);\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+__osm_pr_rcv_get_path_parms(\r
+  IN osm_pr_rcv_t*         const p_rcv,\r
+  IN const ib_path_rec_t*  const p_pr,\r
+  IN const osm_port_t*     const p_src_port,\r
+  IN const osm_port_t*     const p_dest_port,\r
+  IN const uint16_t        dest_lid_ho,\r
+  IN const ib_net64_t      comp_mask,\r
+  OUT osm_path_parms_t*    const p_parms )\r
+{\r
+  const osm_node_t*        p_node;\r
+  const osm_physp_t*       p_physp;\r
+  const osm_physp_t*       p_dest_physp;\r
+  const osm_prtn_t*        p_prtn;\r
+  const ib_port_info_t*    p_pi;\r
+  ib_api_status_t          status = IB_SUCCESS;\r
+  ib_net16_t               pkey;\r
+  uint8_t                  mtu;\r
+  uint8_t                  rate;\r
+  uint8_t                  pkt_life;\r
+  uint8_t                  required_mtu;\r
+  uint8_t                  required_rate;\r
+  uint8_t                  required_pkt_life;\r
+  uint8_t                  sl;\r
+  ib_net16_t               dest_lid;\r
+\r
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_get_path_parms );\r
+\r
+  dest_lid = cl_hton16( dest_lid_ho );\r
+\r
+  p_dest_physp = osm_port_get_default_phys_ptr( p_dest_port );\r
+  p_physp = osm_port_get_default_phys_ptr( p_src_port );\r
+  p_pi = osm_physp_get_port_info_ptr( p_physp );\r
+\r
+  mtu = ib_port_info_get_mtu_cap( p_pi );\r
+  rate = ib_port_info_compute_rate( p_pi );\r
+\r
+  /* \r
+    Mellanox Tavor device performance is better using 1K MTU.\r
+    If required MTU and MTU selector are such that 1K is OK \r
+    and at least one end of the path is Tavor we override the\r
+    port MTU with 1K.\r
+  */\r
+  if ( p_rcv->p_subn->opt.enable_quirks &&\r
+       __osm_sa_path_rec_apply_tavor_mtu_limit(\r
+               p_pr, p_src_port, p_dest_port, comp_mask) )\r
+    if (mtu > IB_MTU_LEN_1024) \r
+    {\r
+      mtu = IB_MTU_LEN_1024;\r
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+              "__osm_pr_rcv_get_path_parms: "\r
+              "Optimized Path MTU to 1K for Mellanox Tavor device\n");\r
+    }\r
+\r
+  /*\r
+    Walk the subnet object from source to destination,\r
+    tracking the most restrictive rate and mtu values along the way...\r
+\r
+    If source port node is a switch, then p_physp should\r
+    point to the port that routes the destination lid\r
+  */\r
+\r
+  p_node = osm_physp_get_node_ptr( p_physp );\r
+\r
+  if( p_node->sw )\r
+  {\r
+    /*\r
+     * If the dest_lid_ho is equal to the lid of the switch pointed by\r
+     * p_sw then p_physp will be the physical port of the switch port zero.\r
+     */\r
+    p_physp = osm_switch_get_route_by_lid(p_node->sw, cl_ntoh16( dest_lid_ho ) );\r
+    if ( p_physp == 0 )\r
+    {\r
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+               "__osm_pr_rcv_get_path_parms: ERR 1F02: "\r
+               "Cannot find routing to LID 0x%X from switch for GUID 0x%016" PRIx64 "\n",\r
+               dest_lid_ho,\r
+               cl_ntoh64( osm_node_get_node_guid( p_node ) ) );\r
+      status = IB_ERROR;\r
+      goto Exit;\r
+    }\r
+  }\r
+\r
+  /*\r
+   * Same as above\r
+   */\r
+  p_node = osm_physp_get_node_ptr( p_dest_physp );\r
+\r
+  if( p_node->sw )\r
+  {\r
+    p_dest_physp = osm_switch_get_route_by_lid( p_node->sw, cl_ntoh16( dest_lid_ho ) );\r
+\r
+    if ( p_dest_physp == 0 )\r
+    {\r
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+               "__osm_pr_rcv_get_path_parms: ERR 1F03: "\r
+               "Cannot find routing to LID 0x%X from switch for GUID 0x%016" PRIx64 "\n",\r
+               dest_lid_ho,\r
+               cl_ntoh64( osm_node_get_node_guid( p_node ) ) );\r
+      status = IB_ERROR;\r
+      goto Exit;\r
+    }\r
+\r
+  }\r
+\r
+  while( p_physp != p_dest_physp )\r
+  {\r
+    p_physp = osm_physp_get_remote( p_physp );\r
+\r
+    if ( p_physp == 0 )\r
+    {\r
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+               "__osm_pr_rcv_get_path_parms: ERR 1F05: "\r
+               "Cannot find remote phys port when routing to LID 0x%X from node GUID 0x%016" PRIx64 "\n",\r
+               dest_lid_ho,\r
+               cl_ntoh64( osm_node_get_node_guid( p_node ) ) );\r
+      status = IB_ERROR;\r
+      goto Exit;\r
+    }\r
+\r
+    /*\r
+      This is point to point case (no switch in between)\r
+    */\r
+    if( p_physp == p_dest_physp )\r
+      break;\r
+\r
+    p_node = osm_physp_get_node_ptr( p_physp );\r
+\r
+    if( !p_node->sw )\r
+    {\r
+      /*\r
+        There is some sort of problem in the subnet object!\r
+        If this isn't a switch, we should have reached\r
+        the destination by now!\r
+      */\r
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+               "__osm_pr_rcv_get_path_parms: ERR 1F06: "\r
+               "Internal error, bad path\n" );\r
+      status = IB_ERROR;\r
+      goto Exit;\r
+    }\r
+\r
+    /*\r
+      Check parameters for the ingress port in this switch.\r
+    */\r
+    p_pi = osm_physp_get_port_info_ptr( p_physp );\r
+\r
+    if( mtu > ib_port_info_get_mtu_cap( p_pi ) )\r
+    {\r
+      mtu = ib_port_info_get_mtu_cap( p_pi );\r
+      if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )\r
+      {\r
+        osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+                 "__osm_pr_rcv_get_path_parms: "\r
+                 "New smallest MTU = %u at intervening port 0x%016" PRIx64\r
+                 " port num 0x%X\n",\r
+                 mtu,\r
+                 cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),\r
+                 osm_physp_get_port_num( p_physp ) );\r
+      }\r
+    }\r
+\r
+    if( rate > ib_port_info_compute_rate( p_pi ) )\r
+    {\r
+      rate = ib_port_info_compute_rate( p_pi );\r
+      if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )\r
+      {\r
+        osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+                 "__osm_pr_rcv_get_path_parms: "\r
+                 "New smallest rate = %u at intervening port 0x%016" PRIx64\r
+                 " port num 0x%X\n",\r
+                 rate,\r
+                 cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),\r
+                 osm_physp_get_port_num( p_physp ) );\r
+      }\r
+    }\r
+\r
+    /*\r
+      Continue with the egress port on this switch.\r
+    */\r
+    p_physp = osm_switch_get_route_by_lid( p_node->sw, dest_lid );\r
+\r
+    if ( p_physp == 0 )\r
+    {\r
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+               "__osm_pr_rcv_get_path_parms: ERR 1F07: "\r
+               "Dead end on path to LID 0x%X from switch for GUID 0x%016" PRIx64 "\n",\r
+               dest_lid_ho,\r
+               cl_ntoh64( osm_node_get_node_guid( p_node ) ) );\r
+      status = IB_ERROR;\r
+      goto Exit;\r
+    }\r
+\r
+    CL_ASSERT( p_physp );\r
+    CL_ASSERT( osm_physp_is_valid( p_physp ) );\r
+\r
+    p_pi = osm_physp_get_port_info_ptr( p_physp );\r
+\r
+    if( mtu > ib_port_info_get_mtu_cap( p_pi ) )\r
+    {\r
+      mtu = ib_port_info_get_mtu_cap( p_pi );\r
+      if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )\r
+      {\r
+        osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+                 "__osm_pr_rcv_get_path_parms: "\r
+                 "New smallest MTU = %u at intervening port 0x%016" PRIx64\r
+                 " port num 0x%X\n",\r
+                 mtu,\r
+                 cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),\r
+                 osm_physp_get_port_num( p_physp ) );\r
+      }\r
+    }\r
+\r
+    if( rate > ib_port_info_compute_rate( p_pi ) )\r
+    {\r
+      rate = ib_port_info_compute_rate( p_pi );\r
+      if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )\r
+      {\r
+        osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+                 "__osm_pr_rcv_get_path_parms: "\r
+                 "New smallest rate = %u at intervening port 0x%016" PRIx64\r
+                 " port num 0x%X\n",\r
+                 rate,\r
+                 cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),\r
+                 osm_physp_get_port_num( p_physp ) );\r
+      }\r
+    }\r
+\r
+  }\r
+\r
+  /*\r
+    p_physp now points to the destination\r
+  */\r
+  p_pi = osm_physp_get_port_info_ptr( p_physp );\r
+\r
+  if( mtu > ib_port_info_get_mtu_cap( p_pi ) )\r
+  {\r
+    mtu = ib_port_info_get_mtu_cap( p_pi );\r
+    if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )\r
+    {\r
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+               "__osm_pr_rcv_get_path_parms: "\r
+               "New smallest MTU = %u at destination port 0x%016" PRIx64 "\n",\r
+               mtu,\r
+               cl_ntoh64(osm_physp_get_port_guid( p_physp )) );\r
+    }\r
+  }\r
+\r
+  if( rate > ib_port_info_compute_rate( p_pi ) )\r
+  {\r
+    rate = ib_port_info_compute_rate( p_pi );\r
+    if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )\r
+    {\r
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+               "__osm_pr_rcv_get_path_parms: "\r
+               "New smallest rate = %u at destination port 0x%016" PRIx64 "\n",\r
+               rate,\r
+               cl_ntoh64(osm_physp_get_port_guid( p_physp )) );\r
+    }\r
+  }\r
+\r
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )\r
+  {\r
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+             "__osm_pr_rcv_get_path_parms: "\r
+             "Path min MTU = %u, min rate = %u\n", mtu, rate );\r
+  }\r
+\r
+  /*\r
+    Determine if these values meet the user criteria\r
+    and adjust appropriately\r
+  */\r
+\r
+  /* we silently ignore cases where only the MTU selector is defined */\r
+  if ( ( comp_mask & IB_PR_COMPMASK_MTUSELEC ) &&\r
+       ( comp_mask & IB_PR_COMPMASK_MTU ) )\r
+  {\r
+    required_mtu = ib_path_rec_mtu( p_pr );\r
+    switch( ib_path_rec_mtu_sel( p_pr ) )\r
+    {\r
+    case 0:    /* must be greater than */\r
+      if( mtu <= required_mtu )\r
+        status = IB_NOT_FOUND;\r
+      break;\r
+\r
+    case 1:    /* must be less than */\r
+       if( mtu >= required_mtu )\r
+       {\r
+          /* adjust to use the highest mtu\r
+             lower then the required one */\r
+          if( required_mtu > 1 )\r
+            mtu = required_mtu - 1;\r
+          else\r
+            status = IB_NOT_FOUND;\r
+       }\r
+      break;\r
+\r
+    case 2:    /* exact match */\r
+      if( mtu < required_mtu )\r
+        status = IB_NOT_FOUND;\r
+      else\r
+        mtu = required_mtu;\r
+      break;\r
+\r
+    case 3:    /* largest available */\r
+      /* can't be disqualified by this one */\r
+      break;\r
+\r
+    default:\r
+      /* if we're here, there's a bug in ib_path_rec_mtu_sel() */\r
+      CL_ASSERT( FALSE );\r
+      status = IB_ERROR;\r
+      break;\r
+    }\r
+  }\r
+\r
+  /* we silently ignore cases where only the Rate selector is defined */\r
+  if ( ( comp_mask & IB_PR_COMPMASK_RATESELEC ) &&\r
+       ( comp_mask & IB_PR_COMPMASK_RATE ) )\r
+  {\r
+    required_rate = ib_path_rec_rate( p_pr );\r
+    switch( ib_path_rec_rate_sel( p_pr ) )\r
+    {\r
+    case 0:    /* must be greater than */\r
+      if( rate <= required_rate )\r
+        status = IB_NOT_FOUND;\r
+      break;\r
+\r
+    case 1:    /* must be less than */\r
+      if( rate >= required_rate )\r
+      {\r
+        /* adjust the rate to use the highest rate\r
+           lower then the required one */\r
+        if( required_rate > 2 )\r
+          rate = required_rate - 1;\r
+        else\r
+          status = IB_NOT_FOUND;\r
+      }\r
+      break;\r
+\r
+    case 2:    /* exact match */\r
+      if( rate < required_rate )\r
+        status = IB_NOT_FOUND;\r
+      else\r
+        rate = required_rate;\r
+      break;\r
+\r
+    case 3:    /* largest available */\r
+      /* can't be disqualified by this one */\r
+      break;\r
+\r
+    default:\r
+      /* if we're here, there's a bug in ib_path_rec_mtu_sel() */\r
+      CL_ASSERT( FALSE );\r
+      status = IB_ERROR;\r
+      break;\r
+    }\r
+  }\r
+\r
+  /* Verify the pkt_life_time */\r
+  /* According to spec definition IBA 1.2 Table 205 PacketLifeTime description,\r
+     for loopback paths, packetLifeTime shall be zero. */\r
+  if ( p_src_port == p_dest_port )\r
+    pkt_life = 0;      /* loopback */\r
+  else\r
+    pkt_life = OSM_DEFAULT_SUBNET_TIMEOUT;\r
+\r
+  /* we silently ignore cases where only the PktLife selector is defined */\r
+  if ( ( comp_mask & IB_PR_COMPMASK_PKTLIFETIMESELEC ) &&\r
+       ( comp_mask & IB_PR_COMPMASK_PKTLIFETIME ) )\r
+  {\r
+    required_pkt_life = ib_path_rec_pkt_life( p_pr );\r
+    switch( ib_path_rec_pkt_life_sel( p_pr ) )\r
+    {\r
+    case 0:    /* must be greater than */\r
+      if( pkt_life <= required_pkt_life )\r
+        status = IB_NOT_FOUND;\r
+      break;\r
+\r
+    case 1:    /* must be less than */\r
+      if( pkt_life >= required_pkt_life )\r
+      {\r
+        /* adjust the lifetime to use the highest possible\r
+           lower then the required one */\r
+        if( required_pkt_life > 1 )\r
+          pkt_life = required_pkt_life - 1;\r
+        else\r
+          status = IB_NOT_FOUND;\r
+      }\r
+      break;\r
+\r
+    case 2:    /* exact match */\r
+      if( pkt_life < required_pkt_life )\r
+         status = IB_NOT_FOUND;\r
+      else\r
+         pkt_life = required_pkt_life;\r
+      break;\r
+\r
+    case 3:    /* smallest available */\r
+      /* can't be disqualified by this one */\r
+      break;\r
+\r
+    default:\r
+      /* if we're here, there's a bug in ib_path_rec_pkt_life_sel() */\r
+      CL_ASSERT( FALSE );\r
+      status = IB_ERROR;\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (status != IB_SUCCESS)\r
+    goto Exit;\r
+\r
+  p_parms->mtu = mtu;\r
+  p_parms->rate = rate;\r
+  p_parms->pkt_life = pkt_life;\r
+\r
+  if( comp_mask & IB_PR_COMPMASK_RAWTRAFFIC &&\r
+      cl_ntoh32( p_pr->hop_flow_raw ) & ( 1<<31 ) )\r
+    pkey = osm_physp_find_common_pkey( p_physp, p_dest_physp );\r
+  else if( comp_mask & IB_PR_COMPMASK_PKEY )\r
+  {\r
+    pkey = p_pr->pkey;\r
+    if( !osm_physp_share_this_pkey( p_physp, p_dest_physp, pkey ) )\r
+    {\r
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+               "__osm_pr_rcv_get_path_parms: ERR 1F1A: "\r
+               "Ports do not share specified PKey 0x%04x\n", cl_ntoh16(pkey));\r
+      status = IB_NOT_FOUND;\r
+      goto Exit;\r
+    }\r
+  }\r
+  else\r
+  {\r
+    pkey = osm_physp_find_common_pkey( p_physp, p_dest_physp );\r
+    if ( !pkey )\r
+    {\r
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+               "__osm_pr_rcv_get_path_parms: ERR 1F1B: "\r
+               "Ports do not have any shared PKeys\n");\r
+      status = IB_NOT_FOUND;\r
+      goto Exit;\r
+    }\r
+  }\r
+\r
+  sl = OSM_DEFAULT_SL;\r
+\r
+  if (pkey) {\r
+    p_prtn = (osm_prtn_t *)cl_qmap_get(&p_rcv->p_subn->prtn_pkey_tbl,\r
+                                       pkey & cl_ntoh16((uint16_t)~0x8000));\r
+    if ( p_prtn == (osm_prtn_t *)cl_qmap_end(&p_rcv->p_subn->prtn_pkey_tbl) )\r
+    {\r
+      /* this may be possible when pkey tables are created somehow in\r
+         previous runs or things are going wrong here */\r
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+               "__osm_pr_rcv_get_path_parms: ERR 1F1C: "\r
+               "No partition found for PKey 0x%04x - using default SL %d\n",\r
+               cl_ntoh16(pkey), sl );\r
+    }\r
+    else\r
+      sl = p_prtn->sl;\r
+\r
+    /* reset pkey when raw traffic */\r
+    if( comp_mask & IB_PR_COMPMASK_RAWTRAFFIC &&\r
+        cl_ntoh32( p_pr->hop_flow_raw ) & ( 1<<31 ) )\r
+      pkey = 0;\r
+  }\r
+\r
+  if ( ( comp_mask & IB_PR_COMPMASK_SL ) && ib_path_rec_sl( p_pr ) != sl )\r
+  {\r
+    status = IB_NOT_FOUND;\r
+    goto Exit;\r
+  }\r
+\r
+  p_parms->pkey = pkey;\r
+  p_parms->sl = sl;\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( p_rcv->p_log );\r
+  return( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static void\r
+__osm_pr_rcv_build_pr(\r
+  IN osm_pr_rcv_t*         const p_rcv,\r
+  IN const osm_port_t*     const p_src_port,\r
+  IN const osm_port_t*     const p_dest_port,\r
+  IN const uint16_t        src_lid_ho,\r
+  IN const uint16_t        dest_lid_ho,\r
+  IN const uint8_t         preference,\r
+  IN const osm_path_parms_t*  const p_parms,\r
+  OUT ib_path_rec_t*       const p_pr )\r
+{\r
+  const osm_physp_t*       p_src_physp;\r
+  const osm_physp_t*       p_dest_physp;\r
+\r
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_build_pr );\r
+\r
+  p_src_physp = osm_port_get_default_phys_ptr( p_src_port );\r
+  p_dest_physp = osm_port_get_default_phys_ptr( p_dest_port );\r
+\r
+  p_pr->dgid.unicast.prefix = osm_physp_get_subnet_prefix( p_dest_physp );\r
+  p_pr->dgid.unicast.interface_id = osm_physp_get_port_guid( p_dest_physp );\r
+\r
+  p_pr->sgid.unicast.prefix = osm_physp_get_subnet_prefix( p_src_physp );\r
+  p_pr->sgid.unicast.interface_id = osm_physp_get_port_guid( p_src_physp );\r
+\r
+  p_pr->dlid = cl_hton16( dest_lid_ho );\r
+  p_pr->slid = cl_hton16( src_lid_ho );\r
+\r
+  p_pr->hop_flow_raw &= cl_hton32(1<<31);\r
+\r
+  p_pr->pkey = p_parms->pkey;\r
+  p_pr->qos_class_sl = cl_hton16(p_parms->sl);\r
+  p_pr->mtu = (uint8_t)(p_parms->mtu | 0x80);\r
+  p_pr->rate = (uint8_t)(p_parms->rate | 0x80);\r
+\r
+  /* According to 1.2 spec definition Table 205 PacketLifeTime description,\r
+     for loopback paths, packetLifeTime shall be zero. */\r
+  if ( p_src_port == p_dest_port )\r
+    p_pr->pkt_life = 0x80;     /* loopback */\r
+  else\r
+    p_pr->pkt_life = (uint8_t)(p_parms->pkt_life | 0x80);\r
+\r
+  p_pr->preference = preference;\r
+\r
+  /* always return num_path = 0 so this is only the reversible component */\r
+  if (p_parms->reversible)\r
+    p_pr->num_path = 0x80;\r
+\r
+  OSM_LOG_EXIT( p_rcv->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static osm_pr_item_t*\r
+__osm_pr_rcv_get_lid_pair_path(\r
+  IN osm_pr_rcv_t*         const p_rcv,\r
+  IN const ib_path_rec_t*  const p_pr,\r
+  IN const osm_port_t*     const p_src_port,\r
+  IN const osm_port_t*     const p_dest_port,\r
+  IN const uint16_t        src_lid_ho,\r
+  IN const uint16_t        dest_lid_ho,\r
+  IN const ib_net64_t      comp_mask,\r
+  IN const uint8_t         preference )\r
+{\r
+  osm_path_parms_t         path_parms;\r
+  osm_path_parms_t         rev_path_parms;\r
+  osm_pr_item_t            *p_pr_item;\r
+  ib_api_status_t          status, rev_path_status;\r
+\r
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_get_lid_pair_path );\r
+\r
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )\r
+  {\r
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+             "__osm_pr_rcv_get_lid_pair_path: "\r
+             "Src LID 0x%X, Dest LID 0x%X\n",\r
+             src_lid_ho, dest_lid_ho );\r
+  }\r
+\r
+  p_pr_item = (osm_pr_item_t*)cl_qlock_pool_get( &p_rcv->pr_pool );\r
+  if( p_pr_item == NULL )\r
+  {\r
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+             "__osm_pr_rcv_get_lid_pair_path: ERR 1F01: "\r
+             "Unable to allocate path record\n" );\r
+    goto Exit;\r
+  }\r
+\r
+  status = __osm_pr_rcv_get_path_parms( p_rcv, p_pr, p_src_port,\r
+                                        p_dest_port, dest_lid_ho,\r
+                                        comp_mask, &path_parms );\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item );\r
+    p_pr_item = NULL;\r
+    goto Exit;\r
+  }\r
+\r
+  /* now try the reversible path */\r
+  rev_path_status = __osm_pr_rcv_get_path_parms( p_rcv, p_pr, p_dest_port,\r
+                                                 p_src_port, src_lid_ho,\r
+                                                 comp_mask, &rev_path_parms );\r
+  path_parms.reversible = ( rev_path_status == IB_SUCCESS );\r
+\r
+  /* did we get a Reversible Path compmask ? */\r
+  /* \r
+     NOTE that if the reversible component = 0, it is a don't care\r
+     rather then requiring non-reversible paths ... \r
+     see Vol1 Ver1.2 p900 l16\r
+  */\r
+  if( comp_mask & IB_PR_COMPMASK_REVERSIBLE )\r
+  {\r
+    if( (! path_parms.reversible && ( p_pr->num_path & 0x80 ) ) )\r
+    {\r
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+               "__osm_pr_rcv_get_lid_pair_path: "\r
+               "Requested reversible path but failed to get one\n");\r
+\r
+      cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item );\r
+      p_pr_item = NULL;\r
+      goto Exit;\r
+    }\r
+  }\r
+\r
+  __osm_pr_rcv_build_pr( p_rcv, p_src_port, p_dest_port, src_lid_ho,\r
+                         dest_lid_ho, preference, &path_parms,\r
+                         &p_pr_item->path_rec );\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( p_rcv->p_log );\r
+  return( p_pr_item );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static void\r
+__osm_pr_rcv_get_port_pair_paths(\r
+  IN osm_pr_rcv_t*         const p_rcv,\r
+  IN const osm_madw_t*     const p_madw,\r
+  IN const osm_port_t*     const p_req_port,\r
+  IN const osm_port_t*     const p_src_port,\r
+  IN const osm_port_t*     const p_dest_port,\r
+  IN const ib_net64_t      comp_mask,\r
+  IN cl_qlist_t*           const p_list )\r
+{\r
+  const ib_path_rec_t*     p_pr;\r
+  const ib_sa_mad_t*       p_sa_mad;\r
+  osm_pr_item_t*           p_pr_item;\r
+  uint16_t                 src_lid_min_ho;\r
+  uint16_t                 src_lid_max_ho;\r
+  uint16_t                 dest_lid_min_ho;\r
+  uint16_t                 dest_lid_max_ho;\r
+  uint16_t                 src_lid_ho;\r
+  uint16_t                 dest_lid_ho;\r
+  uint32_t                 path_num;\r
+  uint8_t                  preference;\r
+  uintn_t                  iterations;\r
+  uintn_t                  src_offset;\r
+  uintn_t                  dest_offset;\r
+\r
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_get_port_pair_paths );\r
+\r
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )\r
+  {\r
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+             "__osm_pr_rcv_get_port_pair_paths: "\r
+             "Src port 0x%016" PRIx64 ", "\r
+             "Dst port 0x%016" PRIx64 "\n",\r
+             cl_ntoh64( osm_port_get_guid( p_src_port ) ),\r
+             cl_ntoh64( osm_port_get_guid( p_dest_port ) ) );\r
+  }\r
+\r
+  /* Check that the req_port, src_port and dest_port all share a\r
+     pkey. The check is done on the default physical port of the ports. */\r
+  if (osm_port_share_pkey(p_rcv->p_log, p_req_port, p_src_port) == FALSE ||\r
+      osm_port_share_pkey(p_rcv->p_log, p_req_port, p_dest_port) == FALSE ||\r
+      osm_port_share_pkey(p_rcv->p_log, p_src_port, p_dest_port) == FALSE )\r
+  {\r
+    /* One of the pairs doesn't share a pkey so the path is disqualified. */\r
+    goto Exit;\r
+  }\r
+\r
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );\r
+  p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );\r
+\r
+  /*\r
+    We shouldn't be here if the paths are disqualified in some way...\r
+    Thus, we assume every possible connection is valid.\r
+\r
+    We desire to return high-quality paths first.\r
+    In OpenSM, higher quality means least overlap with other paths.\r
+    This is acheived in practice by returning paths with\r
+    different LID value on each end, which means these\r
+    paths are more redundant that paths with the same LID repeated\r
+    on one side.  For example, in OpenSM the paths between two\r
+    endpoints with LMC = 1 might be as follows:\r
+\r
+    Port A, LID 1 <-> Port B, LID 3\r
+    Port A, LID 1 <-> Port B, LID 4\r
+    Port A, LID 2 <-> Port B, LID 3\r
+    Port A, LID 2 <-> Port B, LID 4\r
+\r
+    The OpenSM unicast routing algorithms attempt to disperse each path\r
+    to as varied a physical path as is reasonable.  1<->3 and 1<->4 have\r
+    more physical overlap (hence less redundancy) than 1<->3 and 2<->4.\r
+\r
+    OpenSM ranks paths in three preference groups:\r
+\r
+    Preference Value    Description\r
+    ----------------    -------------------------------------------\r
+    0             Redundant in both directions with other\r
+    pref value = 0 paths\r
+\r
+    1             Redundant in one direction with other\r
+    pref value = 0 and pref value = 1 paths\r
+\r
+    2             Not redundant in either direction with\r
+    other paths\r
+\r
+    3-FF          Unused\r
+\r
+\r
+    SA clients don't need to know these details, only that the lower\r
+    preference paths are preferred, as stated in the spec.  The paths\r
+    may not actually be physically redundant depending on the topology\r
+    of the subnet, but the point of LMC > 0 is to offer redundancy,\r
+    so it is assumed that the subnet is physically appropriate for the\r
+    specified LMC value.  A more advanced implementation would inspect for \r
+    physical redundancy, but I'm not going to bother with that now.\r
+  */\r
+\r
+  /*\r
+    Refine our search if the client specified end-point LIDs\r
+  */\r
+  if( comp_mask & IB_PR_COMPMASK_DLID )\r
+  {\r
+    dest_lid_min_ho = cl_ntoh16( p_pr->dlid );\r
+    dest_lid_max_ho = cl_ntoh16( p_pr->dlid );\r
+  }\r
+  else\r
+  {\r
+    osm_port_get_lid_range_ho( p_dest_port, &dest_lid_min_ho,\r
+                               &dest_lid_max_ho );\r
+  }\r
+\r
+  if( comp_mask & IB_PR_COMPMASK_SLID )\r
+  {\r
+    src_lid_min_ho = cl_ntoh16( p_pr->slid );\r
+    src_lid_max_ho = cl_ntoh16( p_pr->slid );\r
+  }\r
+  else\r
+  {\r
+    osm_port_get_lid_range_ho( p_src_port, &src_lid_min_ho,\r
+                               &src_lid_max_ho );\r
+  }\r
+\r
+  if ( src_lid_min_ho == 0 )\r
+  {\r
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+             "__osm_pr_rcv_get_port_pair_paths: ERR 1F20:"\r
+             "Obtained source LID of 0. No such LID possible\n");\r
+     goto Exit;\r
+  }\r
+\r
+  if ( dest_lid_min_ho == 0 )\r
+  {\r
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+             "__osm_pr_rcv_get_port_pair_paths: ERR 1F21:"\r
+             "Obtained destination LID of 0. No such LID possible\n");\r
+     goto Exit;\r
+  }\r
+\r
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )\r
+  {\r
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+             "__osm_pr_rcv_get_port_pair_paths: "\r
+             "Src LIDs [0x%X-0x%X], "\r
+             "Dest LIDs [0x%X-0x%X]\n",\r
+             src_lid_min_ho, src_lid_max_ho,\r
+             dest_lid_min_ho, dest_lid_max_ho );\r
+  }\r
+\r
+  src_lid_ho = src_lid_min_ho;\r
+  dest_lid_ho = dest_lid_min_ho;\r
+\r
+  /*\r
+    Preferred paths come first in OpenSM\r
+  */\r
+  preference = 0;\r
+  path_num = 0;\r
+\r
+  /* If SubnAdmGet, assume NumbPaths 1 (1.2 erratum) */\r
+  if( p_sa_mad->method != IB_MAD_METHOD_GET )\r
+    if( comp_mask & IB_PR_COMPMASK_NUMBPATH )\r
+      iterations = ib_path_rec_num_path( p_pr );\r
+    else\r
+      iterations = (uintn_t)(-1);\r
+  else\r
+    iterations = 1;\r
+\r
+  while( path_num < iterations )\r
+  {\r
+    /*\r
+      These paths are "fully redundant"\r
+    */\r
+\r
+    p_pr_item = __osm_pr_rcv_get_lid_pair_path( p_rcv, p_pr,\r
+                                                p_src_port, p_dest_port,\r
+                                                src_lid_ho, dest_lid_ho,\r
+                                                comp_mask, preference );\r
+\r
+    if( p_pr_item )\r
+    {\r
+      cl_qlist_insert_tail( p_list,\r
+                            (cl_list_item_t*)&p_pr_item->pool_item );\r
+      ++path_num;\r
+    }\r
+\r
+    if( ++src_lid_ho > src_lid_max_ho )\r
+      break;\r
+\r
+    if( ++dest_lid_ho > dest_lid_max_ho )\r
+      break;\r
+  }\r
+\r
+  /*\r
+    Check if we've accumulated all the paths that the user cares to see\r
+  */\r
+  if( path_num == iterations )\r
+    goto Exit;\r
+\r
+  /*\r
+    Don't bother reporting preference 1 paths for now.\r
+    It's more trouble than it's worth and can only occur\r
+    if ports have different LMC values, which isn't supported\r
+    by OpenSM right now anyway.\r
+  */\r
+  preference = 2;\r
+  src_lid_ho = src_lid_min_ho;\r
+  dest_lid_ho = dest_lid_min_ho;\r
+  src_offset = 0;\r
+  dest_offset = 0;\r
+\r
+  /*\r
+    Iterate over the remaining paths\r
+  */\r
+  while( path_num < iterations )\r
+  {\r
+    dest_offset++;\r
+    dest_lid_ho++;\r
+\r
+    if( dest_lid_ho > dest_lid_max_ho )\r
+    {\r
+      src_offset++;\r
+      src_lid_ho++;\r
+\r
+      if( src_lid_ho > src_lid_max_ho )\r
+        break;    /* done */\r
+\r
+      dest_offset = 0;\r
+      dest_lid_ho = dest_lid_min_ho;\r
+    }\r
+\r
+    /*\r
+      These paths are "fully non-redundant" with paths already\r
+      identified above and consequently not of much value.\r
+\r
+      Don't return paths we already identified above, as indicated\r
+      by the offset values being equal.\r
+    */\r
+    if( src_offset == dest_offset )\r
+      continue;      /* already reported */\r
+\r
+    p_pr_item = __osm_pr_rcv_get_lid_pair_path( p_rcv, p_pr,\r
+                                                p_src_port, p_dest_port,\r
+                                                src_lid_ho, dest_lid_ho,\r
+                                                comp_mask, preference );\r
+\r
+    if( p_pr_item )\r
+    {\r
+      cl_qlist_insert_tail( p_list,\r
+                            (cl_list_item_t*)&p_pr_item->pool_item );\r
+      ++path_num;\r
+    }\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( p_rcv->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_net16_t\r
+__osm_pr_rcv_get_end_points(\r
+  IN osm_pr_rcv_t*         const p_rcv,\r
+  IN const osm_madw_t*     const p_madw,\r
+  OUT const osm_port_t**   const pp_src_port,\r
+  OUT const osm_port_t**   const pp_dest_port )\r
+{\r
+  const ib_path_rec_t*     p_pr;\r
+  const ib_sa_mad_t*       p_sa_mad;\r
+  ib_net64_t               comp_mask;\r
+  ib_api_status_t          status;\r
+  ib_net16_t               sa_status = IB_SA_MAD_STATUS_SUCCESS;\r
+\r
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_get_end_points );\r
+\r
+  /*\r
+    Determine what fields are valid and then get a pointer\r
+    to the source and destination port objects, if possible.\r
+  */\r
+\r
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );\r
+  p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );\r
+\r
+  comp_mask = p_sa_mad->comp_mask;\r
+\r
+  /*\r
+    Check a few easy disqualifying cases up front before getting\r
+    into the endpoints.\r
+  */\r
+\r
+  if( comp_mask & IB_PR_COMPMASK_SGID )\r
+  {\r
+    if ( ! ib_gid_is_link_local ( &p_pr->sgid ) )\r
+    {\r
+      if ( ib_gid_get_subnet_prefix ( &p_pr->sgid ) != p_rcv->p_subn->opt.subnet_prefix )\r
+      {\r
+        /*\r
+          This 'error' is the client's fault (bad gid) so\r
+          don't enter it as an error in our own log.\r
+          Return an error response to the client.\r
+        */\r
+        osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,\r
+                 "__osm_pr_rcv_get_end_points: "\r
+                 "Non local SGID subnet prefix 0x%016" PRIx64 "\n",\r
+                 cl_ntoh64( p_pr->sgid.unicast.prefix ) );\r
+\r
+        sa_status = IB_SA_MAD_STATUS_INVALID_GID;\r
+        goto Exit;\r
+      }\r
+    }\r
+\r
+    *pp_src_port = (osm_port_t*)cl_qmap_get(\r
+      &p_rcv->p_subn->port_guid_tbl,\r
+      p_pr->sgid.unicast.interface_id );\r
+\r
+    if( *pp_src_port == (osm_port_t*)cl_qmap_end(\r
+          &p_rcv->p_subn->port_guid_tbl ) )\r
+    {\r
+      /*\r
+        This 'error' is the client's fault (bad gid) so\r
+        don't enter it as an error in our own log.\r
+        Return an error response to the client.\r
+      */\r
+      osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,\r
+               "__osm_pr_rcv_get_end_points: "\r
+               "No source port with GUID 0x%016" PRIx64 "\n",\r
+               cl_ntoh64( p_pr->sgid.unicast.interface_id) );\r
+\r
+      sa_status = IB_SA_MAD_STATUS_INVALID_GID;\r
+      goto Exit;\r
+    }\r
+  }\r
+  else\r
+  {\r
+    *pp_src_port = 0;\r
+    if( comp_mask & IB_PR_COMPMASK_SLID )\r
+    {\r
+      status = cl_ptr_vector_at( &p_rcv->p_subn->port_lid_tbl,\r
+                                 cl_ntoh16(p_pr->slid), (void**)pp_src_port );\r
+\r
+      if( (status != CL_SUCCESS) || (*pp_src_port == NULL) )\r
+      {\r
+        /*\r
+          This 'error' is the client's fault (bad lid) so\r
+          don't enter it as an error in our own log.\r
+          Return an error response to the client.\r
+        */\r
+        osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,\r
+                 "__osm_pr_rcv_get_end_points: "\r
+                 "No source port with LID = 0x%X\n",\r
+                 cl_ntoh16( p_pr->slid) );\r
+\r
+        sa_status = IB_SA_MAD_STATUS_NO_RECORDS;\r
+        goto Exit;\r
+      }\r
+    }\r
+  }\r
+\r
+  if( comp_mask & IB_PR_COMPMASK_DGID )\r
+  {\r
+    if ( ! ib_gid_is_link_local ( &p_pr->dgid ) )\r
+    {\r
+      if ( ! ib_gid_is_multicast ( &p_pr->dgid ) &&\r
+             ib_gid_get_subnet_prefix ( &p_pr->dgid ) != p_rcv->p_subn->opt.subnet_prefix )\r
+      {\r
+        /*\r
+          This 'error' is the client's fault (bad gid) so\r
+          don't enter it as an error in our own log.\r
+          Return an error response to the client.\r
+        */\r
+        osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,\r
+                 "__osm_pr_rcv_get_end_points: "\r
+                 "Non local DGID subnet prefix 0x%016" PRIx64 "\n",\r
+                 cl_ntoh64( p_pr->dgid.unicast.prefix ) );\r
+\r
+        sa_status = IB_SA_MAD_STATUS_INVALID_GID;\r
+        goto Exit;\r
+      }\r
+    }\r
+\r
+    *pp_dest_port = (osm_port_t*)cl_qmap_get(\r
+      &p_rcv->p_subn->port_guid_tbl,\r
+      p_pr->dgid.unicast.interface_id );\r
+\r
+    if( *pp_dest_port == (osm_port_t*)cl_qmap_end(\r
+          &p_rcv->p_subn->port_guid_tbl ) )\r
+    {\r
+      /*\r
+        This 'error' is the client's fault (bad gid) so\r
+        don't enter it as an error in our own log.\r
+        Return an error response to the client.\r
+      */\r
+      osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,\r
+               "__osm_pr_rcv_get_end_points: "\r
+               "No dest port with GUID 0x%016" PRIx64 "\n",\r
+               cl_ntoh64( p_pr->dgid.unicast.interface_id) );\r
+\r
+      sa_status = IB_SA_MAD_STATUS_INVALID_GID;\r
+      goto Exit;\r
+    }\r
+  }\r
+  else\r
+  {\r
+    *pp_dest_port = 0;\r
+    if( comp_mask & IB_PR_COMPMASK_DLID )\r
+    {\r
+      status = cl_ptr_vector_at( &p_rcv->p_subn->port_lid_tbl,\r
+                                 cl_ntoh16(p_pr->dlid),  (void**)pp_dest_port );\r
+\r
+      if( (status != CL_SUCCESS) || (*pp_dest_port == NULL) )\r
+      {\r
+        /*\r
+          This 'error' is the client's fault (bad lid) so\r
+          don't enter it as an error in our own log.\r
+          Return an error response to the client.\r
+        */\r
+        osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,\r
+                 "__osm_pr_rcv_get_end_points: "\r
+                 "No dest port with LID = 0x%X\n",\r
+                 cl_ntoh16( p_pr->dlid) );\r
+\r
+        sa_status = IB_SA_MAD_STATUS_NO_RECORDS;\r
+        goto Exit;\r
+      }\r
+    }\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( p_rcv->p_log );\r
+  return( sa_status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static void\r
+__osm_pr_rcv_process_world(\r
+  IN osm_pr_rcv_t*         const p_rcv,\r
+  IN const osm_madw_t*     const p_madw,\r
+  IN const osm_port_t*     const requester_port,\r
+  IN const ib_net64_t      comp_mask,\r
+  IN cl_qlist_t*           const p_list )\r
+{\r
+  const cl_qmap_t*         p_tbl;\r
+  const osm_port_t*        p_dest_port;\r
+  const osm_port_t*        p_src_port;\r
+\r
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_process_world );\r
+\r
+  /*\r
+    Iterate the entire port space over itself.\r
+    A path record from a port to itself is legit, so no\r
+    need for a special case there.\r
+\r
+    We compute both A -> B and B -> A, since we don't have\r
+    any check to determine the reversability of the paths.\r
+  */\r
+  p_tbl = &p_rcv->p_subn->port_guid_tbl;\r
+\r
+  p_dest_port = (osm_port_t*)cl_qmap_head( p_tbl );\r
+  while( p_dest_port != (osm_port_t*)cl_qmap_end( p_tbl ) )\r
+  {\r
+    p_src_port = (osm_port_t*)cl_qmap_head( p_tbl );\r
+    while( p_src_port != (osm_port_t*)cl_qmap_end( p_tbl ) )\r
+    {\r
+      __osm_pr_rcv_get_port_pair_paths( p_rcv, p_madw, requester_port, p_src_port,\r
+                                        p_dest_port, comp_mask, p_list );\r
+\r
+      p_src_port = (osm_port_t*)cl_qmap_next( &p_src_port->map_item );\r
+    }\r
+\r
+    p_dest_port = (osm_port_t*)cl_qmap_next( &p_dest_port->map_item );\r
+  }\r
+\r
+  OSM_LOG_EXIT( p_rcv->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static void\r
+__osm_pr_rcv_process_half(\r
+  IN osm_pr_rcv_t*         const p_rcv,\r
+  IN const osm_madw_t*     const p_madw,\r
+  IN const osm_port_t*     const requester_port,\r
+  IN const osm_port_t*     const p_src_port,\r
+  IN const osm_port_t*     const p_dest_port,\r
+  IN const ib_net64_t      comp_mask,\r
+  IN cl_qlist_t*           const p_list )\r
+{\r
+  const cl_qmap_t*         p_tbl;\r
+  const osm_port_t*        p_port;\r
+\r
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_process_half );\r
+\r
+  /*\r
+    Iterate over every port, looking for matches...\r
+    A path record from a port to itself is legit, so no\r
+    need to special case that one.\r
+  */\r
+  p_tbl = &p_rcv->p_subn->port_guid_tbl;\r
+\r
+  if( p_src_port )\r
+  {\r
+    /*\r
+      The src port if fixed, so iterate over destination ports.\r
+    */\r
+    p_port = (osm_port_t*)cl_qmap_head( p_tbl );\r
+    while( p_port != (osm_port_t*)cl_qmap_end( p_tbl ) )\r
+    {\r
+      __osm_pr_rcv_get_port_pair_paths( p_rcv, p_madw , requester_port, p_src_port,\r
+                                        p_port, comp_mask, p_list );\r
+      p_port = (osm_port_t*)cl_qmap_next( &p_port->map_item );\r
+    }\r
+  }\r
+  else\r
+  {\r
+    /*\r
+      The dest port if fixed, so iterate over source ports.\r
+    */\r
+    p_port = (osm_port_t*)cl_qmap_head( p_tbl );\r
+    while( p_port != (osm_port_t*)cl_qmap_end( p_tbl ) )\r
+    {\r
+      __osm_pr_rcv_get_port_pair_paths( p_rcv, p_madw, requester_port, p_port,\r
+                                        p_dest_port, comp_mask, p_list );\r
+      p_port = (osm_port_t*)cl_qmap_next( &p_port->map_item );\r
+    }\r
+  }\r
+\r
+  OSM_LOG_EXIT( p_rcv->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static void\r
+__osm_pr_rcv_process_pair(\r
+  IN osm_pr_rcv_t*         const p_rcv,\r
+  IN const osm_madw_t*     const p_madw,\r
+  IN const osm_port_t*     const requester_port,\r
+  IN const osm_port_t*     const p_src_port,\r
+  IN const osm_port_t*     const p_dest_port,\r
+  IN const ib_net64_t      comp_mask,\r
+  IN cl_qlist_t*           const p_list )\r
+{\r
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_process_pair );\r
+\r
+  __osm_pr_rcv_get_port_pair_paths( p_rcv, p_madw, requester_port, p_src_port,\r
+                                    p_dest_port, comp_mask, p_list );\r
+\r
+  OSM_LOG_EXIT( p_rcv->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ *********************************************************************/\r
+static void\r
+__search_mgrp_by_mgid(\r
+  IN  cl_map_item_t* const      p_map_item,\r
+  IN  void*                     context )\r
+{\r
+  osm_mgrp_t*                   p_mgrp = (osm_mgrp_t*)p_map_item;\r
+  osm_sa_pr_mcmr_search_ctxt_t *p_ctxt = (osm_sa_pr_mcmr_search_ctxt_t *) context;\r
+  const ib_gid_t               *p_recvd_mgid;\r
+  osm_pr_rcv_t                 *p_rcv;\r
+  /* uint32_t  i; */\r
+\r
+  p_recvd_mgid = p_ctxt->p_mgid;\r
+  p_rcv = p_ctxt->p_rcv;\r
+\r
+  /* ignore groups marked for deletion */\r
+  if ( p_mgrp->to_be_deleted )\r
+    return;\r
+\r
+  /* compare entire MGID so different scope will not sneak in for\r
+     the same MGID */\r
+  if ( memcmp( &p_mgrp->mcmember_rec.mgid,\r
+                p_recvd_mgid,\r
+                sizeof(ib_gid_t) ) )\r
+    return;\r
+\r
+#if 0\r
+  for ( i = 0 ; i < sizeof(p_mgrp->mcmember_rec.mgid.multicast.raw_group_id); i++)\r
+  {\r
+    if ( p_mgrp->mcmember_rec.mgid.multicast.raw_group_id[i] !=\r
+         p_recvd_mgid->mgid.multicast.raw_group_id[i] )\r
+      return;\r
+  }\r
+#endif\r
+\r
+  if( p_ctxt->p_mgrp )\r
+  {\r
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+             "__search_mgrp_by_mgid: ERR 1F08: "\r
+             "Multiple MC groups for same MGID\n" );\r
+    return;\r
+  }\r
+  p_ctxt->p_mgrp = p_mgrp;\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+__get_mgrp_by_mgid(\r
+  IN osm_pr_rcv_t*             const p_rcv,\r
+  IN ib_path_rec_t*            p_recvd_path_rec,\r
+  OUT osm_mgrp_t **            pp_mgrp )\r
+{\r
+  osm_sa_pr_mcmr_search_ctxt_t mcmr_search_context;\r
+\r
+  mcmr_search_context.p_mgid = &p_recvd_path_rec->dgid;\r
+  mcmr_search_context.p_rcv = p_rcv;\r
+  mcmr_search_context.p_mgrp = NULL;\r
+\r
+  cl_qmap_apply_func( &p_rcv->p_subn->mgrp_mlid_tbl,\r
+                      __search_mgrp_by_mgid,\r
+                      &mcmr_search_context);\r
+\r
+  if( mcmr_search_context.p_mgrp == NULL )\r
+  {\r
+    return IB_NOT_FOUND;\r
+  }\r
+\r
+  *pp_mgrp = mcmr_search_context.p_mgrp;\r
+  return IB_SUCCESS;\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static osm_mgrp_t *\r
+__get_mgrp_by_mlid(\r
+  IN const osm_pr_rcv_t* const p_rcv,\r
+  IN ib_net16_t          const mlid )\r
+{\r
+  cl_map_item_t *        map_item;\r
+\r
+  map_item = cl_qmap_get( &p_rcv->p_subn->mgrp_mlid_tbl, mlid );\r
+\r
+  if( map_item == cl_qmap_end(&p_rcv->p_subn->mgrp_mlid_tbl) )\r
+  {\r
+    return NULL;\r
+  }\r
+\r
+  return (osm_mgrp_t *)map_item;\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static void\r
+__osm_pr_get_mgrp(\r
+  IN osm_pr_rcv_t*         const p_rcv,\r
+  IN const osm_madw_t*     const p_madw,\r
+  OUT osm_mgrp_t           **pp_mgrp )\r
+{\r
+  ib_path_rec_t*           p_pr;\r
+  const ib_sa_mad_t*       p_sa_mad;\r
+  ib_net64_t               comp_mask;\r
+  ib_api_status_t          status;\r
+\r
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_get_mgrp );\r
+\r
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );\r
+  p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );\r
+\r
+  comp_mask = p_sa_mad->comp_mask;\r
+\r
+  if( comp_mask & IB_PR_COMPMASK_DGID )\r
+  {\r
+    status = __get_mgrp_by_mgid( p_rcv, p_pr, pp_mgrp );\r
+    if( status != IB_SUCCESS )\r
+    {\r
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+               "__osm_pr_get_mgrp: ERR 1F09: "\r
+               "No MC group found for PathRecord destination GID\n" );\r
+      goto Exit;\r
+    }\r
+  }\r
+\r
+  if( comp_mask & IB_PR_COMPMASK_DLID )\r
+  {\r
+    if( *pp_mgrp)\r
+    {\r
+      /* check that the MLID in the MC group is */\r
+      /* the same as the DLID in the PathRecord */\r
+      if( (*pp_mgrp)->mlid != p_pr->dlid )\r
+      {\r
+       /* Note: perhaps this might be better indicated as an invalid request */\r
+        osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+                 "__osm_pr_get_mgrp: ERR 1F10: "\r
+                 "MC group MLID does not match PathRecord destination LID\n" );\r
+        *pp_mgrp = NULL;\r
+        goto Exit;\r
+      }\r
+    }\r
+    else\r
+    {\r
+      *pp_mgrp = __get_mgrp_by_mlid( p_rcv, p_pr->dlid );\r
+      if( *pp_mgrp == NULL)\r
+      {\r
+        osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+                 "__osm_pr_get_mgrp: ERR 1F11: "\r
+                 "No MC group found for PathRecord destination LID\n" );\r
+      }\r
+    }\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( p_rcv->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+__osm_pr_match_mgrp_attributes(\r
+  IN osm_pr_rcv_t*         const p_rcv,\r
+  IN const osm_madw_t*     const p_madw,\r
+  IN const osm_mgrp_t*     const p_mgrp )\r
+{\r
+  const ib_path_rec_t*     p_pr;\r
+  const ib_sa_mad_t*       p_sa_mad;\r
+  ib_net64_t               comp_mask;\r
+  ib_api_status_t          status = IB_ERROR;\r
+  uint32_t                 flow_label;\r
+  uint8_t                  sl;\r
+  uint8_t                  hop_limit;\r
+\r
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_match_mgrp_attributes );\r
+\r
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );\r
+  p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );\r
+\r
+  comp_mask = p_sa_mad->comp_mask;\r
+\r
+  /* If SGID and/or SLID specified, should validate as member of MC group */\r
+  /* Also, MTU, rate, packet lifetime, and raw traffic requested are not currently checked */\r
+  if( comp_mask & IB_PR_COMPMASK_PKEY )\r
+  {\r
+    if( p_pr->pkey != p_mgrp->mcmember_rec.pkey )\r
+      goto Exit;\r
+  }\r
+\r
+  ib_member_get_sl_flow_hop( p_mgrp->mcmember_rec.sl_flow_hop,\r
+                             &sl, &flow_label, &hop_limit );\r
+\r
+  if( comp_mask & IB_PR_COMPMASK_SL )\r
+  {\r
+    if( ib_path_rec_sl( p_pr ) != sl )\r
+      goto Exit;\r
+  }\r
+\r
+  /* If SubnAdmGet, assume NumbPaths of 1 (1.2 erratum) */\r
+  if( ( comp_mask & IB_PR_COMPMASK_NUMBPATH ) &&\r
+      ( p_sa_mad->method != IB_MAD_METHOD_GET ) )\r
+  {\r
+    if( ib_path_rec_num_path( p_pr ) == 0 )\r
+      goto Exit;\r
+  }\r
+\r
+  if( comp_mask & IB_PR_COMPMASK_FLOWLABEL )\r
+  {\r
+    if( ib_path_rec_flow_lbl( p_pr ) != flow_label )\r
+      goto Exit;\r
+  }\r
+\r
+  if( comp_mask & IB_PR_COMPMASK_HOPLIMIT )\r
+  {\r
+    if( ib_path_rec_hop_limit( p_pr ) != hop_limit )\r
+      goto Exit;\r
+  }\r
+\r
+  if( comp_mask & IB_PR_COMPMASK_TCLASS )\r
+  {\r
+    if( p_pr->tclass != p_mgrp->mcmember_rec.tclass )\r
+      goto Exit;\r
+  }\r
+\r
+  status = IB_SUCCESS;\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( p_rcv->p_log );\r
+  return( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static int\r
+__osm_pr_rcv_check_mcast_dest(\r
+  IN osm_pr_rcv_t*         const p_rcv,\r
+  IN const osm_madw_t*     const p_madw )\r
+{\r
+  const ib_path_rec_t*     p_pr;\r
+  const ib_sa_mad_t*       p_sa_mad;\r
+  ib_net64_t               comp_mask;\r
+  int                      is_multicast = 0;\r
+\r
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_check_mcast_dest );\r
+\r
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );\r
+  p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );\r
+\r
+  comp_mask = p_sa_mad->comp_mask;\r
+\r
+  if( comp_mask & IB_PR_COMPMASK_DGID )\r
+  {\r
+    is_multicast = ib_gid_is_multicast( &p_pr->dgid );\r
+    if( !is_multicast )\r
+      goto Exit;\r
+  }\r
+\r
+  if( comp_mask & IB_PR_COMPMASK_DLID )\r
+  {\r
+    if( cl_ntoh16( p_pr->dlid ) >= IB_LID_MCAST_START_HO &&\r
+        cl_ntoh16( p_pr->dlid ) <= IB_LID_MCAST_END_HO )\r
+      is_multicast = 1;\r
+    else if( is_multicast )\r
+    {\r
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+               "__osm_pr_rcv_check_mcast_dest: ERR 1F12: "\r
+               "PathRecord request indicates MGID but not MLID\n" );\r
+      is_multicast = -1;\r
+    }\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( p_rcv->p_log );\r
+  return( is_multicast );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static void\r
+__osm_pr_rcv_respond(\r
+  IN osm_pr_rcv_t*         const p_rcv,\r
+  IN const osm_madw_t*     const p_madw,\r
+  IN cl_qlist_t*           const p_list )\r
+{\r
+  osm_madw_t*              p_resp_madw;\r
+  const ib_sa_mad_t*       p_sa_mad;\r
+  ib_sa_mad_t*             p_resp_sa_mad;\r
+  size_t                   num_rec, pre_trim_num_rec;\r
+#ifndef VENDOR_RMPP_SUPPORT\r
+  size_t                  trim_num_rec;\r
+#endif\r
+  ib_path_rec_t*           p_resp_pr;\r
+  ib_api_status_t          status;\r
+  const ib_sa_mad_t*       p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );\r
+  osm_pr_item_t*           p_pr_item;\r
+  uint32_t                 i;\r
+\r
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_respond );\r
+\r
+  num_rec = cl_qlist_count( p_list );\r
+\r
+  /*\r
+   * C15-0.1.30:\r
+   * If we do a SubnAdmGet and got more than one record it is an error !\r
+   */\r
+  if (p_rcvd_mad->method == IB_MAD_METHOD_GET)\r
+  {\r
+    if (num_rec == 0)\r
+    {\r
+      osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );\r
+      goto Exit;\r
+    }\r
+    if (num_rec > 1)\r
+    {\r
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+               "__osm_pr_rcv_respond: ERR 1F13: "\r
+               "Got more than one record for SubnAdmGet (%zu)\n",\r
+               num_rec );\r
+      osm_sa_send_error( p_rcv->p_resp, p_madw,\r
+                         IB_SA_MAD_STATUS_TOO_MANY_RECORDS );\r
+      /* need to set the mem free ... */\r
+      p_pr_item = (osm_pr_item_t*)cl_qlist_remove_head( p_list );\r
+      while( p_pr_item != (osm_pr_item_t*)cl_qlist_end( p_list ) )\r
+      {\r
+        cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item );\r
+        p_pr_item = (osm_pr_item_t*)cl_qlist_remove_head( p_list );\r
+      }\r
+      goto Exit;\r
+    }\r
+  }\r
+\r
+  pre_trim_num_rec = num_rec;\r
+#ifndef VENDOR_RMPP_SUPPORT\r
+  trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_path_rec_t);\r
+  if (trim_num_rec < num_rec)\r
+  {\r
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,\r
+             "__osm_pr_rcv_respond: "\r
+             "Number of records:%u trimmed to:%u to fit in one MAD\n",\r
+             num_rec,trim_num_rec );\r
+    num_rec = trim_num_rec;\r
+  }\r
+#endif\r
+\r
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+           "__osm_pr_rcv_respond: "\r
+           "Generating response with %zu records\n", num_rec );\r
+\r
+  if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))\r
+  {\r
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );\r
+    goto Exit;\r
+  }\r
+\r
+  /*\r
+   * Get a MAD to reply. Address of Mad is in the received mad_wrapper\r
+   */\r
+  p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, p_madw->h_bind,\r
+                                  num_rec * sizeof(ib_path_rec_t) + IB_SA_MAD_HDR_SIZE,\r
+                                  &p_madw->mad_addr );\r
+  if( !p_resp_madw )\r
+  {\r
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+             "__osm_pr_rcv_respond: ERR 1F14: "\r
+             "Unable to allocate MAD\n" );\r
+\r
+    for( i = 0; i < num_rec; i++ )\r
+    {\r
+      p_pr_item = (osm_pr_item_t*)cl_qlist_remove_head( p_list );\r
+      cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item );\r
+    }\r
+\r
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES );\r
+    goto Exit;\r
+  }\r
+\r
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );\r
+  p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );\r
+\r
+  memcpy( p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE );\r
+  p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;\r
+  /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */\r
+  p_resp_sa_mad->sm_key = 0;\r
+  /* Fill in the offset (paylen will be done by the rmpp SAR) */\r
+  p_resp_sa_mad->attr_offset = ib_get_attr_offset( sizeof(ib_path_rec_t) );\r
+\r
+  p_resp_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );\r
+\r
+#ifndef VENDOR_RMPP_SUPPORT\r
+  /* we support only one packet RMPP - so we will set the first and\r
+     last flags for gettable */\r
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)\r
+  {\r
+    p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;\r
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;\r
+  }\r
+#else\r
+  /* forcefully define the packet as RMPP one */\r
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)\r
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;\r
+#endif\r
+\r
+  for ( i = 0; i < pre_trim_num_rec; i++ )\r
+  {\r
+    p_pr_item = (osm_pr_item_t*)cl_qlist_remove_head( p_list );\r
+    /* copy only if not trimmed */\r
+    if (i < num_rec)\r
+        *p_resp_pr = p_pr_item->path_rec;\r
+\r
+    cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item );\r
+    p_resp_pr++;\r
+  }\r
+\r
+  CL_ASSERT( cl_is_qlist_empty( p_list ) );\r
+\r
+  status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+             "__osm_pr_rcv_respond: ERR 1F15: "\r
+             "Unable to send MAD (%s)\n", ib_get_err_str( status ) );\r
+    /*  osm_mad_pool_put( p_rcv->p_mad_pool, p_resp_madw ); */\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( p_rcv->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_pr_rcv_process(\r
+  IN osm_pr_rcv_t*         const p_rcv,\r
+  IN const osm_madw_t*     const p_madw )\r
+{\r
+  const ib_path_rec_t*     p_pr;\r
+  const ib_sa_mad_t*       p_sa_mad;\r
+  const osm_port_t*        p_src_port;\r
+  const osm_port_t*        p_dest_port;\r
+  cl_qlist_t               pr_list;\r
+  ib_net16_t               sa_status;\r
+  osm_port_t*              requester_port;\r
+  int ret;\r
+\r
+  OSM_LOG_ENTER( p_rcv->p_log, osm_pr_rcv_process );\r
+\r
+  CL_ASSERT( p_madw );\r
+\r
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );\r
+  p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );\r
+\r
+  CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_PATH_RECORD );\r
+\r
+  /* we only support SubnAdmGet and SubnAdmGetTable methods */\r
+  if ((p_sa_mad->method != IB_MAD_METHOD_GET) &&\r
+      (p_sa_mad->method != IB_MAD_METHOD_GETTABLE)) {\r
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+             "osm_pr_rcv_process: ERR 1F17: " \r
+             "Unsupported Method (%s)\n",\r
+             ib_get_sa_method_str( p_sa_mad->method ) );\r
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );\r
+    goto Exit;\r
+  }\r
+\r
+  /* update the requester physical port. */\r
+  requester_port = osm_get_port_by_mad_addr( p_rcv->p_log, p_rcv->p_subn,\r
+                                             osm_madw_get_mad_addr_ptr( p_madw ) );\r
+  if( requester_port == NULL )\r
+  {\r
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+             "osm_pr_rcv_process: ERR 1F16: "\r
+             "Cannot find requester physical port\n" );\r
+    goto Exit;\r
+  }\r
+\r
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )\r
+    osm_dump_path_record( p_rcv->p_log, p_pr, OSM_LOG_DEBUG );\r
+\r
+  cl_qlist_init( &pr_list );\r
+\r
+  /*\r
+    Most SA functions (including this one) are read-only on the\r
+    subnet object, so we grab the lock non-exclusively.\r
+  */\r
+  cl_plock_acquire( p_rcv->p_lock );\r
+\r
+  /* Handle multicast destinations separately */\r
+  if( (ret = __osm_pr_rcv_check_mcast_dest( p_rcv, p_madw )) < 0 )\r
+  {\r
+    /* Multicast DGID with unicast DLID */\r
+    cl_plock_release( p_rcv->p_lock );\r
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_INVALID_FIELD );\r
+    goto Exit;\r
+  }\r
+\r
+  if(ret > 0)\r
+    goto McastDest;\r
+\r
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+           "osm_pr_rcv_process: "\r
+           "Unicast destination requested\n" );\r
+\r
+  sa_status = __osm_pr_rcv_get_end_points( p_rcv, p_madw,\r
+                                           &p_src_port, &p_dest_port );\r
+\r
+  if( sa_status == IB_SA_MAD_STATUS_SUCCESS )\r
+  {\r
+    /*\r
+      What happens next depends on the type of endpoint information\r
+      that was specified....\r
+    */\r
+    if( p_src_port )\r
+    {\r
+      if( p_dest_port )\r
+        __osm_pr_rcv_process_pair( p_rcv, p_madw, requester_port,\r
+                                   p_src_port, p_dest_port,\r
+                                   p_sa_mad->comp_mask, &pr_list );\r
+      else\r
+        __osm_pr_rcv_process_half( p_rcv, p_madw, requester_port,\r
+                                   p_src_port, NULL,\r
+                                   p_sa_mad->comp_mask, &pr_list );\r
+    }\r
+    else\r
+    {\r
+      if( p_dest_port )\r
+        __osm_pr_rcv_process_half( p_rcv, p_madw, requester_port,\r
+                                   NULL, p_dest_port,\r
+                                   p_sa_mad->comp_mask, &pr_list );\r
+      else\r
+        /*\r
+          Katie, bar the door!\r
+        */\r
+        __osm_pr_rcv_process_world( p_rcv, p_madw, requester_port,\r
+                                    p_sa_mad->comp_mask, &pr_list );\r
+    }\r
+  }\r
+  goto Unlock;\r
+\r
+ McastDest:\r
+  osm_log(p_rcv->p_log, OSM_LOG_DEBUG,\r
+             "osm_pr_rcv_process: "\r
+             "Multicast destination requested\n" );\r
+  {\r
+    osm_mgrp_t *p_mgrp = NULL;\r
+    ib_api_status_t status;\r
+    osm_pr_item_t* p_pr_item;\r
+    uint32_t flow_label;\r
+    uint8_t  sl;\r
+    uint8_t  hop_limit;\r
+\r
+    /* First, get the MC info */\r
+    __osm_pr_get_mgrp( p_rcv, p_madw, &p_mgrp );\r
+\r
+    if ( p_mgrp )\r
+    {\r
+      /* Make sure the rest of the PathRecord matches the MC group attributes */\r
+      status = __osm_pr_match_mgrp_attributes( p_rcv, p_madw, p_mgrp );\r
+      if ( status == IB_SUCCESS )\r
+      {\r
+        p_pr_item = (osm_pr_item_t*)cl_qlock_pool_get( &p_rcv->pr_pool );\r
+        if( p_pr_item == NULL )\r
+        {\r
+          osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+                   "osm_pr_rcv_process: ERR 1F18: "\r
+                   "Unable to allocate path record for MC group\n" );\r
+        }\r
+        else\r
+        {\r
+         /* Copy PathRecord request into response */\r
+          p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );\r
+          p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );\r
+          p_pr_item->path_rec = *p_pr;\r
+\r
+          /* Now, use the MC info to cruft up the PathRecord response */        \r
+          p_pr_item->path_rec.dgid = p_mgrp->mcmember_rec.mgid;\r
+          p_pr_item->path_rec.dlid = p_mgrp->mcmember_rec.mlid;\r
+         p_pr_item->path_rec.tclass = p_mgrp->mcmember_rec.tclass;\r
+         p_pr_item->path_rec.num_path = 1;\r
+         p_pr_item->path_rec.pkey = p_mgrp->mcmember_rec.pkey;\r
+\r
+         /* MTU, rate, and packet lifetime should be exactly */\r
+         p_pr_item->path_rec.mtu = (2<<6) | p_mgrp->mcmember_rec.mtu;\r
+          p_pr_item->path_rec.rate = (2<<6) | p_mgrp->mcmember_rec.rate;\r
+          p_pr_item->path_rec.pkt_life = (2<<6) | p_mgrp->mcmember_rec.pkt_life;\r
+\r
+         /* SL, Hop Limit, and Flow Label */\r
+          ib_member_get_sl_flow_hop( p_mgrp->mcmember_rec.sl_flow_hop,\r
+                                     &sl, &flow_label, &hop_limit );\r
+         p_pr_item->path_rec.qos_class_sl = cl_hton16( sl );\r
+          p_pr_item->path_rec.hop_flow_raw = (uint32_t)(hop_limit) |\r
+                                             (flow_label << 8);\r
+\r
+          cl_qlist_insert_tail( &pr_list,\r
+                                (cl_list_item_t*)&p_pr_item->pool_item );\r
+\r
+        }\r
+      }\r
+      else\r
+      {\r
+        osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+                 "osm_pr_rcv_process: ERR 1F19: "\r
+                 "MC group attributes don't match PathRecord request\n" );\r
+      }\r
+    }\r
+  }\r
+\r
+ Unlock:\r
+  cl_plock_release( p_rcv->p_lock );\r
+\r
+  /* Now, (finally) respond to the PathRecord request */\r
+  __osm_pr_rcv_respond( p_rcv, p_madw, &pr_list );\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( p_rcv->p_log );\r
+}\r
+\r
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_path_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_path_record_ctrl.c
new file mode 100644 (file)
index 0000000..2a9bc77
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_path_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_pr_rcv_ctrl_t.
+ * This object represents the PathRecord request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_path_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pr_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_pr_rcv_process( ((osm_pr_rcv_ctrl_t*)context)->p_rcv,
+                      (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pr_rcv_ctrl_construct(
+  IN osm_pr_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pr_rcv_ctrl_destroy(
+  IN osm_pr_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pr_rcv_ctrl_init(
+  IN osm_pr_rcv_ctrl_t* const p_ctrl,
+  IN osm_pr_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_pr_rcv_ctrl_init );
+
+  osm_pr_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_PATH_RECORD,
+    __osm_pr_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_pr_rcv_ctrl_init: ERR 2001: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_pkey_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_pkey_record.c
new file mode 100644 (file)
index 0000000..0e5ffee
--- /dev/null
@@ -0,0 +1,590 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_pkey_record.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_pkey_record.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_PKEY_REC_RCV_POOL_MIN_SIZE      32
+#define OSM_PKEY_REC_RCV_POOL_GROW_SIZE     32
+
+typedef  struct _osm_pkey_item
+{
+  cl_pool_item_t           pool_item;
+  ib_pkey_table_record_t   rec;
+} osm_pkey_item_t;
+
+typedef  struct _osm_pkey_search_ctxt
+{
+  const ib_pkey_table_record_t*   p_rcvd_rec;
+  ib_net64_t                      comp_mask;
+  uint16_t                        block_num;
+  cl_qlist_t*                     p_list;
+  osm_pkey_rec_rcv_t*             p_rcv;
+  const osm_physp_t*              p_req_physp;
+} osm_pkey_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rec_rcv_construct(
+  IN osm_pkey_rec_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+  cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rec_rcv_destroy(
+  IN osm_pkey_rec_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_pkey_rec_rcv_destroy );
+  cl_qlock_pool_destroy( &p_rcv->pool );
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pkey_rec_rcv_init(
+  IN osm_pkey_rec_rcv_t*     const p_rcv,
+  IN osm_sa_resp_t*        const p_resp,
+  IN osm_mad_pool_t*    const p_mad_pool,
+  IN const osm_subn_t*     const p_subn,
+  IN osm_log_t*            const p_log,
+  IN cl_plock_t*           const p_lock )
+{
+  ib_api_status_t          status;
+
+  OSM_LOG_ENTER( p_log, osm_pkey_rec_rcv_init );
+
+  osm_pkey_rec_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_resp = p_resp;
+  p_rcv->p_mad_pool = p_mad_pool;
+
+  /* used for matching records collection */
+  status = cl_qlock_pool_init( &p_rcv->pool,
+                               OSM_PKEY_REC_RCV_POOL_MIN_SIZE,
+                               0,
+                               OSM_PKEY_REC_RCV_POOL_GROW_SIZE,
+                               sizeof(osm_pkey_item_t),
+                               NULL, NULL, NULL );
+
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_pkey_create(
+  IN osm_pkey_rec_rcv_t*       const p_rcv,
+  IN osm_physp_t*              const p_physp,
+  IN osm_pkey_search_ctxt_t*   const p_ctxt,
+  IN uint16_t                  block )
+{
+  osm_pkey_item_t*             p_rec_item;
+  uint16_t                     lid;
+  ib_api_status_t              status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_pkey_create );
+
+  p_rec_item = (osm_pkey_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+  if( p_rec_item == NULL )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sa_pkey_create: ERR 4602: "
+             "cl_qlock_pool_get failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+  if (p_physp->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH)
+  {
+    lid = osm_physp_get_port_info_ptr( p_physp )->base_lid;
+  }
+  else
+  {
+    lid = osm_node_get_base_lid( p_physp->p_node, 0 );
+  }
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_sa_pkey_create: "
+             "New P_Key table for: port 0x%016" PRIx64
+             ", lid 0x%X, port# 0x%X Block:%u\n",
+             cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+             cl_ntoh16( lid ), osm_physp_get_port_num( p_physp ),
+             block
+             );
+  }
+
+  memset( &p_rec_item->rec, 0, sizeof( p_rec_item->rec ) );
+
+  p_rec_item->rec.lid = lid;
+  p_rec_item->rec.block_num = block;
+  p_rec_item->rec.port_num = osm_physp_get_port_num( p_physp );
+  p_rec_item->rec.pkey_tbl =
+    *(osm_pkey_tbl_block_get(osm_physp_get_pkey_tbl(p_physp), block));
+
+  cl_qlist_insert_tail( p_ctxt->p_list,
+                        (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_pkey_check_physp(
+  IN osm_pkey_rec_rcv_t*       const p_rcv,
+  IN osm_physp_t*              const p_physp,
+  osm_pkey_search_ctxt_t*      const p_ctxt )
+{
+  ib_net64_t comp_mask = p_ctxt->comp_mask;
+  uint16_t   block, num_blocks;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_pkey_check_physp );
+
+  /* we got here with the phys port - all is left is to get the right block */
+  if ( comp_mask & IB_PKEY_COMPMASK_BLOCK )
+  {
+    __osm_sa_pkey_create( p_rcv, p_physp, p_ctxt, p_ctxt->block_num);
+  }
+  else
+  {
+    num_blocks = 
+      osm_pkey_tbl_get_num_blocks( osm_physp_get_pkey_tbl( p_physp ));
+    for (block = 0; block < num_blocks; block++) {
+      __osm_sa_pkey_create( p_rcv, p_physp, p_ctxt, block );
+    }
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_pkey_by_comp_mask(
+  IN osm_pkey_rec_rcv_t*   const p_rcv,
+  IN const osm_port_t*     const p_port,
+  osm_pkey_search_ctxt_t*  const p_ctxt )
+{
+  const ib_pkey_table_record_t*   p_rcvd_rec;
+  ib_net64_t               comp_mask;
+  osm_physp_t *            p_physp;
+  uint8_t                  port_num;
+  uint8_t                  num_ports;
+  const osm_physp_t*       p_req_physp;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_pkey_by_comp_mask );
+
+  p_rcvd_rec = p_ctxt->p_rcvd_rec;
+  comp_mask = p_ctxt->comp_mask;
+  port_num = p_rcvd_rec->port_num;
+  p_req_physp = p_ctxt->p_req_physp;
+
+  /* if this is a switch port we can search all ports
+     otherwise we must be looking on port 0 */
+  if ( p_port->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH )
+  {
+    /* we put it in the comp mask and port num */
+    port_num = p_port->default_port_num;
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_sa_pkey_by_comp_mask:  "
+             "Using Physical Default Port Number: 0x%X (for End Node)\n",
+             port_num);
+    comp_mask |= IB_PKEY_COMPMASK_PORT;
+  }
+
+  if( comp_mask & IB_PKEY_COMPMASK_PORT )
+  {
+    if (port_num < osm_port_get_num_physp( p_port ))
+    {
+      p_physp = osm_port_get_phys_ptr( p_port, port_num );
+      /* Check that the p_physp is valid, and that is shares a pkey
+         with the p_req_physp. */
+      if( p_physp && osm_physp_is_valid( p_physp ) &&
+          (osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp)) )
+        __osm_sa_pkey_check_physp( p_rcv, p_physp, p_ctxt );
+    }
+    else
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_sa_pkey_by_comp_mask: ERR 4603: "
+               "Given Physical Port Number: 0x%X is out of range should be < 0x%X\n",
+               port_num, osm_port_get_num_physp( p_port ));
+      goto Exit;
+    }
+  }
+  else
+  {
+    num_ports = osm_port_get_num_physp( p_port );
+    for( port_num = 0; port_num < num_ports; port_num++ )
+    {
+      p_physp = osm_port_get_phys_ptr( p_port, port_num );
+      if( p_physp == NULL )
+        continue;
+
+      if( !osm_physp_is_valid( p_physp ) )
+        continue;
+
+      /* if the requester and the p_physp don't share a pkey -
+         continue */
+      if (!osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp ) )
+        continue;
+
+      __osm_sa_pkey_check_physp( p_rcv, p_physp, p_ctxt );
+    }
+  }
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_pkey_by_comp_mask_cb(
+  IN cl_map_item_t*        const p_map_item,
+  IN void*                 context )
+{
+  const osm_port_t*        const p_port = (osm_port_t*)p_map_item;
+  osm_pkey_search_ctxt_t*  const p_ctxt = (osm_pkey_search_ctxt_t *)context;
+
+  __osm_sa_pkey_by_comp_mask( p_ctxt->p_rcv, p_port, p_ctxt );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rec_rcv_process(
+  IN osm_pkey_rec_rcv_t*   const p_rcv,
+  IN const osm_madw_t*     const p_madw )
+{
+  const ib_sa_mad_t*       p_rcvd_mad;
+  const ib_pkey_table_record_t*   p_rcvd_rec;
+  const cl_ptr_vector_t*   p_tbl;
+  const osm_port_t*        p_port = NULL;
+  const ib_pkey_table_t*   p_pkey;
+  cl_qlist_t               rec_list;
+  osm_madw_t*              p_resp_madw;
+  ib_sa_mad_t*             p_resp_sa_mad;
+  ib_pkey_table_record_t*  p_resp_rec;
+  uint32_t                 num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  uint32_t                trim_num_rec;
+#endif
+  uint32_t                 i;
+  osm_pkey_search_ctxt_t   context;
+  osm_pkey_item_t*         p_rec_item;
+  ib_api_status_t          status = IB_SUCCESS;
+  ib_net64_t               comp_mask;
+  osm_physp_t*             p_req_physp;
+
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_pkey_rec_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_rcvd_rec = (ib_pkey_table_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+  comp_mask = p_rcvd_mad->comp_mask;
+
+  CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_PKEY_TBL_RECORD );
+
+  /* we only support SubnAdmGet and SubnAdmGetTable methods */
+  if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) &&
+       (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_pkey_rec_rcv_process: ERR 4605: "
+             "Unsupported Method (%s)\n",
+             ib_get_sa_method_str( p_rcvd_mad->method ) );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+    goto Exit;
+  }
+
+  /*
+     p922 - P_KeyTableRecords shall only be provided in response
+     to trusted requests.
+     Check that the requester is a trusted one.
+  */
+  if ( p_rcvd_mad->sm_key != p_rcv->p_subn->opt.sm_key )
+  {
+    /* This is not a trusted requester! */
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_pkey_rec_rcv_process ERR 4608: "
+             "Request from non-trusted requester: "
+             "Given SM_Key:0x%016" PRIx64 "\n",
+             cl_ntoh64(p_rcvd_mad->sm_key) );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID );
+    goto Exit;
+  }
+
+  /* update the requester physical port. */
+  p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+                                          p_rcv->p_subn,
+                                          osm_madw_get_mad_addr_ptr(p_madw) );
+  if (p_req_physp == NULL)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_pkey_rec_rcv_process: ERR 4604: "
+             "Cannot find requester physical port\n" );
+    goto Exit;
+  }
+
+  p_pkey = (ib_pkey_table_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+
+  cl_qlist_init( &rec_list );
+
+  context.p_rcvd_rec = p_rcvd_rec;
+  context.p_list = &rec_list;
+  context.comp_mask = p_rcvd_mad->comp_mask;
+  context.p_rcv = p_rcv;
+  context.block_num = p_rcvd_rec->block_num;
+  context.p_req_physp = p_req_physp;
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+           "osm_pkey_rec_rcv_process: "
+           "Got Query Lid:0x%04X(%02X), Block:0x%02X(%02X), Port:0x%02X(%02X)\n",
+           cl_ntoh16(p_rcvd_rec->lid),  (comp_mask & IB_PKEY_COMPMASK_LID) != 0,
+           p_rcvd_rec->port_num, (comp_mask & IB_PKEY_COMPMASK_PORT) != 0,
+           p_rcvd_rec->block_num, (comp_mask & IB_PKEY_COMPMASK_BLOCK) != 0 );
+
+  cl_plock_acquire( p_rcv->p_lock );
+
+  /*
+    If the user specified a LID, it obviously narrows our
+    work load, since we don't have to search every port
+  */
+  if( comp_mask & IB_PKEY_COMPMASK_LID )
+  {
+
+    p_tbl = &p_rcv->p_subn->port_lid_tbl;
+
+    CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 );
+
+    status = osm_get_port_by_base_lid( p_rcv->p_subn, p_rcvd_rec->lid, &p_port );
+    if ( ( status != IB_SUCCESS ) || ( p_port == NULL ) )
+    {
+      status = IB_NOT_FOUND;
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_pkey_rec_rcv_process: ERR 460B: "
+               "No port found with LID 0x%x\n",
+               cl_ntoh16(p_rcvd_rec->lid) );
+    }
+  }
+
+  if ( status == IB_SUCCESS )
+  {
+    /* if we got a unique port - no need for a port search */
+    if( p_port )
+      /* this does the loop on all the port phys ports */
+      __osm_sa_pkey_by_comp_mask( p_rcv, p_port, &context );
+    else
+    {
+      cl_qmap_apply_func( &p_rcv->p_subn->port_guid_tbl,
+                          __osm_sa_pkey_by_comp_mask_cb,
+                          &context );
+    }
+  }
+
+  cl_plock_release( p_rcv->p_lock );
+
+  num_rec = cl_qlist_count( &rec_list );
+
+  /*
+   * C15-0.1.30:
+   * If we do a SubnAdmGet and got more than one record it is an error !
+   */
+  if (p_rcvd_mad->method == IB_MAD_METHOD_GET)
+  {
+    if (num_rec == 0)
+    {
+      osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+      goto Exit;
+    }
+    if (num_rec > 1)
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_pkey_rec_rcv_process: ERR 460A: "
+               "Got more than one record for SubnAdmGet (%u)\n",
+               num_rec );
+      osm_sa_send_error( p_rcv->p_resp, p_madw,
+                         IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+
+      /* need to set the mem free ... */
+      p_rec_item = (osm_pkey_item_t*)cl_qlist_remove_head( &rec_list );
+      while( p_rec_item != (osm_pkey_item_t*)cl_qlist_end( &rec_list ) )
+      {
+        cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+        p_rec_item = (osm_pkey_item_t*)cl_qlist_remove_head( &rec_list );
+      }
+
+      goto Exit;
+    }
+  }
+
+  pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_pkey_table_record_t);
+  if (trim_num_rec < num_rec)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "osm_pkey_rec_rcv_process: "
+             "Number of records:%u trimmed to:%u to fit in one MAD\n",
+             num_rec, trim_num_rec );
+    num_rec = trim_num_rec;
+  }
+#endif
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+           "osm_pkey_rec_rcv_process: "
+           "Returning %u records\n", num_rec );
+
+  if((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+  {
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+    goto Exit;
+  }
+
+  /*
+   * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+   */ 
+  p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+                                  p_madw->h_bind,
+                                  num_rec * sizeof(ib_pkey_table_record_t) + IB_SA_MAD_HDR_SIZE,
+                                  &p_madw->mad_addr );
+
+  if( !p_resp_madw )
+  {
+    osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+            "osm_pkey_rec_rcv_process: ERR 4606: "
+            "osm_mad_pool_get failed\n" );
+
+    for( i = 0; i < num_rec; i++ )
+    {
+      p_rec_item = (osm_pkey_item_t*)cl_qlist_remove_head( &rec_list );
+      cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    }
+
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES );
+    goto Exit;
+  }
+
+  p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+  /*
+    Copy the MAD header back into the response mad.
+    Set the 'R' bit and the payload length,
+    Then copy all records from the list into the response payload.
+  */
+
+  memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+  /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
+  p_resp_sa_mad->sm_key = 0;
+
+  /* Fill in the offset (paylen will be done by the rmpp SAR) */
+  p_resp_sa_mad->attr_offset =
+    ib_get_attr_offset( sizeof(ib_pkey_table_record_t) );
+
+  p_resp_rec = (ib_pkey_table_record_t*)
+    ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+#ifndef VENDOR_RMPP_SUPPORT
+  /* we support only one packet RMPP - so we will set the first and
+     last flags for gettable */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+  {
+    p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+  }
+#else
+  /* forcefully define the packet as RMPP one */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+  for( i = 0; i < pre_trim_num_rec; i++ )
+  {
+    p_rec_item = (osm_pkey_item_t*)cl_qlist_remove_head( &rec_list );
+    /* copy only if not trimmed */
+    if (i < num_rec)
+    {
+      *p_resp_rec = p_rec_item->rec;
+    }
+    cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    p_resp_rec++;
+  }
+
+  CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+  status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE);
+  if (status != IB_SUCCESS)
+  {
+    osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+            "osm_pkey_rec_rcv_process: ERR 4607: "
+            "osm_vendor_send status = %s\n",
+            ib_get_err_str(status));
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_pkey_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_pkey_record_ctrl.c
new file mode 100644 (file)
index 0000000..0aefe39
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_pkey_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_pkey_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_pkey_rec_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_pkey_rec_rcv_process( ((osm_pkey_rec_rcv_ctrl_t*)context)->p_rcv,
+                            (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rec_rcv_ctrl_construct(
+  IN osm_pkey_rec_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rec_rcv_ctrl_destroy(
+  IN osm_pkey_rec_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pkey_rec_rcv_ctrl_init(
+  IN osm_pkey_rec_rcv_ctrl_t* const p_ctrl,
+  IN osm_pkey_rec_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_pkey_rec_rcv_ctrl_init );
+
+  osm_pkey_rec_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_PKEY_TBL_RECORD,
+    __osm_pkey_rec_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_pkey_rec_rcv_ctrl_init: ERR 4701: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_portinfo_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_portinfo_record.c
new file mode 100644 (file)
index 0000000..29bf18b
--- /dev/null
@@ -0,0 +1,878 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_portinfo_record.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_pir_rcv_t.
+ * This object represents the PortInfoRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.10 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_portinfo_record.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_PIR_RCV_POOL_MIN_SIZE      32
+#define OSM_PIR_RCV_POOL_GROW_SIZE     32
+
+typedef  struct _osm_pir_item
+{
+  cl_pool_item_t           pool_item;
+  ib_portinfo_record_t     rec;
+} osm_pir_item_t;
+
+typedef  struct _osm_pir_search_ctxt
+{
+  const ib_portinfo_record_t* p_rcvd_rec;
+  ib_net64_t               comp_mask;
+  cl_qlist_t*              p_list;
+  osm_pir_rcv_t*           p_rcv;
+  const osm_physp_t*       p_req_physp;
+  boolean_t                is_enhanced_comp_mask;
+} osm_pir_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pir_rcv_construct(
+  IN osm_pir_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+  cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pir_rcv_destroy(
+  IN osm_pir_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_pir_rcv_destroy );
+  cl_qlock_pool_destroy( &p_rcv->pool );
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pir_rcv_init(
+  IN osm_pir_rcv_t*  const p_rcv,
+  IN osm_sa_resp_t*  const p_resp,
+  IN osm_mad_pool_t* const p_mad_pool,
+  IN osm_subn_t*     const p_subn,
+  IN osm_log_t*      const p_log,
+  IN cl_plock_t*     const p_lock )
+{
+  ib_api_status_t          status;
+
+  OSM_LOG_ENTER( p_log, osm_pir_rcv_init );
+
+  osm_pir_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_resp = p_resp;
+  p_rcv->p_mad_pool = p_mad_pool;
+
+  status = cl_qlock_pool_init( &p_rcv->pool,
+                               OSM_PIR_RCV_POOL_MIN_SIZE,
+                               0,
+                               OSM_PIR_RCV_POOL_GROW_SIZE,
+                               sizeof(osm_pir_item_t),
+                               NULL, NULL, NULL );
+
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_pir_rcv_new_pir(
+  IN osm_pir_rcv_t*        const p_rcv,
+  IN const osm_physp_t*    const p_physp,
+  IN cl_qlist_t*           const p_list,
+  IN ib_net16_t            const lid )
+{
+  osm_pir_item_t*          p_rec_item;
+  ib_api_status_t          status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pir_rcv_new_pir );
+
+  p_rec_item = (osm_pir_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+  if( p_rec_item == NULL )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_pir_rcv_new_pir: ERR 2102: "
+             "cl_qlock_pool_get failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_pir_rcv_new_pir: "
+             "New PortInfoRecord: port 0x%016" PRIx64
+             ", lid 0x%X, port# 0x%X\n",
+             cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+             cl_ntoh16( lid ), osm_physp_get_port_num( p_physp ) );
+  }
+
+  memset( &p_rec_item->rec, 0, sizeof( p_rec_item->rec ) );
+
+  p_rec_item->rec.lid = lid;
+  p_rec_item->rec.port_info = *osm_physp_get_port_info_ptr( p_physp );
+  p_rec_item->rec.port_num = osm_physp_get_port_num( p_physp );
+
+  cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_pir_create(
+  IN osm_pir_rcv_t*           const p_rcv,
+  IN const osm_physp_t*       const p_physp,
+  IN osm_pir_search_ctxt_t*   const p_ctxt )
+{
+  uint8_t                     lmc;
+  uint16_t                    max_lid_ho;
+  uint16_t                    base_lid_ho;
+  uint16_t                    match_lid_ho;
+  osm_physp_t                *p_node_physp;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_pir_create );
+
+  if (p_physp->p_node->sw)
+  {
+    p_node_physp = osm_node_get_physp_ptr( p_physp->p_node, 0 );
+    base_lid_ho = cl_ntoh16( osm_physp_get_base_lid( p_node_physp ) );
+    lmc = osm_switch_sp0_is_lmc_capable(p_physp->p_node->sw, p_rcv->p_subn) ?
+      osm_physp_get_lmc( p_node_physp ) : 0;
+  }
+  else
+  {
+    lmc = osm_physp_get_lmc( p_physp );
+    base_lid_ho = cl_ntoh16( osm_physp_get_base_lid( p_physp ) );
+  }
+  max_lid_ho = (uint16_t)( base_lid_ho + (1 << lmc) - 1 );
+
+  if( p_ctxt->comp_mask & IB_PIR_COMPMASK_LID )
+  {
+    match_lid_ho = cl_ntoh16( p_ctxt->p_rcvd_rec->lid );
+
+    /*
+      We validate that the lid belongs to this node.
+    */
+    if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+               "__osm_sa_pir_create: "
+               "Comparing LID: 0x%X <= 0x%X <= 0x%X\n",
+               base_lid_ho, match_lid_ho, max_lid_ho
+               );
+    }
+
+    if ( match_lid_ho < base_lid_ho || match_lid_ho > max_lid_ho )
+      goto Exit;
+  }
+
+  __osm_pir_rcv_new_pir( p_rcv, p_physp, p_ctxt->p_list,
+                         cl_hton16( base_lid_ho ) );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_pir_check_physp(
+  IN osm_pir_rcv_t*        const p_rcv,
+  IN const osm_physp_t*    const p_physp,
+  osm_pir_search_ctxt_t*   const p_ctxt )
+{
+  const ib_portinfo_record_t* p_rcvd_rec;
+  ib_net64_t               comp_mask;
+  const ib_port_info_t*    p_comp_pi;
+  const ib_port_info_t*    p_pi;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_pir_check_physp );
+
+  p_rcvd_rec = p_ctxt->p_rcvd_rec;
+  comp_mask = p_ctxt->comp_mask;
+  p_comp_pi = &p_rcvd_rec->port_info;
+  p_pi = osm_physp_get_port_info_ptr( p_physp );
+
+  osm_dump_port_info(
+    p_rcv->p_log,
+    osm_node_get_node_guid( p_physp->p_node ),
+    p_physp->port_guid,
+    p_physp->port_num,
+    &p_physp->port_info,
+    OSM_LOG_DEBUG );
+    
+  /* We have to re-check the base_lid, since if the given
+     base_lid in p_pi is zero - we are comparing on all ports. */     
+  if( comp_mask & IB_PIR_COMPMASK_BASELID )
+  {
+    if( p_comp_pi->base_lid != p_pi->base_lid )
+      goto Exit;
+  }
+  if( comp_mask & IB_PIR_COMPMASK_MKEY )
+  {
+    if( p_comp_pi->m_key != p_pi->m_key )
+      goto Exit;
+  }
+  if( comp_mask & IB_PIR_COMPMASK_GIDPRE )
+  {
+    if( p_comp_pi->subnet_prefix != p_pi->subnet_prefix )
+      goto Exit;
+  }
+  if( comp_mask & IB_PIR_COMPMASK_SMLID )
+  {
+    if( p_comp_pi->master_sm_base_lid != p_pi->master_sm_base_lid )
+      goto Exit;
+  }
+  
+  /* IBTA 1.2 errata provides support for bitwise compare if the bit 31 
+     of the attribute modifier of the Get/GetTable is set */
+  if( comp_mask & IB_PIR_COMPMASK_CAPMASK )
+  {
+    if (p_ctxt->is_enhanced_comp_mask)
+    {
+      if ( ( ( p_comp_pi->capability_mask & p_pi->capability_mask ) != p_comp_pi->capability_mask) )
+        goto Exit; 
+    }
+    else
+    {
+      if( p_comp_pi->capability_mask != p_pi->capability_mask )
+        goto Exit;
+    }
+  }
+
+  if( comp_mask & IB_PIR_COMPMASK_DIAGCODE )
+  {
+    if( p_comp_pi->diag_code != p_pi->diag_code )
+      goto Exit;
+  }
+  if( comp_mask & IB_PIR_COMPMASK_MKEYLEASEPRD )
+  {
+    if( p_comp_pi->m_key_lease_period != p_pi->m_key_lease_period )
+      goto Exit;
+  }
+  if( comp_mask & IB_PIR_COMPMASK_LOCALPORTNUM )
+  {
+    if( p_comp_pi->local_port_num != p_pi->local_port_num )
+      goto Exit;
+  }
+  if( comp_mask & IB_PIR_COMPMASK_LNKWIDTHSUPPORT )
+  {
+    if( p_comp_pi->link_width_supported != p_pi->link_width_supported )
+      goto Exit;
+  }
+  if( comp_mask & IB_PIR_COMPMASK_LNKWIDTHACTIVE )
+  {
+    if( p_comp_pi->link_width_active != p_pi->link_width_active )
+      goto Exit;
+  }
+  if( comp_mask & IB_PIR_COMPMASK_LINKWIDTHENABLED )
+  {
+    if( p_comp_pi->link_width_enabled != p_pi->link_width_enabled )
+      goto Exit;
+  }
+  if( comp_mask & IB_PIR_COMPMASK_LNKSPEEDSUPPORT )
+  {
+    if( ib_port_info_get_link_speed_sup( p_comp_pi )!=
+        ib_port_info_get_link_speed_sup( p_pi) )
+      goto Exit;
+  }
+  if( comp_mask & IB_PIR_COMPMASK_PORTSTATE )
+  {
+    if( ib_port_info_get_port_state( p_comp_pi ) !=
+        ib_port_info_get_port_state( p_pi ) )
+      goto Exit;
+  }
+  if ( comp_mask & IB_PIR_COMPMASK_PORTPHYSTATE )
+  {
+    if ( ib_port_info_get_port_phys_state( p_comp_pi ) !=
+         ib_port_info_get_port_phys_state( p_pi ) )
+      goto Exit;
+  }
+  if ( comp_mask & IB_PIR_COMPMASK_LINKDWNDFLTSTATE )
+  {
+    if ( ib_port_info_get_link_down_def_state( p_comp_pi ) !=
+         ib_port_info_get_link_down_def_state( p_pi ) )
+      goto Exit;
+  }
+  if ( comp_mask & IB_PIR_COMPMASK_MKEYPROTBITS )
+  {
+    if( ib_port_info_get_mpb( p_comp_pi ) !=
+        ib_port_info_get_mpb( p_pi ) )
+      goto Exit;
+  }
+  if( comp_mask & IB_PIR_COMPMASK_LMC )
+  {
+    if( ib_port_info_get_lmc( p_comp_pi ) !=
+        ib_port_info_get_lmc( p_pi ) )
+      goto Exit;
+  }
+  if ( comp_mask & IB_PIR_COMPMASK_LINKSPEEDACTIVE )
+  {
+    if ( ib_port_info_get_link_speed_active( p_comp_pi ) !=
+         ib_port_info_get_link_speed_active( p_pi ) )
+      goto Exit;
+  }
+  if ( comp_mask & IB_PIR_COMPMASK_LINKSPEEDENABLE )
+  {
+    if ( ib_port_info_get_link_speed_enabled( p_comp_pi ) !=
+         ib_port_info_get_link_speed_enabled( p_pi ) )
+      goto Exit;
+  }
+  if( comp_mask & IB_PIR_COMPMASK_NEIGHBORMTU )
+  {
+    if( ib_port_info_get_neighbor_mtu( p_comp_pi ) !=
+        ib_port_info_get_neighbor_mtu( p_pi ) )
+      goto Exit;
+  }
+  if( comp_mask & IB_PIR_COMPMASK_MASTERSMSL )
+  {
+    if( ib_port_info_get_master_smsl( p_comp_pi ) !=
+        ib_port_info_get_master_smsl( p_pi ) )
+      goto Exit;
+  }
+  if( comp_mask & IB_PIR_COMPMASK_VLCAP )
+  {
+    if( ib_port_info_get_vl_cap( p_comp_pi ) !=
+        ib_port_info_get_vl_cap( p_pi ) )
+      goto Exit;
+  }
+  if( comp_mask & IB_PIR_COMPMASK_INITTYPE )
+  {
+    if( ib_port_info_get_init_type( p_comp_pi ) !=
+        ib_port_info_get_init_type( p_pi ) )
+      goto Exit;
+  }
+  if( comp_mask & IB_PIR_COMPMASK_VLHIGHLIMIT )
+  {
+    if( p_comp_pi->vl_high_limit != p_pi->vl_high_limit )
+      goto Exit;
+  }
+  if( comp_mask & IB_PIR_COMPMASK_VLARBHIGHCAP )
+  {
+    if( p_comp_pi->vl_arb_high_cap != p_pi->vl_arb_high_cap )
+      goto Exit;
+  }
+  if( comp_mask & IB_PIR_COMPMASK_VLARBLOWCAP )
+  {
+    if( p_comp_pi->vl_arb_low_cap != p_pi->vl_arb_low_cap )
+      goto Exit;
+  }
+  if( comp_mask & IB_PIR_COMPMASK_MTUCAP )
+  {
+    if( ib_port_info_get_mtu_cap( p_comp_pi ) !=
+        ib_port_info_get_mtu_cap( p_pi ) )
+      goto Exit;
+  }
+  if( comp_mask & IB_PIR_COMPMASK_VLSTALLCNT )
+  {
+    if( ib_port_info_get_vl_stall_count( p_comp_pi ) !=
+        ib_port_info_get_vl_stall_count( p_pi ) )
+      goto Exit;
+  }
+  if (comp_mask & IB_PIR_COMPMASK_HOQLIFE )
+  {
+    if ((p_comp_pi->vl_stall_life & 0x1F) != (p_pi->vl_stall_life & 0x1F) )
+      goto Exit;
+  }
+  if (comp_mask & IB_PIR_COMPMASK_OPVLS )
+  {
+    if ((p_comp_pi->vl_enforce & 0xF0) != (p_pi->vl_enforce & 0xF0) )
+      goto Exit;
+  }
+  if (comp_mask & IB_PIR_COMPMASK_PARENFIN )
+  {
+    if ((p_comp_pi->vl_enforce & 0x08) != (p_pi->vl_enforce & 0x08) )
+      goto Exit;
+  }
+  if (comp_mask & IB_PIR_COMPMASK_PARENFOUT )
+  {
+    if ((p_comp_pi->vl_enforce & 0x04) != (p_pi->vl_enforce & 0x04) )
+      goto Exit;
+  }
+  if (comp_mask & IB_PIR_COMPMASK_FILTERRAWIN )
+  {
+    if ((p_comp_pi->vl_enforce & 0x02) != (p_pi->vl_enforce & 0x02) )
+      goto Exit;
+  }
+  if (comp_mask & IB_PIR_COMPMASK_FILTERRAWOUT )
+  {
+    if ((p_comp_pi->vl_enforce & 0x01) != (p_pi->vl_enforce & 0x01) )
+      goto Exit;
+  }
+  if (comp_mask & IB_PIR_COMPMASK_MKEYVIO )
+  {
+    if (p_comp_pi->m_key_violations != p_pi->m_key_violations )
+      goto Exit;
+  }
+  if (comp_mask & IB_PIR_COMPMASK_PKEYVIO )
+  {
+    if (p_comp_pi->p_key_violations != p_pi->p_key_violations )
+      goto Exit;
+  }
+  if (comp_mask & IB_PIR_COMPMASK_QKEYVIO )
+  {
+    if (p_comp_pi->q_key_violations != p_pi->q_key_violations )
+      goto Exit;
+  }
+  if (comp_mask & IB_PIR_COMPMASK_GUIDCAP )
+  {
+    if (p_comp_pi->guid_cap != p_pi->guid_cap )
+      goto Exit;
+  }
+  if (comp_mask & IB_PIR_COMPMASK_SUBNTO )
+  {
+    if (ib_port_info_get_timeout(p_comp_pi) != ib_port_info_get_timeout(p_pi))
+      goto Exit;
+  }
+  if (comp_mask & IB_PIR_COMPMASK_RESPTIME )
+  {
+    if ((p_comp_pi->resp_time_value & 0x1F) != (p_pi->resp_time_value &0x1F) )
+      goto Exit;
+  }
+  if (comp_mask & IB_PIR_COMPMASK_LOCALPHYERR )
+  {
+    if( ib_port_info_get_local_phy_err_thd( p_comp_pi ) !=
+        ib_port_info_get_local_phy_err_thd( p_pi ) )
+      goto Exit;
+  }
+  if (comp_mask & IB_PIR_COMPMASK_OVERRUNERR)
+  {
+    if( ib_port_info_get_overrun_err_thd( p_comp_pi ) !=
+        ib_port_info_get_overrun_err_thd( p_pi ) )
+      goto Exit;
+  }
+
+  __osm_sa_pir_create( p_rcv, p_physp, p_ctxt );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_pir_by_comp_mask(
+  IN osm_pir_rcv_t*        const p_rcv,
+  IN const osm_port_t*     const p_port,
+  osm_pir_search_ctxt_t*   const p_ctxt )
+{
+  const ib_portinfo_record_t* p_rcvd_rec;
+  ib_net64_t               comp_mask;
+  const osm_physp_t*       p_physp;
+  uint8_t                  port_num;
+  uint8_t                  num_ports;
+  const osm_physp_t*       p_req_physp;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_pir_by_comp_mask );
+
+  p_rcvd_rec = p_ctxt->p_rcvd_rec;
+  comp_mask = p_ctxt->comp_mask;
+  p_req_physp = p_ctxt->p_req_physp;
+
+  num_ports = osm_port_get_num_physp( p_port );
+
+  if( comp_mask & IB_PIR_COMPMASK_PORTNUM )
+  {
+    if (p_rcvd_rec->port_num < num_ports)
+    {
+      p_physp = osm_port_get_phys_ptr( p_port, p_rcvd_rec->port_num );
+      /* Check that the p_physp is valid, and that the p_physp and the
+         p_req_physp share a pkey. */
+      if( p_physp && osm_physp_is_valid( p_physp ) &&
+          osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp))
+        __osm_sa_pir_check_physp( p_rcv, p_physp, p_ctxt );
+    }
+  }
+  else
+  {
+    for( port_num = 0; port_num < num_ports; port_num++ )
+    {
+      p_physp = osm_port_get_phys_ptr( p_port, port_num );
+      if( p_physp == NULL )
+        continue;
+
+      if( !osm_physp_is_valid( p_physp ) )
+        continue;
+
+      /* if the requester and the p_physp don't share a pkey -
+         continue */
+      if (!osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp ) )
+        continue;
+
+      __osm_sa_pir_check_physp( p_rcv, p_physp, p_ctxt );
+    }
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_pir_by_comp_mask_cb(
+  IN cl_map_item_t*        const p_map_item,
+  IN void*                 context )
+{
+  const osm_port_t*        const p_port = (osm_port_t*)p_map_item;
+  osm_pir_search_ctxt_t*   const p_ctxt = (osm_pir_search_ctxt_t *)context;
+
+  __osm_sa_pir_by_comp_mask( p_ctxt->p_rcv, p_port, p_ctxt );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pir_rcv_process(
+  IN osm_pir_rcv_t*        const p_rcv,
+  IN const osm_madw_t*     const p_madw )
+{
+  const ib_sa_mad_t*       p_rcvd_mad;
+  const ib_portinfo_record_t* p_rcvd_rec;
+  const cl_ptr_vector_t*   p_tbl;
+  const osm_port_t*        p_port = NULL;
+  const ib_port_info_t*    p_pi;
+  cl_qlist_t               rec_list;
+  osm_madw_t*              p_resp_madw;
+  ib_sa_mad_t*             p_resp_sa_mad;
+  ib_portinfo_record_t*    p_resp_rec;
+  uint32_t                 num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  uint32_t                trim_num_rec;
+#endif
+  uint32_t                 i;
+  osm_pir_search_ctxt_t    context;
+  osm_pir_item_t*          p_rec_item;
+  ib_api_status_t          status = IB_SUCCESS;
+  ib_net64_t               comp_mask;
+  osm_physp_t*             p_req_physp;
+  boolean_t                trusted_req = TRUE;
+
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_pir_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_rcvd_rec = (ib_portinfo_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+  comp_mask = p_rcvd_mad->comp_mask;
+
+  CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_PORTINFO_RECORD );
+
+  /* we only support SubnAdmGet and SubnAdmGetTable methods */
+  if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) &&
+       (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_pir_rcv_process: ERR 2105: "
+             "Unsupported Method (%s)\n",
+             ib_get_sa_method_str( p_rcvd_mad->method ) );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+    goto Exit;
+  }
+
+  /* update the requester physical port. */
+  p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+                                          p_rcv->p_subn,
+                                          osm_madw_get_mad_addr_ptr(p_madw) );
+  if (p_req_physp == NULL)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_pir_rcv_process: ERR 2104: "
+             "Cannot find requester physical port\n" );
+    goto Exit;
+  }
+
+  if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+    osm_dump_portinfo_record( p_rcv->p_log, p_rcvd_rec, OSM_LOG_DEBUG );
+
+  p_tbl = &p_rcv->p_subn->port_lid_tbl;
+  p_pi = &p_rcvd_rec->port_info;
+
+  cl_qlist_init( &rec_list );
+
+  context.p_rcvd_rec = p_rcvd_rec;
+  context.p_list = &rec_list;
+  context.comp_mask = p_rcvd_mad->comp_mask;
+  context.p_rcv = p_rcv;
+  context.p_req_physp = p_req_physp;
+  context.is_enhanced_comp_mask = cl_ntoh32(p_rcvd_mad->attr_mod) & (1 << 31);
+
+  cl_plock_acquire( p_rcv->p_lock );
+
+  CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 );
+
+  /*
+    If the user specified a LID, it obviously narrows our
+    work load, since we don't have to search every port
+  */
+  if( comp_mask & IB_PIR_COMPMASK_LID )
+  {
+    status = osm_get_port_by_base_lid( p_rcv->p_subn, p_rcvd_rec->lid, &p_port );
+    if ( ( status != IB_SUCCESS ) || ( p_port == NULL ) )
+    {
+      status = IB_NOT_FOUND;
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_pir_rcv_process: ERR 2109: "
+               "No port found with LID 0x%x\n",
+               cl_ntoh16(p_rcvd_rec->lid) );
+    }
+  }
+  else
+  {
+    if( comp_mask & IB_PIR_COMPMASK_BASELID )
+    {
+      if ((uint16_t)cl_ptr_vector_get_size(p_tbl) > cl_ntoh16(p_pi->base_lid))
+      {
+        p_port = cl_ptr_vector_get( p_tbl, cl_ntoh16(p_pi->base_lid) );
+      }
+      else
+      {
+        status = IB_NOT_FOUND;
+        osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                 "osm_pir_rcv_process: ERR 2103: "
+                 "Given LID (0x%X) is out of range:0x%X\n",
+                 cl_ntoh16(p_pi->base_lid), cl_ptr_vector_get_size(p_tbl));
+      }
+    }
+  }
+
+  if ( status == IB_SUCCESS )
+  {
+    if( p_port )
+      __osm_sa_pir_by_comp_mask( p_rcv, p_port, &context );
+    else
+    {
+      cl_qmap_apply_func( &p_rcv->p_subn->port_guid_tbl,
+                          __osm_sa_pir_by_comp_mask_cb,
+                          &context );
+    }
+  }
+
+  cl_plock_release( p_rcv->p_lock );
+
+  num_rec = cl_qlist_count( &rec_list );
+
+  /*
+   * C15-0.1.30:
+   * If we do a SubnAdmGet and got more than one record it is an error !
+   */
+  if (p_rcvd_mad->method == IB_MAD_METHOD_GET)
+  {
+    if (num_rec == 0)
+    {
+      osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+      goto Exit;
+    }
+    if (num_rec > 1)
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_pir_rcv_process: ERR 2108: "
+               "Got more than one record for SubnAdmGet (%u)\n",
+               num_rec );
+      osm_sa_send_error( p_rcv->p_resp, p_madw,
+                         IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+
+      /* need to set the mem free ... */
+      p_rec_item = (osm_pir_item_t*)cl_qlist_remove_head( &rec_list );
+      while( p_rec_item != (osm_pir_item_t*)cl_qlist_end( &rec_list ) )
+      {
+        cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+        p_rec_item = (osm_pir_item_t*)cl_qlist_remove_head( &rec_list );
+      }
+
+      goto Exit;
+    }
+  }
+
+  pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_portinfo_record_t);
+  if (trim_num_rec < num_rec)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "osm_pir_rcv_process: "
+             "Number of records:%u trimmed to:%u to fit in one MAD\n",
+             num_rec, trim_num_rec );
+    num_rec = trim_num_rec;
+  }
+#endif
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+           "osm_pir_rcv_process: "
+           "Returning %u records\n", num_rec );
+
+  if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+  {
+    osm_sa_send_error( p_rcv->p_resp, p_madw,
+                       IB_SA_MAD_STATUS_NO_RECORDS );
+    goto Exit;
+  }
+
+  /*
+   * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+   */
+  p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+                                  p_madw->h_bind,
+                                  num_rec * sizeof(ib_portinfo_record_t) + IB_SA_MAD_HDR_SIZE,
+                                  &p_madw->mad_addr );
+
+  if( !p_resp_madw )
+  {
+    osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+            "osm_pir_rcv_process: ERR 2106: "
+            "osm_mad_pool_get failed\n" );
+
+    for( i = 0; i < num_rec; i++ )
+    {
+      p_rec_item = (osm_pir_item_t*)cl_qlist_remove_head( &rec_list );
+      cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    }
+
+    osm_sa_send_error( p_rcv->p_resp, p_madw,
+                       IB_SA_MAD_STATUS_NO_RESOURCES );
+
+    goto Exit;
+  }
+
+  p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+  /*
+    Copy the MAD header back into the response mad.
+    Set the 'R' bit and the payload length,
+    Then copy all records from the list into the response payload.
+  */
+
+  memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+  /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
+  p_resp_sa_mad->sm_key = 0;
+  /* Fill in the offset (paylen will be done by the rmpp SAR) */
+  p_resp_sa_mad->attr_offset =
+    ib_get_attr_offset( sizeof(ib_portinfo_record_t) );
+
+  p_resp_rec = (ib_portinfo_record_t*)
+    ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+#ifndef VENDOR_RMPP_SUPPORT
+  /* we support only one packet RMPP - so we will set the first and
+     last flags for gettable */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+  {
+    p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+  }
+#else
+  /* forcefully define the packet as RMPP one */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+  /*
+    p922 - The M_Key returned shall be zero, except in the case of a 
+    trusted request. 
+    Note: In the mad controller we check that the SM_Key received on
+    the mad is valid. Meaning - is either zero or equal to the local
+    sm_key.
+  */
+  if (p_rcvd_mad->sm_key == 0)
+    trusted_req = FALSE;
+
+  for( i = 0; i < pre_trim_num_rec; i++ )
+  {
+    p_rec_item = (osm_pir_item_t*)cl_qlist_remove_head( &rec_list );
+    /* copy only if not trimmed */
+    if (i < num_rec)
+    {
+      *p_resp_rec = p_rec_item->rec;
+      if (trusted_req == FALSE)
+        p_resp_rec->port_info.m_key = 0;
+    }
+    cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    p_resp_rec++;
+  }
+
+  CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+  status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE);
+  if (status != IB_SUCCESS)
+  {
+    osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+            "osm_pir_rcv_process: ERR 2107: "
+            "osm_vendor_send status = %s\n",
+            ib_get_err_str(status));
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_portinfo_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_portinfo_record_ctrl.c
new file mode 100644 (file)
index 0000000..80bb937
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_portinfo_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_pir_rcv_ctrl_t.
+ * This object represents the PortInfoRecord request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_portinfo_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_pir_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_pir_rcv_process( ((osm_pir_rcv_ctrl_t*)context)->p_rcv,
+                       (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pir_rcv_ctrl_construct(
+  IN osm_pir_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pir_rcv_ctrl_destroy(
+  IN osm_pir_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pir_rcv_ctrl_init(
+  IN osm_pir_rcv_ctrl_t* const p_ctrl,
+  IN osm_pir_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_pir_rcv_ctrl_init );
+
+  osm_pir_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_PORTINFO_RECORD,
+    __osm_pir_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_pir_rcv_ctrl_init: ERR 2201: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_response.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_response.c
new file mode 100644 (file)
index 0000000..3d242d8
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_response.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_sa_resp_t.
+ * This object represents the SA query responder.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_helper.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_resp_construct(
+  IN osm_sa_resp_t* const p_resp )
+{
+  memset( p_resp, 0, sizeof(*p_resp) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_resp_destroy(
+  IN osm_sa_resp_t* const p_resp )
+{
+  CL_ASSERT( p_resp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sa_resp_init(
+  IN osm_sa_resp_t*     const p_resp,
+  IN osm_mad_pool_t*    const p_pool,
+  IN osm_log_t*         const p_log )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_sa_resp_init );
+
+  osm_sa_resp_construct( p_resp );
+
+  p_resp->p_log = p_log;
+  p_resp->p_pool = p_pool;
+
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_send_error(
+  IN osm_sa_resp_t*        const p_resp,
+  IN const osm_madw_t*     const p_madw,
+  IN const ib_net16_t      sa_status )
+{
+  osm_madw_t*              p_resp_madw;
+  ib_sa_mad_t*             p_resp_sa_mad;
+  ib_sa_mad_t*             p_sa_mad;
+  ib_api_status_t          status;
+
+  OSM_LOG_ENTER( p_resp->p_log, osm_sa_send_error );
+
+  /* avoid races - if we are exiting - exit */
+  if (osm_exit_flag)
+  {
+    osm_log( p_resp->p_log, OSM_LOG_DEBUG,
+             "osm_sa_send_error: "
+             "Ignoring requested send after exit\n" );
+    goto Exit;
+  }
+
+  p_resp_madw = osm_mad_pool_get( p_resp->p_pool,
+                                  p_madw->h_bind, MAD_BLOCK_SIZE, &p_madw->mad_addr );
+
+  if( p_resp_madw == NULL )
+  {
+    osm_log( p_resp->p_log, OSM_LOG_ERROR,
+             "osm_sa_send_error: ERR 2301: "
+             "Unable to acquire response MAD\n" );
+    goto Exit;
+  }
+
+  p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+
+  /*  Copy the MAD header back into the response mad */
+  *p_resp_sa_mad = *p_sa_mad;
+  p_resp_sa_mad->status = sa_status;
+
+  if( p_resp_sa_mad->method == IB_MAD_METHOD_SET )
+    p_resp_sa_mad->method = IB_MAD_METHOD_GET;
+
+  p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+
+  /*
+   * C15-0.1.5 - always return SM_Key = 0 (table 185 p 884)
+   */
+  p_resp_sa_mad->sm_key = 0;
+
+  /*
+   * o15-0.2.7 - The PathRecord Attribute ID shall be used in
+   * the response (to a SubnAdmGetMulti(MultiPathRecord) 
+   */
+  if( p_resp_sa_mad->attr_id == IB_MAD_ATTR_MULTIPATH_RECORD )
+    p_resp_sa_mad->attr_id = IB_MAD_ATTR_PATH_RECORD;
+
+  if( osm_log_is_active( p_resp->p_log, OSM_LOG_FRAMES ) )
+    osm_dump_sa_mad( p_resp->p_log, p_resp_sa_mad, OSM_LOG_FRAMES );
+
+  status = osm_vendor_send( osm_madw_get_bind_handle( p_resp_madw ),
+                            p_resp_madw, FALSE );
+
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_resp->p_log, OSM_LOG_ERROR,
+             "osm_sa_send_error: ERR 2302: "
+             "Error sending MAD (%s)\n", ib_get_err_str( status ) );
+    /*  osm_mad_pool_put( p_resp->p_pool, p_resp_madw ); */
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_resp->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_service_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_service_record.c
new file mode 100644 (file)
index 0000000..97595d0
--- /dev/null
@@ -0,0 +1,1204 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_service_record.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_sr_rcv_t.
+ * This object represents the ServiceRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.9 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_service_record.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <vendor/osm_vendor.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_sa.h>
+#include <opensm/osm_service.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_SR_RCV_POOL_MIN_SIZE    64
+#define OSM_SR_RCV_POOL_GROW_SIZE   64
+
+typedef  struct   _osm_sr_item
+{
+  cl_pool_item_t        pool_item;
+  ib_service_record_t   service_rec;
+} osm_sr_item_t;
+
+typedef  struct   osm_sr_match_item {
+  cl_qlist_t            sr_list;
+  ib_service_record_t*  p_service_rec;
+  ib_net64_t            comp_mask;
+  osm_sr_rcv_t*         p_rcv;
+
+} osm_sr_match_item_t;
+
+typedef struct _osm_sr_search_ctxt
+{
+  osm_sr_match_item_t *  p_sr_item;
+  const osm_physp_t*     p_req_physp;
+} osm_sr_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sr_rcv_construct(
+  IN osm_sr_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+  cl_qlock_pool_construct( &p_rcv->sr_pool );
+  cl_timer_construct(&p_rcv->sr_timer );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sr_rcv_destroy(
+  IN osm_sr_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_sr_rcv_destroy );
+  cl_qlock_pool_destroy( &p_rcv->sr_pool );
+  cl_timer_trim(&p_rcv->sr_timer, 1);
+  cl_timer_destroy(&p_rcv->sr_timer );
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sr_rcv_init(
+  IN osm_sr_rcv_t*      const p_rcv,
+  IN osm_sa_resp_t*     const p_resp,
+  IN osm_mad_pool_t*    const p_mad_pool,
+  IN osm_subn_t*        const p_subn,
+  IN osm_log_t*         const p_log,
+  IN cl_plock_t*        const p_lock )
+{
+  ib_api_status_t       status = IB_ERROR;
+  cl_status_t           cl_status;
+
+  OSM_LOG_ENTER( p_log, osm_sr_rcv_init );
+
+  osm_sr_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_resp = p_resp;
+  p_rcv->p_mad_pool = p_mad_pool;
+
+  cl_status = cl_qlock_pool_init( &p_rcv->sr_pool,
+                                  OSM_SR_RCV_POOL_MIN_SIZE,
+                                  0,
+                                  OSM_SR_RCV_POOL_GROW_SIZE,
+                                  sizeof(osm_sr_item_t),
+                                  NULL, NULL, NULL );
+  if(cl_status != CL_SUCCESS)
+    goto Exit;
+
+  status = cl_timer_init(&p_rcv->sr_timer,
+                         osm_sr_rcv_lease_cb,
+                         p_rcv );
+  if(cl_status != CL_SUCCESS)
+    goto Exit;
+
+  status = IB_SUCCESS;
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+__match_service_pkey_with_ports_pkey(
+  IN osm_sr_rcv_t*         const p_rcv,
+  IN const osm_madw_t*     const p_madw,
+  ib_service_record_t *    const p_service_rec,
+  ib_net64_t   const       comp_mask )
+{
+  boolean_t                valid = TRUE;
+  osm_physp_t *            p_req_physp;
+  ib_net64_t               service_guid;
+  osm_port_t *             service_port;
+
+  /* update the requester physical port. */
+  p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+                                          p_rcv->p_subn,
+                                          osm_madw_get_mad_addr_ptr(p_madw));
+  if (p_req_physp == NULL)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__match_service_pkey_with_ports_pkey: ERR 2404: "
+             "Cannot find requester physical port\n" );
+    valid = FALSE;
+    goto Exit;
+  }
+
+  if((comp_mask & IB_SR_COMPMASK_SPKEY) == IB_SR_COMPMASK_SPKEY)
+  {
+    /* We have a ServiceP_Key - check matching on requester port, and
+       ServiceGid port (if such exists) */
+    /* Make sure it matches the p_req_physp */
+    if (!osm_physp_has_pkey(p_rcv->p_log, p_service_rec->service_pkey, p_req_physp))
+    {
+      valid = FALSE;
+      goto Exit;
+    }
+
+    /* Make sure it matches the port of the ServiceGid */
+    if((comp_mask & IB_SR_COMPMASK_SGID) == IB_SR_COMPMASK_SGID)
+    {
+      service_guid = p_service_rec->service_gid.unicast.interface_id;
+      service_port = (osm_port_t*)cl_qmap_get( &p_rcv->p_subn->port_guid_tbl, service_guid );
+      if (service_port == (osm_port_t*)cl_qmap_end( &p_rcv->p_subn->port_guid_tbl ))
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                 "__match_service_pkey_with_ports_pkey: ERR 2405: "
+                 "No port object for port 0x%016" PRIx64 "\n",
+                 cl_ntoh64( service_guid ) );
+        valid = FALSE;
+        goto Exit;
+      }
+      /* check on the table of the default physical port of the service port */
+      if ( !osm_physp_has_pkey( p_rcv->p_log,
+                                p_service_rec->service_pkey,
+                                osm_port_get_default_phys_ptr(service_port) ) )
+      {
+        valid = FALSE;
+        goto Exit;
+      }
+    }
+  }
+
+ Exit:
+  return valid;
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+__match_name_to_key_association(
+  IN osm_sr_rcv_t*      const p_rcv,
+  ib_service_record_t*  p_service_rec,
+  ib_net64_t            comp_mask )
+{
+  UNUSED_PARAM( p_service_rec );
+  UNUSED_PARAM( p_rcv );
+
+  if( (comp_mask & (IB_SR_COMPMASK_SKEY | IB_SR_COMPMASK_SNAME)) ==
+      (IB_SR_COMPMASK_SKEY | IB_SR_COMPMASK_SNAME) )
+  {
+    /* For now, we are not maintaining the ServiceAssociation record
+     * so just return TRUE
+     */
+    return TRUE;
+  }
+
+  return TRUE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+__validate_sr(
+  IN osm_sr_rcv_t*         const p_rcv,
+  IN const osm_madw_t*     const p_madw )
+{
+  boolean_t                valid = TRUE;
+  ib_sa_mad_t *            p_sa_mad;
+  ib_service_record_t*     p_recvd_service_rec;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __validate_sr );
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_recvd_service_rec =
+    (ib_service_record_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+  valid = __match_service_pkey_with_ports_pkey(
+    p_rcv,
+    p_madw,
+    p_recvd_service_rec,
+    p_sa_mad->comp_mask );
+
+  if(!valid)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__validate_sr: "
+             "No Match for Service Pkey\n" );
+    valid = FALSE;
+    goto Exit;
+  }
+
+  valid = __match_name_to_key_association(
+    p_rcv,
+    p_recvd_service_rec,
+    p_sa_mad->comp_mask );
+
+  if(!valid)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__validate_sr: "
+             "Service Record Name to key matching failed\n" );
+    valid = FALSE;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return valid;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sr_rcv_respond(
+  IN osm_sr_rcv_t*         const p_rcv,
+  IN const osm_madw_t*     const p_madw,
+  IN cl_qlist_t*           const p_list )
+{
+  osm_madw_t*              p_resp_madw;
+  const ib_sa_mad_t*       p_sa_mad;
+  ib_sa_mad_t*             p_resp_sa_mad;
+  uint32_t                 num_rec, num_copied;
+#ifndef VENDOR_RMPP_SUPPORT
+  uint32_t                trim_num_rec;
+#endif
+  ib_service_record_t*     p_resp_sr;
+  ib_api_status_t          status;
+  osm_sr_item_t*           p_sr_item;
+  const ib_sa_mad_t*       p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  boolean_t                trusted_req = TRUE;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sr_rcv_respond );
+
+  num_rec = cl_qlist_count( p_list );
+
+  /*
+   * C15-0.1.30:
+   * If we do a SubnAdmGet and got more than one record it is an error !
+   */
+  if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) &&
+       (num_rec > 1)) {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sr_rcv_respond: ERR 2406: "
+             "Got more than one record for SubnAdmGet (%u).\n",
+             num_rec );
+    osm_sa_send_error( p_rcv->p_resp, p_madw,
+                       IB_SA_MAD_STATUS_TOO_MANY_RECORDS );
+
+    /* need to set the mem free ... */
+    p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list );
+    while( p_sr_item != (osm_sr_item_t*)cl_qlist_end( p_list ) )
+    {
+      cl_qlock_pool_put( &p_rcv->sr_pool, &p_sr_item->pool_item );
+      p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list );
+    }
+
+    goto Exit;
+  }
+
+#ifndef VENDOR_RMPP_SUPPORT
+  trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_service_record_t);
+  if (trim_num_rec < num_rec)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "__osm_sr_rcv_respond: "
+             "Number of records:%u trimmed to:%u to fit in one MAD\n",
+             num_rec, trim_num_rec );
+    num_rec = trim_num_rec;
+  }
+#endif
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_sr_rcv_respond: "
+             "Generating response with %u records\n", num_rec );
+  }
+
+  /*
+    Get a MAD to reply. Address of Mad is in the received mad_wrapper
+  */
+  p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, 
+                                  p_madw->h_bind,
+                                  num_rec * sizeof(ib_service_record_t) + IB_SA_MAD_HDR_SIZE,
+                                  &p_madw->mad_addr );
+  if( !p_resp_madw )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sr_rcv_respond: ERR 2402: "
+             "Unable to allocate MAD\n" );
+    /* Release the quick pool items */
+    p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list );
+    while( p_sr_item != (osm_sr_item_t*)cl_qlist_end( p_list ) )
+    {
+      cl_qlock_pool_put( &p_rcv->sr_pool, &p_sr_item->pool_item );
+      p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list );
+    }
+
+    goto Exit;
+  }
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+  memcpy( p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE );
+
+  /* but what if it was a SET ? setting the response bit is not enough */
+  if (p_rcvd_mad->method == IB_MAD_METHOD_SET)
+  {
+    p_resp_sa_mad->method = IB_MAD_METHOD_GET;
+  }
+  p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+  /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
+  p_resp_sa_mad->sm_key = 0;
+
+  /* Fill in the offset (paylen will be done by the rmpp SAR) */
+  p_resp_sa_mad->attr_offset =
+    ib_get_attr_offset( sizeof(ib_service_record_t) );
+
+#ifndef VENDOR_RMPP_SUPPORT
+  /* we support only one packet RMPP - so we will set the first and
+     last flags for gettable */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+  {
+    p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+  }
+#else
+  /* forcefully define the packet as RMPP one */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+  p_resp_sr = (ib_service_record_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+  if( (p_resp_sa_mad->method != IB_MAD_METHOD_GETTABLE_RESP) &&
+      (num_rec == 0))
+  {
+    p_resp_sa_mad->status = IB_SA_MAD_STATUS_NO_RECORDS;
+    memset( p_resp_sr, 0, sizeof(*p_resp_sr) );
+  }
+  else
+  {
+    /*
+      p923 - The ServiceKey shall be set to 0, except in the case of a trusted 
+      request. 
+      Note: In the mad controller we check that the SM_Key received on
+      the mad is valid. Meaning - is either zero or equal to the local
+      sm_key. 
+    */
+    if (p_sa_mad->sm_key == 0)
+      trusted_req = FALSE;
+
+    p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list );
+
+    /* we need to track the number of copied items so we can
+     * stop the copy - but clear them all
+     */
+    num_copied = 0;
+    while( p_sr_item != (osm_sr_item_t*)cl_qlist_end( p_list ) )
+    {
+      /*  Copy the Link Records from the list into the MAD */
+      if (num_copied < num_rec)
+      {
+        *p_resp_sr = p_sr_item->service_rec;
+        if (trusted_req == FALSE)
+          memset(p_resp_sr->service_key, 0, sizeof(p_resp_sr->service_key));
+
+        num_copied++;
+      }
+      cl_qlock_pool_put( &p_rcv->sr_pool, &p_sr_item->pool_item );
+      p_resp_sr++;
+      p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list );
+    }
+  }
+
+  status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw,  FALSE );
+
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sr_rcv_respond: ERR 2407: "
+             "Unable to send MAD (%s)\n", ib_get_err_str( status ) );
+    /*  osm_mad_pool_put( p_rcv->p_mad_pool, p_resp_madw ); */
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__get_matching_sr(
+  IN  cl_list_item_t* const   p_list_item,
+  IN  void*                   context )
+{
+  osm_sr_search_ctxt_t* const p_ctxt = (osm_sr_search_ctxt_t*)context;
+  osm_svcr_t   *        p_svcr = (osm_svcr_t*)p_list_item;
+  osm_sr_item_t*        p_sr_pool_item;
+  osm_sr_match_item_t*  p_sr_item =p_ctxt->p_sr_item;
+  ib_net64_t            comp_mask = p_sr_item->comp_mask;
+  const osm_physp_t*    p_req_physp = p_ctxt->p_req_physp;
+
+  if((comp_mask & IB_SR_COMPMASK_SID) == IB_SR_COMPMASK_SID)
+  {
+    if(p_sr_item->p_service_rec->service_id !=
+       p_svcr->service_record.service_id)
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SGID) == IB_SR_COMPMASK_SGID)
+  {
+    if(
+      memcmp(&p_sr_item->p_service_rec->service_gid,
+             &p_svcr->service_record.service_gid,
+             sizeof(p_svcr->service_record.service_gid)) != 0)
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SPKEY) == IB_SR_COMPMASK_SPKEY )
+  {
+    if(p_sr_item->p_service_rec->service_pkey !=
+       p_svcr->service_record.service_pkey)
+      return;
+  }
+
+  if((comp_mask & IB_SR_COMPMASK_SKEY) == IB_SR_COMPMASK_SKEY)
+  {
+    if(memcmp(p_sr_item->p_service_rec->service_key ,
+              p_svcr->service_record.service_key,
+              16*sizeof(uint8_t)))
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SNAME) == IB_SR_COMPMASK_SNAME)
+  {
+    if(
+      memcmp(p_sr_item->p_service_rec->service_name,
+             p_svcr->service_record.service_name,
+             sizeof(p_svcr->service_record.service_name)) != 0
+      )
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SDATA8_0) == IB_SR_COMPMASK_SDATA8_0)
+  {
+    if(p_sr_item->p_service_rec->service_data8[0] !=
+       p_svcr->service_record.service_data8[0])
+      return;
+  }
+
+  if((comp_mask & IB_SR_COMPMASK_SDATA8_1) == IB_SR_COMPMASK_SDATA8_1)
+  {
+    if(p_sr_item->p_service_rec->service_data8[1] !=
+       p_svcr->service_record.service_data8[1])
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SDATA8_2) == IB_SR_COMPMASK_SDATA8_2)
+  {
+    if(p_sr_item->p_service_rec->service_data8[2] !=
+       p_svcr->service_record.service_data8[2])
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SDATA8_3) == IB_SR_COMPMASK_SDATA8_3)
+  {
+    if(p_sr_item->p_service_rec->service_data8[3] !=
+       p_svcr->service_record.service_data8[3])
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SDATA8_4)== IB_SR_COMPMASK_SDATA8_4)
+  {
+    if(p_sr_item->p_service_rec->service_data8[4] !=
+       p_svcr->service_record.service_data8[4])
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SDATA8_5)== IB_SR_COMPMASK_SDATA8_5)
+  {
+    if(p_sr_item->p_service_rec->service_data8[5] !=
+       p_svcr->service_record.service_data8[5])
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SDATA8_6)== IB_SR_COMPMASK_SDATA8_6)
+  {
+    if(p_sr_item->p_service_rec->service_data8[6]!=
+       p_svcr->service_record.service_data8[6])
+      return;
+  }
+
+  if((comp_mask & IB_SR_COMPMASK_SDATA8_7)== IB_SR_COMPMASK_SDATA8_7)
+  {
+    if(p_sr_item->p_service_rec->service_data8[7]!=
+       p_svcr->service_record.service_data8[7])
+      return;
+  }
+
+  if((comp_mask & IB_SR_COMPMASK_SDATA8_8)== IB_SR_COMPMASK_SDATA8_8)
+  {
+    if(p_sr_item->p_service_rec->service_data8[8]!=
+       p_svcr->service_record.service_data8[8])
+      return;
+  }
+
+  if((comp_mask & IB_SR_COMPMASK_SDATA8_9)== IB_SR_COMPMASK_SDATA8_9)
+  {
+    if(p_sr_item->p_service_rec->service_data8[9]!=
+       p_svcr->service_record.service_data8[9])
+      return;
+  }
+
+  if((comp_mask & IB_SR_COMPMASK_SDATA8_10)== IB_SR_COMPMASK_SDATA8_10)
+  {
+    if(p_sr_item->p_service_rec->service_data8[10]!=
+       p_svcr->service_record.service_data8[10])
+      return;
+  }
+
+  if((comp_mask & IB_SR_COMPMASK_SDATA8_11)== IB_SR_COMPMASK_SDATA8_11)
+  {
+    if(p_sr_item->p_service_rec->service_data8[11]!=
+       p_svcr->service_record.service_data8[11])
+      return;
+  }
+
+  if((comp_mask & IB_SR_COMPMASK_SDATA8_12)== IB_SR_COMPMASK_SDATA8_12)
+  {
+    if(p_sr_item->p_service_rec->service_data8[12]!=
+       p_svcr->service_record.service_data8[12])
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SDATA8_13)== IB_SR_COMPMASK_SDATA8_13)
+  {
+    if(p_sr_item->p_service_rec->service_data8[13]!=
+       p_svcr->service_record.service_data8[13])
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SDATA8_14)== IB_SR_COMPMASK_SDATA8_14)
+  {
+    if(p_sr_item->p_service_rec->service_data8[14]!=
+       p_svcr->service_record.service_data8[14])
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SDATA8_15)== IB_SR_COMPMASK_SDATA8_15)
+  {
+    if(p_sr_item->p_service_rec->service_data8[15]!=
+       p_svcr->service_record.service_data8[15])
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SDATA16_0)== IB_SR_COMPMASK_SDATA16_0)
+  {
+    if(p_sr_item->p_service_rec->service_data16[0]!=
+       p_svcr->service_record.service_data16[0])
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SDATA16_1)== IB_SR_COMPMASK_SDATA16_1)
+  {
+    if(p_sr_item->p_service_rec->service_data16[1]!=
+       p_svcr->service_record.service_data16[1])
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SDATA16_2)== IB_SR_COMPMASK_SDATA16_2)
+  {
+    if(p_sr_item->p_service_rec->service_data16[2]!=
+       p_svcr->service_record.service_data16[2])
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SDATA16_3)== IB_SR_COMPMASK_SDATA16_3)
+  {
+    if(p_sr_item->p_service_rec->service_data16[3]!=
+       p_svcr->service_record.service_data16[3])
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SDATA16_4)== IB_SR_COMPMASK_SDATA16_4)
+  {
+    if(p_sr_item->p_service_rec->service_data16[4]!=
+       p_svcr->service_record.service_data16[4])
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SDATA16_5)== IB_SR_COMPMASK_SDATA16_5)
+  {
+    if(p_sr_item->p_service_rec->service_data16[5]!=
+       p_svcr->service_record.service_data16[5])
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SDATA16_6)== IB_SR_COMPMASK_SDATA16_6)
+  {
+    if(p_sr_item->p_service_rec->service_data16[6]!=
+       p_svcr->service_record.service_data16[6])
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SDATA16_7)== IB_SR_COMPMASK_SDATA16_7)
+  {
+    if(p_sr_item->p_service_rec->service_data16[7]!=
+       p_svcr->service_record.service_data16[7])
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SDATA32_0)== IB_SR_COMPMASK_SDATA32_0)
+  {
+    if(p_sr_item->p_service_rec->service_data32[0]!=
+       p_svcr->service_record.service_data32[0])
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SDATA32_1)== IB_SR_COMPMASK_SDATA32_1)
+  {
+    if(p_sr_item->p_service_rec->service_data32[1]!=
+       p_svcr->service_record.service_data32[1])
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SDATA32_2)== IB_SR_COMPMASK_SDATA32_2)
+  {
+    if(p_sr_item->p_service_rec->service_data32[2]!=
+       p_svcr->service_record.service_data32[2])
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SDATA32_3)== IB_SR_COMPMASK_SDATA32_3)
+  {
+    if(p_sr_item->p_service_rec->service_data32[3]!=
+       p_svcr->service_record.service_data32[3])
+      return;
+  }
+
+  if((comp_mask & IB_SR_COMPMASK_SDATA64_0)== IB_SR_COMPMASK_SDATA64_0)
+  {
+    if(p_sr_item->p_service_rec->service_data64[0]!=
+       p_svcr->service_record.service_data64[0])
+      return;
+  }
+  if((comp_mask & IB_SR_COMPMASK_SDATA64_1)== IB_SR_COMPMASK_SDATA64_1)
+  {
+    if(p_sr_item->p_service_rec->service_data64[1]!=
+       p_svcr->service_record.service_data64[1])
+      return;
+  }
+
+  /* Check that the requester port has the pkey which is the service_pkey.
+     If not - then it cannot receive this ServiceRecord. */
+  /* The check is relevant only if the service_pkey is valid */
+  if (!ib_pkey_is_invalid(p_svcr->service_record.service_pkey))
+  {
+    if (!osm_physp_has_pkey( p_sr_item->p_rcv->p_log,
+                             p_svcr->service_record.service_pkey,
+                             p_req_physp ) )
+    {
+      osm_log( p_sr_item->p_rcv->p_log, OSM_LOG_VERBOSE,
+               "__get_matching_sr: "
+               "requester port doesn't have the service_pkey: 0x%X\n",
+               cl_ntoh16(p_svcr->service_record.service_pkey) );
+      return;
+    }
+  }
+
+  p_sr_pool_item = (osm_sr_item_t*)cl_qlock_pool_get( &p_sr_item->p_rcv->sr_pool );
+
+  if( p_sr_pool_item == NULL )
+  {
+    osm_log( p_sr_item->p_rcv->p_log, OSM_LOG_ERROR,
+             "__get_matching_sr: ERR 2408: "
+             "Unable to acquire Service Record from pool\n" );
+    goto Exit;
+  }
+
+  p_sr_pool_item->service_rec = p_svcr->service_record;
+
+  cl_qlist_insert_tail( &p_sr_item->sr_list,
+                        (cl_list_item_t*)&p_sr_pool_item->pool_item );
+
+ Exit:
+  return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+osm_sr_rcv_process_get_method(
+  IN osm_sr_rcv_t*         const p_rcv,
+  IN const osm_madw_t*     const p_madw )
+{
+  ib_sa_mad_t *            p_sa_mad;
+  ib_service_record_t*     p_recvd_service_rec;
+  osm_sr_match_item_t      sr_match_item;
+  osm_sr_search_ctxt_t     context;
+  osm_physp_t*             p_req_physp;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_sr_rcv_process_get_method );
+
+  CL_ASSERT( p_madw );
+
+  /* update the requester physical port. */
+  p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+                                          p_rcv->p_subn,
+                                          osm_madw_get_mad_addr_ptr(p_madw) );
+  if (p_req_physp == NULL)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_sr_rcv_process_get_method: ERR 2409: "
+             "Cannot find requester physical port\n" );
+    goto Exit;
+  }
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_recvd_service_rec =
+    (ib_service_record_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_dump_service_record( p_rcv->p_log,
+                             p_recvd_service_rec,
+                             OSM_LOG_DEBUG );
+  }
+
+  cl_qlist_init(&sr_match_item.sr_list);
+  sr_match_item.p_service_rec = p_recvd_service_rec;
+  sr_match_item.comp_mask = p_sa_mad->comp_mask;
+  sr_match_item.p_rcv = p_rcv;
+
+  context.p_sr_item = &sr_match_item;
+  context.p_req_physp = p_req_physp;
+
+  /* Grab the lock */
+  cl_plock_excl_acquire(p_rcv->p_lock);
+
+  cl_qlist_apply_func(&p_rcv->p_subn->sa_sr_list,
+                      __get_matching_sr,
+                      &context);
+
+  cl_plock_release(p_rcv->p_lock);
+
+  if ((p_sa_mad->method == IB_MAD_METHOD_GET) &&
+     (cl_qlist_count( &sr_match_item.sr_list ) == 0))
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "osm_sr_rcv_process_get_method: "
+             "No records matched the Service Record query\n");
+
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+    goto Exit;
+  }
+
+  __osm_sr_rcv_respond( p_rcv, p_madw, &sr_match_item.sr_list );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+osm_sr_rcv_process_set_method(
+  IN osm_sr_rcv_t*         const p_rcv,
+  IN const osm_madw_t*     const p_madw )
+{
+  ib_sa_mad_t *            p_sa_mad;
+  ib_net16_t               sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+  ib_service_record_t*     p_recvd_service_rec;
+  ib_net64_t               comp_mask;
+  osm_svcr_t*              p_svcr;
+  osm_sr_item_t*           p_sr_item;
+  cl_qlist_t               sr_list;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_sr_rcv_process_set_method );
+
+  CL_ASSERT( p_madw );
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_recvd_service_rec =
+    (ib_service_record_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+  comp_mask = p_sa_mad->comp_mask;
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_dump_service_record( p_rcv->p_log,
+                             p_recvd_service_rec,
+                             OSM_LOG_DEBUG );
+  }
+
+  if( (comp_mask & ( IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SGID )) !=  
+      (IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SGID ))
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "osm_sr_rcv_process_set_method: "
+             "Component Mask RID check failed for METHOD_SET\n");
+    osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+    goto Exit;
+  }
+
+  /* if we were not provided with a service lease make it
+     infinite */
+  if( (comp_mask & IB_SR_COMPMASK_SLEASE) != IB_SR_COMPMASK_SLEASE)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "osm_sr_rcv_process_set_method: "
+             "ServiceLease Component Mask not set - using infinite lease\n");
+    p_recvd_service_rec->service_lease = 0xFFFFFFFF;
+  }
+
+  /* Grab the lock */
+  cl_plock_excl_acquire(p_rcv->p_lock);
+
+  /* If Record exists with matching RID */
+  p_svcr = osm_svcr_get_by_rid(
+    p_rcv->p_subn,
+    p_rcv->p_log,
+    p_recvd_service_rec );
+
+  if(p_svcr == NULL)
+  {
+    /* Create the instance of the osm_svcr_t object */
+    p_svcr = osm_svcr_new(p_recvd_service_rec);
+    if(p_svcr == NULL)
+    {
+      cl_plock_release(p_rcv->p_lock);
+
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_sr_rcv_process_set_method: ERR 2411: "
+               "osm_svcr_get_by_rid failed\n" );
+
+      osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES );
+      goto Exit;
+    }
+
+    /* Add this new osm_svcr_t object to subnet object */
+    osm_svcr_insert_to_db(
+      p_rcv->p_subn,
+      p_rcv->p_log,
+      p_svcr );
+
+  }
+  else
+  {
+    /* Update the old instance of the osm_svcr_t object */
+    osm_svcr_init(p_svcr, p_recvd_service_rec);
+  }
+
+  cl_plock_release(p_rcv->p_lock);
+
+  if( p_recvd_service_rec->service_lease != 0xFFFFFFFF )
+  {
+#if 0
+    cl_timer_trim(&p_rcv->sr_timer,
+                  p_recvd_service_rec->service_lease * 1000);
+#endif
+    /*  This was a bug since no check was made to see if too long */
+    /*  just make sure the timer works - get a call back within a second */
+    cl_timer_trim(&p_rcv->sr_timer, 1000);
+    p_svcr->modified_time = cl_get_time_stamp_sec();
+  }
+
+  p_sr_item = (osm_sr_item_t*)cl_qlock_pool_get( &p_rcv->sr_pool );
+  if( p_sr_item == NULL )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_sr_rcv_process_set_method: ERR 2412: "
+             "Unable to acquire Service record\n" );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES );
+    goto Exit;
+  }
+
+  if( (comp_mask & IB_SR_COMPMASK_SPKEY) != IB_SR_COMPMASK_SPKEY)
+  {
+    /* Set the Default Service P_Key in the response */
+    p_recvd_service_rec->service_pkey = IB_DEFAULT_PKEY;
+  }
+
+  p_sr_item->service_rec = *p_recvd_service_rec;
+  cl_qlist_init(&sr_list);
+
+  cl_qlist_insert_tail( &sr_list, (cl_list_item_t*)&p_sr_item->pool_item );
+
+  __osm_sr_rcv_respond( p_rcv, p_madw, &sr_list );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+osm_sr_rcv_process_delete_method(
+  IN osm_sr_rcv_t*         const p_rcv,
+  IN const osm_madw_t*     const p_madw )
+{
+  ib_sa_mad_t *            p_sa_mad;
+  ib_service_record_t*     p_recvd_service_rec;
+  ib_net64_t               comp_mask;
+  osm_svcr_t*              p_svcr;
+  osm_sr_item_t*           p_sr_item;
+  cl_qlist_t               sr_list;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_sr_rcv_process_delete_method );
+
+  CL_ASSERT( p_madw );
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_recvd_service_rec =
+    (ib_service_record_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+  comp_mask = p_sa_mad->comp_mask;
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_dump_service_record( p_rcv->p_log,
+                             p_recvd_service_rec,
+                             OSM_LOG_DEBUG );
+  }
+
+  /* Grab the lock */
+  cl_plock_excl_acquire(p_rcv->p_lock);
+
+  /* If Record exists with matching RID */
+  p_svcr = osm_svcr_get_by_rid(
+    p_rcv->p_subn,
+    p_rcv->p_log,
+    p_recvd_service_rec );
+
+  if(p_svcr == NULL)
+  {
+    cl_plock_release(p_rcv->p_lock);
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "osm_sr_rcv_process_delete_method: "
+             "No records matched the RID\n");
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+    goto Exit;
+  }
+  else
+  {
+    osm_svcr_remove_from_db(p_rcv->p_subn,
+                            p_rcv->p_log,
+                            p_svcr );
+  }
+
+  cl_plock_release(p_rcv->p_lock);
+
+  p_sr_item = (osm_sr_item_t*)cl_qlock_pool_get( &p_rcv->sr_pool );
+  if( p_sr_item == NULL )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_sr_rcv_process_delete_method: ERR 2413: "
+             "Unable to acquire Service record\n");
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES );
+    goto Exit;
+  }
+
+  /* provide back the copy of the record */
+  p_sr_item->service_rec = p_svcr->service_record;
+  cl_qlist_init(&sr_list);
+
+  cl_qlist_insert_tail( &sr_list, (cl_list_item_t*)&p_sr_item->pool_item );
+
+  if(p_svcr)
+    osm_svcr_destroy(p_svcr);
+
+  __osm_sr_rcv_respond( p_rcv, p_madw, &sr_list );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sr_rcv_process(
+  IN osm_sr_rcv_t*         const p_rcv,
+  IN const osm_madw_t*     const p_madw )
+{
+  ib_sa_mad_t *            p_sa_mad;
+  ib_net16_t               sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+  boolean_t                valid;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_sr_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+
+  CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_SERVICE_RECORD );
+
+  switch (p_sa_mad->method)
+  {
+  case IB_MAD_METHOD_SET:
+    valid = __validate_sr(p_rcv, p_madw);
+    if(!valid)
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+               "osm_sr_rcv_process: "
+               "Component Mask check failed for set request\n" );
+      osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+      goto Exit;
+    }
+    osm_sr_rcv_process_set_method(p_rcv, p_madw);
+    break;
+  case IB_MAD_METHOD_DELETE:
+    valid = __validate_sr(p_rcv, p_madw);
+    if(!valid)
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+               "osm_sr_rcv_process: "
+               "Component Mask check failed for delete request\n" );
+      osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+      goto Exit;
+    }
+    osm_sr_rcv_process_delete_method(p_rcv, p_madw);
+    break;
+  case IB_MAD_METHOD_GET:
+  case IB_MAD_METHOD_GETTABLE:
+    osm_sr_rcv_process_get_method(p_rcv, p_madw);
+    break;
+  default:
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "osm_sr_rcv_process: "
+             "Unsupported Method (%s)\n",
+             ib_get_sa_method_str( p_sa_mad->method ) );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+    break;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sr_rcv_lease_cb(
+  IN void*        context )
+{
+  osm_sr_rcv_t*   p_rcv = (osm_sr_rcv_t*)context;
+  cl_list_item_t* p_list_item;
+  cl_list_item_t* p_next_list_item;
+  osm_svcr_t*     p_svcr;
+  uint32_t        curr_time;
+  uint32_t        elapsed_time;
+  uint32_t        trim_time = 20; /*  maxiaml timer refresh is 20 seconds */
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_sr_rcv_lease_cb );
+
+  cl_plock_excl_acquire(p_rcv->p_lock);
+
+  p_list_item = cl_qlist_head(&p_rcv->p_subn->sa_sr_list);
+
+  while( p_list_item != cl_qlist_end(&p_rcv->p_subn->sa_sr_list) )
+  {
+    p_svcr = (osm_svcr_t*)p_list_item;
+
+    if(p_svcr->service_record.service_lease == 0xFFFFFFFF)
+    {
+      p_list_item = cl_qlist_next(p_list_item);
+      continue;
+    }
+
+    /* current time in seconds */
+    curr_time = cl_get_time_stamp_sec();
+    /* elapsed time from last modify */
+    elapsed_time = curr_time - p_svcr->modified_time;
+    /* but it can not be less then 1 */
+    if (elapsed_time < 1) elapsed_time = 1;
+
+    if(elapsed_time < p_svcr->lease_period)
+    {
+      /*
+         Just update the service lease period
+         note: for simplicity we work with a uint32_t field
+         external to the network order lease_period of the MAD
+      */
+      p_svcr->lease_period -= elapsed_time;
+
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+               "osm_sr_rcv_lease_cb: "
+               "Remaining time for Service Name:%s is:0x%X\n",
+               p_svcr->service_record.service_name,
+               p_svcr->lease_period );
+
+      p_svcr->modified_time = curr_time;
+
+      /* Update the trim timer */
+      if(trim_time > p_svcr->lease_period)
+      {
+        trim_time = p_svcr->lease_period;
+        if (trim_time < 1) trim_time = 1;
+      }
+
+      p_list_item = cl_qlist_next(p_list_item);
+      continue;
+
+    }
+    else
+    {
+      p_next_list_item = cl_qlist_next(p_list_item);
+
+      /* Remove the service Record */
+      osm_svcr_remove_from_db(p_rcv->p_subn,
+                              p_rcv->p_log,
+                              p_svcr);
+
+      osm_svcr_destroy(p_svcr);
+
+      p_list_item = p_next_list_item;
+      continue;
+    }
+  }
+
+  /* Release the Lock */
+  cl_plock_release(p_rcv->p_lock);
+
+  if(trim_time != 0xFFFFFFFF)
+  {
+    cl_timer_trim(&p_rcv->sr_timer,
+                  trim_time * 1000); /* Convert to milli seconds */
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_service_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_service_record_ctrl.c
new file mode 100644 (file)
index 0000000..1aa5c47
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_service_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_sr_rcv_ctrl_t.
+ * This object represents the ServiceRecord request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_service_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sr_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_sr_rcv_process( ((osm_sr_rcv_ctrl_t*)context)->p_rcv,
+                      (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sr_rcv_ctrl_construct(
+  IN osm_sr_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sr_rcv_ctrl_destroy(
+  IN osm_sr_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sr_rcv_ctrl_init(
+  IN osm_sr_rcv_ctrl_t* const p_ctrl,
+  IN osm_sr_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_sr_rcv_ctrl_init );
+
+  osm_sr_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_SERVICE_RECORD,
+    __osm_sr_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_sr_rcv_ctrl_init: ERR 2501: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_slvl_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_slvl_record.c
new file mode 100644 (file)
index 0000000..b3a2c88
--- /dev/null
@@ -0,0 +1,557 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_slvl_record.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_slvl_rec_rcv_t.
+ * This object represents the SLtoVL Mapping Query Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_slvl_record.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_SLVL_REC_RCV_POOL_MIN_SIZE    32
+#define OSM_SLVL_REC_RCV_POOL_GROW_SIZE   32
+
+typedef  struct _osm_slvl_item
+{
+  cl_pool_item_t           pool_item;
+  ib_slvl_table_record_t   rec;
+} osm_slvl_item_t;
+
+typedef  struct _osm_slvl_search_ctxt
+{
+  const ib_slvl_table_record_t* p_rcvd_rec;
+  ib_net64_t                    comp_mask;
+  uint8_t                       in_port_num;
+  cl_qlist_t*                   p_list;
+  osm_slvl_rec_rcv_t*           p_rcv;
+  const osm_physp_t*            p_req_physp;
+} osm_slvl_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rec_rcv_construct(
+  IN osm_slvl_rec_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+  cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rec_rcv_destroy(
+  IN osm_slvl_rec_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_slvl_rec_rcv_destroy );
+  cl_qlock_pool_destroy( &p_rcv->pool );
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_slvl_rec_rcv_init(
+  IN osm_slvl_rec_rcv_t*   const p_rcv,
+  IN osm_sa_resp_t*        const p_resp,
+  IN osm_mad_pool_t*       const p_mad_pool,
+  IN const osm_subn_t*     const p_subn,
+  IN osm_log_t*            const p_log,
+  IN cl_plock_t*           const p_lock )
+{
+  ib_api_status_t          status;
+
+  OSM_LOG_ENTER( p_log, osm_slvl_rec_rcv_init );
+
+  osm_slvl_rec_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_resp = p_resp;
+  p_rcv->p_mad_pool = p_mad_pool;
+
+  /* used for matching records collection */
+  status = cl_qlock_pool_init( &p_rcv->pool,
+                               OSM_SLVL_REC_RCV_POOL_MIN_SIZE,
+                               0,
+                               OSM_SLVL_REC_RCV_POOL_GROW_SIZE,
+                               sizeof(osm_slvl_item_t),
+                               NULL, NULL, NULL );
+
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_slvl_create(
+  IN osm_slvl_rec_rcv_t*      const p_rcv,
+  IN const osm_physp_t*       const p_physp,
+  IN osm_slvl_search_ctxt_t*  const p_ctxt,
+  IN uint8_t                  in_port_idx )
+{
+  osm_slvl_item_t*            p_rec_item;
+  uint16_t lid;
+  ib_api_status_t             status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_slvl_create );
+
+  p_rec_item = (osm_slvl_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+  if( p_rec_item == NULL )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sa_slvl_create: ERR 2602: "
+             "cl_qlock_pool_get failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+  if (p_physp->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH)
+  {
+    lid = osm_physp_get_port_info_ptr( p_physp )->base_lid;
+  }
+  else
+  {
+    lid = osm_node_get_base_lid( p_physp->p_node, 0 );
+  }
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_sa_slvl_create: "
+             "New SLtoVL Map for: OUT port 0x%016" PRIx64
+             ", lid 0x%X, port# 0x%X to In Port:%u\n",
+             cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+             cl_ntoh16( lid ), osm_physp_get_port_num( p_physp ),
+             in_port_idx
+             );
+  }
+
+  memset( &p_rec_item->rec, 0, sizeof( p_rec_item->rec ) );
+
+  p_rec_item->rec.lid = lid;
+  p_rec_item->rec.out_port_num = osm_physp_get_port_num( p_physp );
+  p_rec_item->rec.in_port_num = in_port_idx;
+  p_rec_item->rec.slvl_tbl = *(osm_physp_get_slvl_tbl(p_physp,in_port_idx));
+
+  cl_qlist_insert_tail( p_ctxt->p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_slvl_by_comp_mask(
+  IN osm_slvl_rec_rcv_t*         const p_rcv,
+  IN const osm_port_t*           const p_port,
+  osm_slvl_search_ctxt_t*        const p_ctxt )
+{
+  const ib_slvl_table_record_t*  p_rcvd_rec;
+  ib_net64_t                     comp_mask;
+  const osm_physp_t*             p_out_physp, *p_in_physp;
+  uint8_t                        in_port_num, out_port_num;
+  uint8_t                        num_ports;
+  uint8_t                        in_port_start, in_port_end;
+  uint8_t                        out_port_start, out_port_end;
+  const osm_physp_t*             p_req_physp;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_slvl_by_comp_mask );
+
+  p_rcvd_rec = p_ctxt->p_rcvd_rec;
+  comp_mask = p_ctxt->comp_mask;
+  num_ports = osm_port_get_num_physp( p_port );
+  in_port_start = 0;
+  in_port_end = num_ports;
+  out_port_start = 0;
+  out_port_end = num_ports;
+  p_req_physp = p_ctxt->p_req_physp;
+
+  if ( p_port->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_sa_slvl_by_comp_mask:  "
+             "Using Physical Default Port Number: 0x%X (for End Node)\n",
+             p_port->default_port_num );
+    p_out_physp = osm_port_get_phys_ptr( p_port, p_port->default_port_num );
+    /* check that the p_out_physp and the p_req_physp share a pkey */
+    if (osm_physp_share_pkey( p_rcv->p_log, p_req_physp, p_out_physp ))
+    __osm_sa_slvl_create( p_rcv, p_out_physp, p_ctxt, 0 );
+  }
+  else
+  {
+    if ( comp_mask & IB_SLVL_COMPMASK_OUT_PORT )
+    {
+      out_port_start = out_port_end = p_rcvd_rec->out_port_num;
+    }
+    if ( comp_mask & IB_SLVL_COMPMASK_IN_PORT )
+    {
+      in_port_start = in_port_end = p_rcvd_rec->in_port_num;
+    }
+
+    for( out_port_num = out_port_start; out_port_num <= out_port_end; out_port_num++ ) {
+      p_out_physp = osm_port_get_phys_ptr( p_port, out_port_num );
+      if( p_out_physp == NULL )
+        continue;
+
+      if( !osm_physp_is_valid( p_out_physp ) )
+        continue;
+
+      for( in_port_num = in_port_start; in_port_num <= in_port_end; in_port_num++ ) {
+#if 0
+        if (out_port_num && out_port_num == in_port_num)
+          continue;
+#endif
+
+        p_in_physp = osm_port_get_phys_ptr( p_port, in_port_num );
+        if( p_in_physp == NULL )
+          continue;
+
+        if( !osm_physp_is_valid( p_in_physp ) )
+          continue;
+
+        /* if the requester and the p_out_physp don't share a pkey -
+           continue */
+        if (!osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_out_physp ) )
+          continue;
+
+        __osm_sa_slvl_create(p_rcv, p_out_physp, p_ctxt, in_port_num);
+      }
+    }
+  }
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_slvl_by_comp_mask_cb(
+  IN cl_map_item_t*        const p_map_item,
+  IN void*                 context )
+{
+  const osm_port_t*        const p_port = (osm_port_t*)p_map_item;
+  osm_slvl_search_ctxt_t*  const p_ctxt = (osm_slvl_search_ctxt_t *)context;
+
+  __osm_sa_slvl_by_comp_mask( p_ctxt->p_rcv, p_port, p_ctxt );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rec_rcv_process(
+  IN osm_slvl_rec_rcv_t*         const p_rcv,
+  IN const osm_madw_t*           const p_madw )
+{
+  const ib_sa_mad_t*             p_rcvd_mad;
+  const ib_slvl_table_record_t*  p_rcvd_rec;
+  const cl_ptr_vector_t*         p_tbl;
+  const osm_port_t*              p_port = NULL;
+  const ib_slvl_table_t*         p_slvl_tbl;
+  cl_qlist_t                     rec_list;
+  osm_madw_t*                    p_resp_madw;
+  ib_sa_mad_t*                   p_resp_sa_mad;
+  ib_slvl_table_record_t*        p_resp_rec;
+  uint32_t                       num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  uint32_t                      trim_num_rec;
+#endif
+  uint32_t                       i;
+  osm_slvl_search_ctxt_t         context;
+  osm_slvl_item_t*               p_rec_item;
+  ib_api_status_t                status = IB_SUCCESS;
+  ib_net64_t                     comp_mask;
+  osm_physp_t*                   p_req_physp;
+
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_slvl_rec_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_rcvd_rec = (ib_slvl_table_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+  comp_mask = p_rcvd_mad->comp_mask;
+
+  CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_SLVL_RECORD );
+
+  /* we only support SubnAdmGet and SubnAdmGetTable methods */
+  if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) &&
+       (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_slvl_rec_rcv_process: ERR 2604: "
+             "Unsupported Method (%s)\n",
+             ib_get_sa_method_str( p_rcvd_mad->method ) );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+    goto Exit;
+  }
+
+  /* update the requester physical port. */
+  p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+                                          p_rcv->p_subn,
+                                          osm_madw_get_mad_addr_ptr(p_madw) );
+  if (p_req_physp == NULL)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_slvl_rec_rcv_process: ERR 2603: "
+             "Cannot find requester physical port\n" );
+    goto Exit;
+  }
+
+  p_slvl_tbl = (ib_slvl_table_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+
+  cl_qlist_init( &rec_list );
+
+  context.p_rcvd_rec = p_rcvd_rec;
+  context.p_list = &rec_list;
+  context.comp_mask = p_rcvd_mad->comp_mask;
+  context.p_rcv = p_rcv;
+  context.in_port_num = p_rcvd_rec->in_port_num;
+  context.p_req_physp = p_req_physp;
+
+  cl_plock_acquire( p_rcv->p_lock );
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+           "osm_slvl_rec_rcv_process: "
+           "Got Query Lid:0x%04X(%02X), In-Port:0x%02X(%02X), Out-Port:0x%02X(%02X)\n",
+           cl_ntoh16(p_rcvd_rec->lid),  (comp_mask & IB_SLVL_COMPMASK_LID) != 0,
+           p_rcvd_rec->in_port_num, (comp_mask & IB_SLVL_COMPMASK_IN_PORT) != 0,
+           p_rcvd_rec->out_port_num, (comp_mask & IB_SLVL_COMPMASK_OUT_PORT) != 0 );
+
+  /*
+    If the user specified a LID, it obviously narrows our
+    work load, since we don't have to search every port
+  */
+  if( comp_mask & IB_SLVL_COMPMASK_LID )
+  {
+
+    p_tbl = &p_rcv->p_subn->port_lid_tbl;
+
+    CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 );
+
+    status = osm_get_port_by_base_lid( p_rcv->p_subn, p_rcvd_rec->lid, &p_port );
+    if ( ( status != IB_SUCCESS ) || ( p_port == NULL ) )
+    {
+      status = IB_NOT_FOUND;
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_slvl_rec_rcv_process: ERR 2608: "
+               "No port found with LID 0x%x\n",
+               cl_ntoh16(p_rcvd_rec->lid) );
+    }
+  }
+
+  if ( status == IB_SUCCESS )
+  {
+    /* if we have a unique port - no need for a port search */
+    if( p_port )
+      /*  this does the loop on all the port phys ports */
+      __osm_sa_slvl_by_comp_mask( p_rcv, p_port, &context );
+    else
+    {
+      cl_qmap_apply_func( &p_rcv->p_subn->port_guid_tbl,
+                          __osm_sa_slvl_by_comp_mask_cb,
+                          &context );
+    }
+  }
+
+  cl_plock_release( p_rcv->p_lock );
+
+  num_rec = cl_qlist_count( &rec_list );
+
+  /*
+   * C15-0.1.30:
+   * If we do a SubnAdmGet and got more than one record it is an error !
+   */
+  if (p_rcvd_mad->method == IB_MAD_METHOD_GET)
+  {
+    if (num_rec == 0)
+    {
+      osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+      goto Exit;
+    }
+    if (num_rec > 1)
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_slvl_rec_rcv_process: ERR 2607: "
+               "Got more than one record for SubnAdmGet (%u)\n",
+               num_rec );
+      osm_sa_send_error( p_rcv->p_resp, p_madw,
+                         IB_SA_MAD_STATUS_TOO_MANY_RECORDS );
+
+      /* need to set the mem free ... */
+      p_rec_item = (osm_slvl_item_t*)cl_qlist_remove_head( &rec_list );
+      while( p_rec_item != (osm_slvl_item_t*)cl_qlist_end( &rec_list ) )
+      {
+        cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+        p_rec_item = (osm_slvl_item_t*)cl_qlist_remove_head( &rec_list );
+      }
+
+      goto Exit;
+    }
+  }
+
+  pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_slvl_table_record_t);
+  if (trim_num_rec < num_rec)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "osm_slvl_rec_rcv_process: "
+             "Number of records:%u trimmed to:%u to fit in one MAD\n",
+             num_rec, trim_num_rec );
+    num_rec = trim_num_rec;
+  }
+#endif
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+           "osm_slvl_rec_rcv_process: "
+           "Returning %u records\n", num_rec );
+
+  if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+  {
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+    goto Exit;
+  }
+
+  /*
+   * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+   */
+  p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+                                  p_madw->h_bind,
+                                  num_rec * sizeof(ib_slvl_table_record_t) + IB_SA_MAD_HDR_SIZE,
+                                  &p_madw->mad_addr );
+
+  if( !p_resp_madw )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_slvl_rec_rcv_process: ERR 2605: "
+             "osm_mad_pool_get failed\n" );
+
+    for( i = 0; i < num_rec; i++ )
+    {
+      p_rec_item = (osm_slvl_item_t*)cl_qlist_remove_head( &rec_list );
+      cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    }
+
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES );
+    goto Exit;
+  }
+
+  p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+  /*
+    Copy the MAD header back into the response mad.
+    Set the 'R' bit and the payload length,
+    Then copy all records from the list into the response payload.
+  */
+
+  memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+  /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
+  p_resp_sa_mad->sm_key = 0;
+
+  /* Fill in the offset (paylen will be done by the rmpp SAR) */
+  p_resp_sa_mad->attr_offset =
+    ib_get_attr_offset( sizeof(ib_slvl_table_record_t) );
+
+  p_resp_rec = (ib_slvl_table_record_t*)
+    ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+#ifndef VENDOR_RMPP_SUPPORT
+  /* we support only one packet RMPP - so we will set the first and
+     last flags for gettable */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+  {
+    p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+  }
+#else
+  /* forcefully define the packet as RMPP one */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+  for( i = 0; i < pre_trim_num_rec; i++ )
+  {
+    p_rec_item = (osm_slvl_item_t*)cl_qlist_remove_head( &rec_list );
+    /* copy only if not trimmed */
+    if (i < num_rec)
+    {
+      *p_resp_rec = p_rec_item->rec;
+    }
+    cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    p_resp_rec++;
+  }
+
+  CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+  status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE);
+  if(status != IB_SUCCESS)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_slvl_rec_rcv_process: ERR 2606: "
+             "osm_vendor_send status = %s\n",
+             ib_get_err_str(status) );
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_slvl_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_slvl_record_ctrl.c
new file mode 100644 (file)
index 0000000..42d305c
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_slvl_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_slvl_rec_rcv_ctrl_t.
+ * This object represents the SLtoVL Map Record SA request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_slvl_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_slvl_rec_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_slvl_rec_rcv_process( ((osm_slvl_rec_rcv_ctrl_t*)context)->p_rcv,
+                            (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rec_rcv_ctrl_construct(
+  IN osm_slvl_rec_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rec_rcv_ctrl_destroy(
+  IN osm_slvl_rec_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_slvl_rec_rcv_ctrl_init(
+  IN osm_slvl_rec_rcv_ctrl_t* const p_ctrl,
+  IN osm_slvl_rec_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_slvl_rec_rcv_ctrl_init );
+
+  osm_slvl_rec_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_SLVL_TBL_RECORD,
+    __osm_slvl_rec_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_slvl_rec_rcv_ctrl_init: ERR 2701: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sminfo_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sminfo_record.c
new file mode 100644 (file)
index 0000000..77582e6
--- /dev/null
@@ -0,0 +1,583 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_sminfo_record.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_smir_rcv_t.
+ * This object represents the SMInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_sminfo_record.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <vendor/osm_vendor.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_remote_sm.h>
+
+#define OSM_SMIR_RCV_POOL_MIN_SIZE     32
+#define OSM_SMIR_RCV_POOL_GROW_SIZE    32
+
+typedef  struct _osm_smir_item
+{
+  cl_pool_item_t           pool_item;
+  ib_sminfo_record_t       rec;
+} osm_smir_item_t;
+
+typedef  struct _osm_smir_search_ctxt
+{
+  const ib_sminfo_record_t* p_rcvd_rec;
+  ib_net64_t               comp_mask;
+  cl_qlist_t*              p_list;
+  osm_smir_rcv_t*          p_rcv;
+  const osm_physp_t*       p_req_physp;
+} osm_smir_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_smir_rcv_construct(
+  IN osm_smir_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+  cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_smir_rcv_destroy(
+  IN osm_smir_rcv_t* const p_rcv )
+{
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_smir_rcv_destroy );
+  cl_qlock_pool_destroy( &p_rcv->pool );
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_smir_rcv_init(
+  IN osm_smir_rcv_t* const p_rcv,
+  IN osm_sa_resp_t*  const p_resp,
+  IN osm_mad_pool_t* const p_mad_pool,
+  IN osm_subn_t*     const p_subn,
+  IN osm_stats_t*    const p_stats,
+  IN osm_log_t*      const p_log,
+  IN cl_plock_t*     const p_lock )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_smir_rcv_init );
+
+  osm_smir_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_resp = p_resp;
+  p_rcv->p_stats = p_stats;
+  p_rcv->p_mad_pool = p_mad_pool;
+
+  status = cl_qlock_pool_init( &p_rcv->pool,
+                               OSM_SMIR_RCV_POOL_MIN_SIZE,
+                               0,
+                               OSM_SMIR_RCV_POOL_GROW_SIZE,
+                               sizeof(osm_smir_item_t),
+                               NULL, NULL, NULL );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+static ib_api_status_t
+__osm_smir_rcv_new_smir(
+  IN osm_smir_rcv_t*         const p_rcv,
+  IN const osm_port_t*       const p_port,
+  IN cl_qlist_t*             const p_list,
+  IN ib_net64_t              const guid,
+  IN ib_net32_t              const act_count,
+  IN uint8_t                 const pri_state,
+  IN const osm_physp_t*      const p_req_physp )
+{
+  osm_smir_item_t*           p_rec_item;
+  ib_api_status_t            status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_smir_rcv_new_smir );
+
+  p_rec_item = (osm_smir_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+  if( p_rec_item == NULL )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_smir_rcv_new_smir: ERR 2801: "
+             "cl_qlock_pool_get failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_smir_rcv_new_smir: "
+             "New SMInfo: GUID 0x%016" PRIx64 "\n",
+             cl_ntoh64( guid )
+             );
+  }
+
+  memset( &p_rec_item->rec, 0, sizeof(ib_sminfo_record_t) );
+
+  p_rec_item->rec.lid = osm_port_get_base_lid( p_port );
+  p_rec_item->rec.sm_info.guid = guid;
+  p_rec_item->rec.sm_info.act_count = act_count;
+  p_rec_item->rec.sm_info.pri_state = pri_state;
+
+  cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_smir_by_comp_mask(
+  IN osm_smir_rcv_t*        const p_rcv,
+  IN const osm_remote_sm_t* const p_rem_sm,
+  osm_smir_search_ctxt_t*   const p_ctxt )
+{
+  const ib_sminfo_record_t* const p_rcvd_rec = p_ctxt->p_rcvd_rec;
+  const osm_physp_t*        const p_req_physp = p_ctxt->p_req_physp;
+  ib_net64_t                const comp_mask = p_ctxt->comp_mask;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_smir_by_comp_mask );
+
+  if ( comp_mask & IB_SMIR_COMPMASK_GUID )
+  {
+    if ( p_rem_sm->smi.guid != p_rcvd_rec->sm_info.guid )
+      goto Exit;
+  }
+
+  if ( comp_mask & IB_SMIR_COMPMASK_PRIORITY )
+  {
+    if ( ib_sminfo_get_priority( &p_rem_sm->smi ) !=
+         ib_sminfo_get_priority( &p_rcvd_rec->sm_info ) )
+      goto Exit;
+  }
+
+  if ( comp_mask & IB_SMIR_COMPMASK_SMSTATE )
+  {
+    if ( ib_sminfo_get_state( &p_rem_sm->smi ) !=
+         ib_sminfo_get_state( &p_rcvd_rec->sm_info ) )
+      goto Exit;
+  }
+
+  /* Implement any other needed search cases */
+
+ __osm_smir_rcv_new_smir( p_rcv, p_rem_sm->p_port, p_ctxt->p_list,
+                          p_rem_sm->smi.guid,
+                          p_rem_sm->smi.act_count,
+                          p_rem_sm->smi.pri_state,
+                          p_req_physp );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_smir_by_comp_mask_cb(
+  IN cl_map_item_t*        const p_map_item,
+  IN void*                 context )
+{
+  const osm_remote_sm_t*   const p_rem_sm = (osm_remote_sm_t*)p_map_item;
+  osm_smir_search_ctxt_t*  const p_ctxt = (osm_smir_search_ctxt_t *)context;
+
+  __osm_sa_smir_by_comp_mask( p_ctxt->p_rcv, p_rem_sm, p_ctxt );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_smir_rcv_process(
+  IN osm_smir_rcv_t*        const p_rcv,
+  IN const osm_madw_t*      const p_madw )
+{
+  const ib_sa_mad_t*        p_rcvd_mad;
+  const ib_sminfo_record_t* p_rcvd_rec;
+  const cl_qmap_t*          p_tbl;
+  const osm_port_t*         p_port = NULL;
+  const ib_sm_info_t*       p_smi;
+  cl_qlist_t                rec_list;
+  osm_madw_t*               p_resp_madw;
+  ib_sa_mad_t*              p_resp_sa_mad;
+  ib_sminfo_record_t*       p_resp_rec;
+  uint32_t                  num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  uint32_t                  trim_num_rec;
+#endif
+  uint32_t                  i;
+  osm_smir_search_ctxt_t    context;
+  osm_smir_item_t*          p_rec_item;
+  ib_api_status_t           status = IB_SUCCESS;
+  ib_net64_t                comp_mask;
+  ib_net64_t                port_guid;
+  osm_physp_t*              p_req_physp;
+  osm_port_t*               local_port;
+  osm_remote_sm_t*          p_rem_sm;
+  cl_qmap_t*                p_sm_guid_tbl;
+  uint8_t                   pri_state;
+
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_smir_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_rcvd_rec = (ib_sminfo_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+  comp_mask = p_rcvd_mad->comp_mask;
+
+  CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_SMINFO_RECORD );
+
+  /* we only support SubnAdmGet and SubnAdmGetTable methods */
+  if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) &&
+       (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_smir_rcv_process: ERR 2804: "
+             "Unsupported Method (%s)\n",
+             ib_get_sa_method_str( p_rcvd_mad->method ) );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+    goto Exit;
+  }
+
+  /* update the requester physical port. */
+  p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+                                          p_rcv->p_subn,
+                                          osm_madw_get_mad_addr_ptr(p_madw) );
+  if (p_req_physp == NULL)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_smir_rcv_process: ERR 2803: "
+             "Cannot find requester physical port\n" );
+    goto Exit;
+  }
+
+  if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+    osm_dump_sm_info_record( p_rcv->p_log, p_rcvd_rec, OSM_LOG_DEBUG );
+
+  p_tbl = &p_rcv->p_subn->sm_guid_tbl;
+  p_smi = &p_rcvd_rec->sm_info;
+
+  cl_qlist_init( &rec_list );
+
+  context.p_rcvd_rec = p_rcvd_rec;
+  context.p_list = &rec_list;
+  context.comp_mask = p_rcvd_mad->comp_mask;
+  context.p_rcv = p_rcv;
+  context.p_req_physp = p_req_physp;
+
+  cl_plock_acquire( p_rcv->p_lock );
+
+  /*
+    If the user specified a LID, it obviously narrows our
+    work load, since we don't have to search every port
+  */
+  if( comp_mask & IB_SMIR_COMPMASK_LID )
+  {
+    status = osm_get_port_by_base_lid( p_rcv->p_subn, p_rcvd_rec->lid, &p_port );
+    if ( ( status != IB_SUCCESS ) || ( p_port == NULL ) )
+    {
+      status = IB_NOT_FOUND;
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_smir_rcv_process: ERR 2806: "
+               "No port found with LID 0x%x\n",
+               cl_ntoh16(p_rcvd_rec->lid) );
+    }
+  }
+
+  if ( status == IB_SUCCESS )
+  {
+    /* Handle our own SM first */
+    local_port = osm_get_port_by_guid( p_rcv->p_subn, p_rcv->p_subn->sm_port_guid );
+    if ( !local_port )
+    {
+      cl_plock_release( p_rcv->p_lock );
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_smir_rcv_process: ERR 2809: "
+               "No port found with GUID 0x%016" PRIx64 "\n",
+               cl_ntoh64(p_rcv->p_subn->sm_port_guid ) );
+      goto Exit;
+    }
+
+    if ( !p_port || local_port == p_port )
+    {
+      if (FALSE ==
+          osm_physp_share_pkey( p_rcv->p_log, p_req_physp,
+                                osm_port_get_default_phys_ptr( local_port ) ) )
+      {
+        cl_plock_release( p_rcv->p_lock );
+        osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                 "osm_smir_rcv_process: ERR 2805: "
+                 "Cannot get SMInfo record due to pkey violation\n" );
+        goto Exit;
+      }
+
+      /* Check that other search components specified match */
+      if ( comp_mask & IB_SMIR_COMPMASK_GUID )
+      {
+        if ( p_rcv->p_subn->sm_port_guid != p_smi->guid )
+          goto Remotes;
+      }
+      if ( comp_mask & IB_SMIR_COMPMASK_PRIORITY )
+      {
+        if ( p_rcv->p_subn->opt.sm_priority != ib_sminfo_get_priority( p_smi ) )
+          goto Remotes;
+      }
+      if ( comp_mask & IB_SMIR_COMPMASK_SMSTATE )
+      {
+        if ( p_rcv->p_subn->sm_state != ib_sminfo_get_state( p_smi ) )
+          goto Remotes;
+      }
+
+      /* Now, add local SMInfo to list */
+      pri_state = p_rcv->p_subn->sm_state & 0x0F;
+      pri_state |= (p_rcv->p_subn->opt.sm_priority & 0x0F) << 4;
+      __osm_smir_rcv_new_smir( p_rcv, local_port, context.p_list, 
+                               p_rcv->p_subn->sm_port_guid,
+                               cl_ntoh32( p_rcv->p_stats->qp0_mads_sent ),
+                               pri_state,
+                               p_req_physp );
+    }
+
+ Remotes:
+    if( p_port && p_port != local_port )
+    {
+      /* Find remote SM corresponding to p_port */
+      port_guid = osm_port_get_guid( p_port );
+      p_sm_guid_tbl = &p_rcv->p_subn->sm_guid_tbl;
+      p_rem_sm = (osm_remote_sm_t*)cl_qmap_get( p_sm_guid_tbl, port_guid );
+      if (p_rem_sm != (osm_remote_sm_t*)cl_qmap_end( p_sm_guid_tbl ) )
+        __osm_sa_smir_by_comp_mask( p_rcv, p_rem_sm, &context );
+      else
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                 "osm_smir_rcv_process: ERR 280A: "
+                 "No remote SM for GUID  0x%016" PRIx64 "\n",
+                 cl_ntoh64( port_guid ) );
+      }
+    }
+    else
+    {
+      /* Go over all other known (remote) SMs */
+      cl_qmap_apply_func( &p_rcv->p_subn->sm_guid_tbl,
+                          __osm_sa_smir_by_comp_mask_cb,
+                          &context );
+    }
+  }
+
+  cl_plock_release( p_rcv->p_lock );
+
+  num_rec = cl_qlist_count( &rec_list );
+
+  /*
+   * C15-0.1.30:
+   * If we do a SubnAdmGet and got more than one record it is an error !
+   */
+  if (p_rcvd_mad->method == IB_MAD_METHOD_GET)
+  {
+    if (num_rec == 0)
+    {
+      osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+      goto Exit;
+    }
+    if (num_rec > 1)
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_smir_rcv_process: ERR 2808: "
+               "Got more than one record for SubnAdmGet (%u)\n",
+               num_rec );
+      osm_sa_send_error( p_rcv->p_resp, p_madw,
+                         IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+
+      /* need to set the mem free ... */
+      p_rec_item = (osm_smir_item_t*)cl_qlist_remove_head( &rec_list );
+      while( p_rec_item != (osm_smir_item_t*)cl_qlist_end( &rec_list ) )
+      {
+        cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+        p_rec_item = (osm_smir_item_t*)cl_qlist_remove_head( &rec_list );
+      }
+
+      goto Exit;
+    }
+  }
+
+  pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_sminfo_record_t);
+  if (trim_num_rec < num_rec)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "osm_smir_rcv_process: "
+             "Number of records:%u trimmed to:%u to fit in one MAD\n",
+             num_rec, trim_num_rec );
+    num_rec = trim_num_rec;
+  }
+#endif
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+           "osm_smir_rcv_process: "
+           "Returning %u records\n", num_rec );
+
+  if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+  {
+    osm_sa_send_error( p_rcv->p_resp, p_madw,
+                       IB_SA_MAD_STATUS_NO_RECORDS );
+    goto Exit;
+  }
+
+  /*
+   * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+   */
+  p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+                                  p_madw->h_bind,
+                                  num_rec * sizeof(ib_sminfo_record_t) + IB_SA_MAD_HDR_SIZE,
+                                  &p_madw->mad_addr );
+
+  if( !p_resp_madw )
+  {
+    osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+            "osm_smir_rcv_process: ERR 2807: "
+            "osm_mad_pool_get failed\n" );
+
+    for( i = 0; i < num_rec; i++ )
+    {
+      p_rec_item = (osm_smir_item_t*)cl_qlist_remove_head( &rec_list );
+      cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    }
+
+    osm_sa_send_error( p_rcv->p_resp, p_madw,
+                       IB_SA_MAD_STATUS_NO_RESOURCES );
+
+    goto Exit;
+  }
+
+  p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+  /*
+    Copy the MAD header back into the response mad.
+    Set the 'R' bit and the payload length,
+    Then copy all records from the list into the response payload.
+  */
+
+  memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+  /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
+  p_resp_sa_mad->sm_key = 0;
+  /* Fill in the offset (paylen will be done by the rmpp SAR) */
+  p_resp_sa_mad->attr_offset =
+    ib_get_attr_offset( sizeof(ib_sminfo_record_t) );
+
+  p_resp_rec = (ib_sminfo_record_t*)
+    ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+#ifndef VENDOR_RMPP_SUPPORT
+  /* we support only one packet RMPP - so we will set the first and
+     last flags for gettable */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+  {
+    p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+  }
+#else
+  /* forcefully define the packet as RMPP one */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+  for( i = 0; i < pre_trim_num_rec; i++ )
+  {
+    p_rec_item = (osm_smir_item_t*)cl_qlist_remove_head( &rec_list );
+    /* copy only if not trimmed */
+    if (i < num_rec)
+    {
+      *p_resp_rec = p_rec_item->rec;
+      p_resp_rec->sm_info.sm_key = 0;
+    }
+    cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    p_resp_rec++;
+  }
+
+  CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+  status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+  if( status != IB_SUCCESS )
+  {
+    osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+            "osm_smir_rcv_process: ERR 2802: "
+            "Error sending MAD (%s)\n",
+            ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sminfo_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sminfo_record_ctrl.c
new file mode 100644 (file)
index 0000000..f617274
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_sminfo_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_smir_ctrl_t.
+ * This object represents the SMInfo request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_sminfo_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_smir_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_smir_rcv_process( ((osm_smir_ctrl_t*)context)->p_rcv,
+                        (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_smir_ctrl_construct(
+  IN osm_smir_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_smir_ctrl_destroy(
+  IN osm_smir_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_smir_ctrl_init(
+  IN osm_smir_ctrl_t* const p_ctrl,
+  IN osm_smir_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_smir_ctrl_init );
+
+  osm_smir_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_SMINFO_RECORD,
+    __osm_smir_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_smir_ctrl_init: ERR 2901: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sw_info_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sw_info_record.c
new file mode 100644 (file)
index 0000000..8c893ad
--- /dev/null
@@ -0,0 +1,535 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_sir_rcv_t.
+ * This object represents the SwitchInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_sw_info_record.h>
+#include <opensm/osm_node.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_SIR_RCV_POOL_MIN_SIZE    32
+#define OSM_SIR_RCV_POOL_GROW_SIZE   32
+
+typedef  struct _osm_sir_item
+{
+  cl_pool_item_t           pool_item;
+  ib_switch_info_record_t  rec;
+} osm_sir_item_t;
+
+typedef  struct _osm_sir_search_ctxt
+{
+  const ib_switch_info_record_t* p_rcvd_rec;
+  ib_net64_t               comp_mask;
+  cl_qlist_t*              p_list;
+  osm_sir_rcv_t*           p_rcv;
+  const osm_physp_t*       p_req_physp;
+} osm_sir_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sir_rcv_construct(
+  IN osm_sir_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+  cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sir_rcv_destroy(
+  IN osm_sir_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_sir_rcv_destroy );
+  cl_qlock_pool_destroy( &p_rcv->pool );
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sir_rcv_init(
+  IN osm_sir_rcv_t*        const p_rcv,
+  IN osm_sa_resp_t*        const p_resp,
+  IN osm_mad_pool_t*       const p_mad_pool,
+  IN osm_subn_t*           const p_subn,
+  IN osm_log_t*            const p_log,
+  IN cl_plock_t*           const p_lock )
+{
+  ib_api_status_t          status;
+
+  OSM_LOG_ENTER( p_log, osm_sir_rcv_init );
+
+  osm_sir_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_resp = p_resp;
+  p_rcv->p_mad_pool = p_mad_pool;
+
+  status = cl_qlock_pool_init( &p_rcv->pool,
+                               OSM_SIR_RCV_POOL_MIN_SIZE,
+                               0,
+                               OSM_SIR_RCV_POOL_GROW_SIZE,
+                               sizeof(osm_sir_item_t),
+                               NULL, NULL, NULL );
+
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_sir_rcv_new_sir(
+  IN osm_sir_rcv_t*        const p_rcv,
+  IN const osm_switch_t*   const p_sw,
+  IN cl_qlist_t*           const p_list,
+  IN ib_net16_t            const lid )
+{
+  osm_sir_item_t*          p_rec_item;
+  ib_api_status_t          status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sir_rcv_new_sir );
+
+  p_rec_item = (osm_sir_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+  if( p_rec_item == NULL )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sir_rcv_new_sir: ERR 5308: "
+             "cl_qlock_pool_get failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_sir_rcv_new_sir: "
+             "New SwitchInfoRecord: lid 0x%X\n",
+             cl_ntoh16( lid )
+             );
+  }
+
+  memset( &p_rec_item->rec, 0, sizeof(ib_switch_info_record_t) );
+
+  p_rec_item->rec.lid = lid;
+  p_rec_item->rec.switch_info = p_sw->switch_info;
+
+  cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static osm_port_t*
+__osm_sir_get_port_by_guid(
+  IN osm_sir_rcv_t*   const p_rcv,
+  IN uint64_t         port_guid )
+{
+  osm_port_t*         p_port;
+
+  CL_PLOCK_ACQUIRE(p_rcv->p_lock);
+
+  p_port = (osm_port_t *)cl_qmap_get(&p_rcv->p_subn->port_guid_tbl,
+                                     port_guid);
+  if (p_port == (osm_port_t *)cl_qmap_end(&p_rcv->p_subn->port_guid_tbl))
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_sir_get_port_by_guid ERR 5309: "
+             "Invalid port GUID 0x%016" PRIx64 "\n",
+             port_guid );
+    p_port = NULL;
+  }
+
+  CL_PLOCK_RELEASE(p_rcv->p_lock);
+  return p_port;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sir_rcv_create_sir(
+  IN osm_sir_rcv_t*        const p_rcv,
+  IN const osm_switch_t*   const p_sw,
+  IN cl_qlist_t*           const p_list,
+  IN ib_net16_t            const match_lid,
+  IN const osm_physp_t*    const p_req_physp )
+{
+  osm_port_t*              p_port;
+  const osm_physp_t*       p_physp;
+  uint16_t                 match_lid_ho;
+  ib_net16_t               min_lid_ho;
+  ib_net16_t               max_lid_ho;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sir_rcv_create_sir );
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_sir_rcv_create_sir: "
+             "Looking for SwitchInfoRecord with LID: 0x%X\n",
+             cl_ntoh16( match_lid )
+             );
+  }
+
+  /* In switches, the port guid is the node guid. */
+  p_port =
+    __osm_sir_get_port_by_guid( p_rcv, p_sw->p_node->node_info.port_guid );
+  if (! p_port)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sir_rcv_create_sir: ERR 530A: "
+             "Failed to find Port by Node Guid:0x%016" PRIx64
+             "\n",
+             cl_ntoh64( p_sw->p_node->node_info.node_guid )
+             );
+    goto Exit;
+  }
+
+  /* check that the requester physp and the current physp are under
+     the same partition. */
+  p_physp = osm_port_get_default_phys_ptr( p_port );
+  if (! p_physp)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sir_rcv_create_sir: ERR 530B: "
+             "Failed to find default physical Port by Node Guid:0x%016" PRIx64
+             "\n",
+             cl_ntoh64( p_sw->p_node->node_info.node_guid )
+             );
+    goto Exit;
+  }
+  if (! osm_physp_share_pkey( p_rcv->p_log, p_req_physp, p_physp ))
+    goto Exit;
+
+  /* get the port 0 of the switch */
+  osm_port_get_lid_range_ho( p_port, &min_lid_ho, &max_lid_ho );
+
+  match_lid_ho = cl_ntoh16( match_lid );
+  if( match_lid_ho )
+  {
+    /*
+      We validate that the lid belongs to this switch.
+    */
+    if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+               "__osm_sir_rcv_create_sir: "
+               "Comparing LID: 0x%X <= 0x%X <= 0x%X\n",
+               min_lid_ho, match_lid_ho, max_lid_ho
+               );
+    }
+
+    if ( match_lid_ho < min_lid_ho || match_lid_ho > max_lid_ho )
+      goto Exit;
+
+  }
+
+  __osm_sir_rcv_new_sir( p_rcv, p_sw, p_list, osm_port_get_base_lid(p_port) );
+
+Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sir_rcv_by_comp_mask(
+  IN cl_map_item_t*        const p_map_item,
+  IN void*                 context )
+{
+  const osm_sir_search_ctxt_t* const p_ctxt = (osm_sir_search_ctxt_t *)context;
+  const osm_switch_t*      const p_sw = (osm_switch_t*)p_map_item;
+  const ib_switch_info_record_t* const p_rcvd_rec = p_ctxt->p_rcvd_rec;
+  const osm_physp_t*       const p_req_physp = p_ctxt->p_req_physp;
+  osm_sir_rcv_t*           const p_rcv = p_ctxt->p_rcv;
+  ib_net64_t               const comp_mask = p_ctxt->comp_mask;
+  ib_net16_t               match_lid = 0;
+
+  OSM_LOG_ENTER( p_ctxt->p_rcv->p_log, __osm_sir_rcv_by_comp_mask );
+
+  osm_dump_switch_info(
+    p_ctxt->p_rcv->p_log,
+    &p_sw->switch_info,
+    OSM_LOG_VERBOSE );    
+
+  if( comp_mask & IB_SWIR_COMPMASK_LID )
+  {
+    match_lid = p_rcvd_rec->lid;
+    if (!match_lid)
+      goto Exit;
+  }
+
+  __osm_sir_rcv_create_sir( p_rcv, p_sw, p_ctxt->p_list,
+                            match_lid, p_req_physp );
+
+Exit:
+  OSM_LOG_EXIT( p_ctxt->p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sir_rcv_process(
+  IN osm_sir_rcv_t*        const p_rcv,
+  IN const osm_madw_t*     const p_madw )
+{
+  const ib_sa_mad_t*       p_rcvd_mad;
+  const ib_switch_info_record_t*  p_rcvd_rec;
+  ib_switch_info_record_t*        p_resp_rec;
+  cl_qlist_t               rec_list;
+  osm_madw_t*              p_resp_madw;
+  ib_sa_mad_t*             p_resp_sa_mad;
+  uint32_t                 num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  uint32_t                trim_num_rec;
+#endif
+  uint32_t                 i;
+  osm_sir_search_ctxt_t    context;
+  osm_sir_item_t*          p_rec_item;
+  ib_api_status_t          status;
+  osm_physp_t*             p_req_physp;
+
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_sir_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_rcvd_rec = (ib_switch_info_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+
+  CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_SWITCH_INFO_RECORD );
+
+  /* we only support SubnAdmGet and SubnAdmGetTable methods */
+  if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) &&
+       (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) ) {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_sir_rcv_process: ERR 5305: "
+             "Unsupported Method (%s)\n",
+             ib_get_sa_method_str( p_rcvd_mad->method ) );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+    goto Exit;
+  }
+
+  /* update the requester physical port. */
+  p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+                                          p_rcv->p_subn,
+                                          osm_madw_get_mad_addr_ptr(p_madw) );
+  if (p_req_physp == NULL)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_sir_rcv_process: ERR 5304: "
+             "Cannot find requester physical port\n" );
+    goto Exit;
+  }
+
+  if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+    osm_dump_switch_info_record( p_rcv->p_log, p_rcvd_rec, OSM_LOG_DEBUG );
+
+  cl_qlist_init( &rec_list );
+
+  context.p_rcvd_rec    = p_rcvd_rec;
+  context.p_list        = &rec_list;
+  context.comp_mask     = p_rcvd_mad->comp_mask;
+  context.p_rcv         = p_rcv;
+  context.p_req_physp   = p_req_physp;
+
+  cl_plock_acquire( p_rcv->p_lock );
+
+  /* Go over all switches */
+  cl_qmap_apply_func( &p_rcv->p_subn->sw_guid_tbl,
+                      __osm_sir_rcv_by_comp_mask,
+                      &context );
+
+  cl_plock_release( p_rcv->p_lock );
+
+  num_rec = cl_qlist_count( &rec_list );
+
+  /*
+   * C15-0.1.30:
+   * If we do a SubnAdmGet and got more than one record it is an error !
+   */
+  if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec > 1) ) {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_sir_rcv_process: ERR 5303: "
+             "Got more than one record for SubnAdmGet (%u)\n",
+             num_rec );
+    osm_sa_send_error( p_rcv->p_resp, p_madw,
+                       IB_SA_MAD_STATUS_TOO_MANY_RECORDS );
+
+    /* need to set the mem free ... */
+    p_rec_item = (osm_sir_item_t*)cl_qlist_remove_head( &rec_list );
+    while( p_rec_item != (osm_sir_item_t*)cl_qlist_end( &rec_list ) )
+    {
+      cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+      p_rec_item = (osm_sir_item_t*)cl_qlist_remove_head( &rec_list );
+    }
+
+    goto Exit;
+  }
+
+  pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  /* we limit the number of records to a single packet */
+  trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_switch_info_record_t);
+  if (trim_num_rec < num_rec)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "osm_sir_rcv_process: "
+             "Number of records:%u trimmed to:%u to fit in one MAD\n",
+             num_rec, trim_num_rec );
+    num_rec = trim_num_rec;
+  }
+#endif
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+           "osm_sir_rcv_process: "
+           "Returning %u records\n", num_rec );
+
+  if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+  {
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+    goto Exit;
+  }
+
+  /* 
+   * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+   */
+  p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+                                  p_madw->h_bind,
+                                  num_rec * sizeof(ib_switch_info_record_t) + IB_SA_MAD_HDR_SIZE,
+                                  &p_madw->mad_addr );
+
+  if( !p_resp_madw )
+  {
+    osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+            "osm_sir_rcv_process: ERR 5306: "
+            "osm_mad_pool_get failed\n" );
+
+    for( i = 0; i < num_rec; i++ )
+    {
+      p_rec_item = (osm_sir_item_t*)cl_qlist_remove_head( &rec_list );
+      cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    }
+
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES );
+    goto Exit;
+  }
+
+  p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+  /*
+    Copy the MAD header back into the response mad.
+    Set the 'R' bit and the payload length,
+    Then copy all records from the list into the response payload.
+  */
+
+  memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+  /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
+  p_resp_sa_mad->sm_key = 0;
+  /* Fill in the offset (paylen will be done by the rmpp SAR) */
+  p_resp_sa_mad->attr_offset =
+    ib_get_attr_offset( sizeof(ib_switch_info_record_t) );
+
+  p_resp_rec = (ib_switch_info_record_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+#ifndef VENDOR_RMPP_SUPPORT
+  /* we support only one packet RMPP - so we will set the first and
+     last flags for gettable */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+  {
+    p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+  }
+#else
+  /* forcefully define the packet as RMPP one */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+  for( i = 0; i < pre_trim_num_rec; i++ )
+  {
+    p_rec_item = (osm_sir_item_t*)cl_qlist_remove_head( &rec_list );
+    /* copy only if not trimmed */
+    if (i < num_rec)
+    {
+      *p_resp_rec = p_rec_item->rec;
+    }
+    cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    p_resp_rec++;
+  }
+
+  CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+  status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+  if (status != IB_SUCCESS)
+  {
+    osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+            "osm_sir_rcv_process: ERR 5307: "
+            "osm_vendor_send status = %s\n",
+            ib_get_err_str(status));
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sw_info_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_sw_info_record_ctrl.c
new file mode 100644 (file)
index 0000000..726cd40
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_sir_rcv_ctrl_t.
+ * This object represents the SwitchInfo Record controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_sw_info_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sir_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_sir_rcv_process( ((osm_sir_rcv_ctrl_t*)context)->p_rcv,
+                       (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sir_rcv_ctrl_construct(
+  IN osm_sir_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sir_rcv_ctrl_destroy(
+  IN osm_sir_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sir_rcv_ctrl_init(
+  IN osm_sir_rcv_ctrl_t* const p_ctrl,
+  IN osm_sir_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_sir_rcv_ctrl_init );
+
+  osm_sir_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_SWITCH_INFO_RECORD,
+    __osm_sir_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_sir_rcv_ctrl_init: ERR 5301: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_vlarb_record.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_vlarb_record.c
new file mode 100644 (file)
index 0000000..6d29936
--- /dev/null
@@ -0,0 +1,577 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_vlarb_record.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_vlarb_rec_rcv_t.
+ * This object represents the VLArbitrationRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_vlarb_record.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_VLARB_REC_RCV_POOL_MIN_SIZE      32
+#define OSM_VLARB_REC_RCV_POOL_GROW_SIZE     32
+
+typedef  struct _osm_vl_arb_item
+{
+  cl_pool_item_t           pool_item;
+  ib_vl_arb_table_record_t rec;
+} osm_vl_arb_item_t;
+
+typedef  struct _osm_vl_arb_search_ctxt
+{
+  const ib_vl_arb_table_record_t* p_rcvd_rec;
+  ib_net64_t                    comp_mask;
+  uint8_t                       block_num;
+  cl_qlist_t*                   p_list;
+  osm_vlarb_rec_rcv_t*          p_rcv;
+  const osm_physp_t*            p_req_physp;
+} osm_vl_arb_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vlarb_rec_rcv_construct(
+  IN osm_vlarb_rec_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+  cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vlarb_rec_rcv_destroy(
+  IN osm_vlarb_rec_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_vlarb_rec_rcv_destroy );
+  cl_qlock_pool_destroy( &p_rcv->pool );
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_vlarb_rec_rcv_init(
+  IN osm_vlarb_rec_rcv_t*  const p_rcv,
+  IN osm_sa_resp_t*        const p_resp,
+  IN osm_mad_pool_t*       const p_mad_pool,
+  IN const osm_subn_t*     const p_subn,
+  IN osm_log_t*            const p_log,
+  IN cl_plock_t*           const p_lock )
+{
+  ib_api_status_t          status;
+
+  OSM_LOG_ENTER( p_log, osm_vlarb_rec_rcv_init );
+
+  osm_vlarb_rec_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_resp = p_resp;
+  p_rcv->p_mad_pool = p_mad_pool;
+
+  /* used for matching records collection */
+  status = cl_qlock_pool_init( &p_rcv->pool,
+                               OSM_VLARB_REC_RCV_POOL_MIN_SIZE,
+                               0,
+                               OSM_VLARB_REC_RCV_POOL_GROW_SIZE,
+                               sizeof(osm_vl_arb_item_t),
+                               NULL, NULL, NULL );
+
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_vl_arb_create(
+  IN osm_vlarb_rec_rcv_t*        const p_rcv,
+  IN osm_physp_t*                const p_physp,
+  IN osm_vl_arb_search_ctxt_t*   const p_ctxt,
+  IN uint8_t                     block )
+{
+  osm_vl_arb_item_t*             p_rec_item;
+  uint16_t                       lid;
+  ib_api_status_t                status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_vl_arb_create );
+
+  p_rec_item = (osm_vl_arb_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+  if( p_rec_item == NULL )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sa_vl_arb_create: ERR 2A02: "
+             "cl_qlock_pool_get failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+  if (p_physp->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH)
+  {
+    lid = osm_physp_get_port_info_ptr( p_physp )->base_lid;
+  }
+  else
+  {
+    lid = osm_node_get_base_lid( p_physp->p_node, 0 );
+  }
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_sa_vl_arb_create: "
+             "New VLArbitration for: port 0x%016" PRIx64
+             ", lid 0x%X, port# 0x%X Block:%u\n",
+             cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+             cl_ntoh16( lid ), osm_physp_get_port_num( p_physp ),
+             block
+             );
+  }
+
+  memset( &p_rec_item->rec, 0, sizeof( p_rec_item->rec ) );
+
+  p_rec_item->rec.lid = lid;
+  p_rec_item->rec.port_num = osm_physp_get_port_num( p_physp );
+  p_rec_item->rec.block_num = block;
+  p_rec_item->rec.vl_arb_tbl = *(osm_physp_get_vla_tbl(p_physp, block));
+
+  cl_qlist_insert_tail( p_ctxt->p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_vl_arb_check_physp(
+  IN osm_vlarb_rec_rcv_t*   const p_rcv,
+  IN osm_physp_t*           const p_physp,
+  osm_vl_arb_search_ctxt_t* const p_ctxt )
+{
+  ib_net64_t                comp_mask = p_ctxt->comp_mask;
+  uint8_t                   block;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_vl_arb_check_physp );
+
+  /* we got here with the phys port - all that's left is to get the right block */
+  for (block = 1; block <= 4; block++) {
+    if (!(comp_mask & IB_VLA_COMPMASK_BLOCK) || block == p_ctxt->block_num)
+    {
+      __osm_sa_vl_arb_create( p_rcv, p_physp, p_ctxt, block );
+    }
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_vl_arb_by_comp_mask(
+  IN osm_vlarb_rec_rcv_t*     const p_rcv,
+  IN const osm_port_t*        const p_port,
+  osm_vl_arb_search_ctxt_t*   const p_ctxt )
+{
+  const ib_vl_arb_table_record_t*   p_rcvd_rec;
+  ib_net64_t                  comp_mask;
+  osm_physp_t *               p_physp;
+  uint8_t                     port_num;
+  uint8_t                     num_ports;
+  const osm_physp_t*          p_req_physp;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_vl_arb_by_comp_mask );
+
+  p_rcvd_rec = p_ctxt->p_rcvd_rec;
+  comp_mask = p_ctxt->comp_mask;
+  port_num = p_rcvd_rec->port_num;
+  p_req_physp = p_ctxt->p_req_physp;
+
+  /* if this is a switch port we can search all ports
+     otherwise we must be looking on port 0 */
+  if ( p_port->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH)
+  {
+    /* we put it in the comp mask and port num */
+    port_num = p_port->default_port_num;
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_sa_vl_arb_by_comp_mask:  "
+             "Using Physical Default Port Number: 0x%X (for End Node)\n",
+             port_num );
+    comp_mask |= IB_VLA_COMPMASK_OUT_PORT;
+  }
+
+  if( comp_mask & IB_VLA_COMPMASK_OUT_PORT )
+  {
+    if (port_num < osm_port_get_num_physp( p_port ))
+    {
+      p_physp = osm_port_get_phys_ptr( p_port, port_num );
+      /* check that the p_physp is valid, and that the requester
+         and the p_physp share a pkey. */
+      if( p_physp && osm_physp_is_valid( p_physp ) &&
+          osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp) )
+        __osm_sa_vl_arb_check_physp( p_rcv, p_physp, p_ctxt );
+    }
+    else
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_sa_vl_arb_by_comp_mask: ERR 2A03: "
+               "Given Physical Port Number: 0x%X is out of range should be < 0x%X\n",
+               port_num, osm_port_get_num_physp( p_port ) );
+      goto Exit;
+    }
+  }
+  else
+  {
+    num_ports = osm_port_get_num_physp( p_port );
+    for( port_num = 0; port_num < num_ports; port_num++ )
+    {
+      p_physp = osm_port_get_phys_ptr( p_port, port_num );
+      if( p_physp == NULL )
+        continue;
+
+      if( !osm_physp_is_valid( p_physp ) )
+        continue;
+
+      /* if the requester and the p_physp don't share a pkey -
+         continue */
+      if (!osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp))
+        continue;
+
+      __osm_sa_vl_arb_check_physp( p_rcv, p_physp, p_ctxt );
+    }
+  }
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_vl_arb_by_comp_mask_cb(
+  IN cl_map_item_t*         const p_map_item,
+  IN void*                  context )
+{
+  const osm_port_t*         const p_port = (osm_port_t*)p_map_item;
+  osm_vl_arb_search_ctxt_t* const p_ctxt = (osm_vl_arb_search_ctxt_t *)context;
+
+  __osm_sa_vl_arb_by_comp_mask( p_ctxt->p_rcv, p_port, p_ctxt );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vlarb_rec_rcv_process(
+  IN osm_vlarb_rec_rcv_t*  const p_rcv,
+  IN const osm_madw_t*     const p_madw )
+{
+  const ib_sa_mad_t*       p_rcvd_mad;
+  const ib_vl_arb_table_record_t*   p_rcvd_rec;
+  const cl_ptr_vector_t*   p_tbl;
+  const osm_port_t*        p_port = NULL;
+  const ib_vl_arb_table_t* p_vl_arb;
+  cl_qlist_t               rec_list;
+  osm_madw_t*              p_resp_madw;
+  ib_sa_mad_t*             p_resp_sa_mad;
+  ib_vl_arb_table_record_t*    p_resp_rec;
+  uint32_t                 num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT 
+  uint32_t                trim_num_rec;
+#endif
+  uint32_t                 i;
+  osm_vl_arb_search_ctxt_t context;
+  osm_vl_arb_item_t*       p_rec_item;
+  ib_api_status_t          status = IB_SUCCESS;
+  ib_net64_t               comp_mask;
+  osm_physp_t*             p_req_physp;
+
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_vlarb_rec_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_rcvd_rec = (ib_vl_arb_table_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+  comp_mask = p_rcvd_mad->comp_mask;
+
+  CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_VLARB_RECORD );
+
+  /* we only support SubnAdmGet and SubnAdmGetTable methods */
+  if ( (p_rcvd_mad->method != IB_MAD_METHOD_GET) &&
+       (p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_vlarb_rec_rcv_process: ERR 2A05: "
+             "Unsupported Method (%s)\n",
+             ib_get_sa_method_str( p_rcvd_mad->method ) );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+    goto Exit;
+  }
+
+  /* update the requester physical port. */
+  p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+                                          p_rcv->p_subn,
+                                          osm_madw_get_mad_addr_ptr(p_madw) );
+  if (p_req_physp == NULL)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_vlarb_rec_rcv_process: ERR 2A04: "
+             "Cannot find requester physical port\n" );
+    goto Exit;
+  }
+
+  p_vl_arb = (ib_vl_arb_table_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+
+  cl_qlist_init( &rec_list );
+
+  context.p_rcvd_rec = p_rcvd_rec;
+  context.p_list = &rec_list;
+  context.comp_mask = p_rcvd_mad->comp_mask;
+  context.p_rcv = p_rcv;
+  context.block_num = p_rcvd_rec->block_num;
+  context.p_req_physp = p_req_physp;
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+           "osm_vlarb_rec_rcv_process: "
+           "Got Query Lid:0x%04X(%02X), Port:0x%02X(%02X), Block:0x%02X(%02X)\n",
+           cl_ntoh16(p_rcvd_rec->lid),  (comp_mask & IB_VLA_COMPMASK_LID) != 0,
+           p_rcvd_rec->port_num, (comp_mask & IB_VLA_COMPMASK_OUT_PORT) != 0,
+           p_rcvd_rec->block_num, (comp_mask & IB_VLA_COMPMASK_BLOCK) != 0 );
+
+  cl_plock_acquire( p_rcv->p_lock );
+
+  /*
+    If the user specified a LID, it obviously narrows our
+    work load, since we don't have to search every port
+  */
+  if( comp_mask & IB_VLA_COMPMASK_LID )
+  {
+
+    p_tbl = &p_rcv->p_subn->port_lid_tbl;
+
+    CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 );
+
+    status = osm_get_port_by_base_lid( p_rcv->p_subn, p_rcvd_rec->lid, &p_port );
+    if ( ( status != IB_SUCCESS ) || ( p_port == NULL ) )
+    {
+      status = IB_NOT_FOUND;
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_vlarb_rec_rcv_process: ERR 2A09: "
+               "No port found with LID 0x%x\n",
+               cl_ntoh16(p_rcvd_rec->lid) );
+    }
+  }
+
+  if ( status == IB_SUCCESS )
+  {
+    /* if we got a unique port - no need for a port search */
+    if( p_port )
+      /*  this does the loop on all the port phys ports */
+      __osm_sa_vl_arb_by_comp_mask( p_rcv, p_port, &context );
+    else
+    {
+      cl_qmap_apply_func( &p_rcv->p_subn->port_guid_tbl,
+                          __osm_sa_vl_arb_by_comp_mask_cb,
+                          &context );
+    }
+  }
+
+  cl_plock_release( p_rcv->p_lock );
+
+  num_rec = cl_qlist_count( &rec_list );
+
+  /*
+   * C15-0.1.30:
+   * If we do a SubnAdmGet and got more than one record it is an error !
+   */
+  if (p_rcvd_mad->method == IB_MAD_METHOD_GET)
+  {
+    if (num_rec == 0)
+    {
+      osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+      goto Exit;
+    }
+    if (num_rec > 1)
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_vlarb_rec_rcv_process:  ERR 2A08: "
+               "Got more than one record for SubnAdmGet (%u)\n",
+               num_rec );
+      osm_sa_send_error( p_rcv->p_resp, p_madw,
+                         IB_SA_MAD_STATUS_TOO_MANY_RECORDS );
+
+      /* need to set the mem free ... */
+      p_rec_item = (osm_vl_arb_item_t*)cl_qlist_remove_head( &rec_list );
+      while( p_rec_item != (osm_vl_arb_item_t*)cl_qlist_end( &rec_list ) )
+      {
+        cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+        p_rec_item = (osm_vl_arb_item_t*)cl_qlist_remove_head( &rec_list );
+      }
+
+      goto Exit;
+    }
+  }
+
+  pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+  trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_vl_arb_table_record_t);
+  if (trim_num_rec < num_rec)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "osm_vlarb_rec_rcv_process: "
+             "Number of records:%u trimmed to:%u to fit in one MAD\n",
+             num_rec, trim_num_rec );
+    num_rec = trim_num_rec;
+  }
+#endif
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+           "osm_vlarb_rec_rcv_process: "
+           "Returning %u records\n", num_rec );
+
+  if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+  {
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+    goto Exit;
+  }
+
+  /*
+   * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+   */
+  p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+                                  p_madw->h_bind,
+                                  num_rec * sizeof(ib_vl_arb_table_record_t) + IB_SA_MAD_HDR_SIZE,
+                                  &p_madw->mad_addr );
+
+  if( !p_resp_madw )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_vlarb_rec_rcv_process: ERR 2A06: "
+             "osm_mad_pool_get failed\n" );
+
+    for( i = 0; i < num_rec; i++ )
+    {
+      p_rec_item = (osm_vl_arb_item_t*)cl_qlist_remove_head( &rec_list );
+      cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    }
+
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES );
+    goto Exit;
+  }
+
+  p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+
+  /*
+    Copy the MAD header back into the response mad.
+    Set the 'R' bit and the payload length,
+    Then copy all records from the list into the response payload.
+  */
+
+  memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+  /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
+  p_resp_sa_mad->sm_key = 0;
+
+  /* Fill in the offset (paylen will be done by the rmpp SAR) */
+  p_resp_sa_mad->attr_offset =
+    ib_get_attr_offset( sizeof(ib_vl_arb_table_record_t) );
+
+  p_resp_rec = (ib_vl_arb_table_record_t*)
+    ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+#ifndef VENDOR_RMPP_SUPPORT
+  /* we support only one packet RMPP - so we will set the first and
+     last flags for gettable */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+  {
+    p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;
+  }
+#else
+  /* forcefully define the packet as RMPP one */
+  if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+    p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+  for( i = 0; i < pre_trim_num_rec; i++ )
+  {
+    p_rec_item = (osm_vl_arb_item_t*)cl_qlist_remove_head( &rec_list );
+    /* copy only if not trimmed */
+    if (i < num_rec)
+    {
+      *p_resp_rec = p_rec_item->rec;
+    }
+    cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+    p_resp_rec++;
+  }
+
+  CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+  status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+  if(status != IB_SUCCESS)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_vlarb_rec_rcv_process: ERR 2A07: "
+             "osm_vendor_send status = %s\n",
+             ib_get_err_str(status) );
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_vlarb_record_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sa_vlarb_record_ctrl.c
new file mode 100644 (file)
index 0000000..cc57ae8
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sa_vlarb_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_vlarb_rec_rcv_ctrl_t.
+ * This object represents the VL Arbitration Record SA request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_vlarb_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_vlarb_rec_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_vlarb_rec_rcv_process( ((osm_vlarb_rec_rcv_ctrl_t*)context)->p_rcv,
+                             (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vlarb_rec_rcv_ctrl_construct(
+  IN osm_vlarb_rec_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vlarb_rec_rcv_ctrl_destroy(
+  IN osm_vlarb_rec_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_vlarb_rec_rcv_ctrl_init(
+  IN osm_vlarb_rec_rcv_ctrl_t* const p_ctrl,
+  IN osm_vlarb_rec_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_vlarb_rec_rcv_ctrl_init );
+
+  osm_vlarb_rec_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_VL_ARB_RECORD,
+    __osm_vlarb_rec_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_vlarb_rec_rcv_ctrl_init: ERR 2B01: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_service.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_service.c
new file mode 100644 (file)
index 0000000..64d3e0c
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_service.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of service record functions.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_timer.h>
+#include <opensm/osm_service.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_svcr_construct(
+  IN osm_svcr_t* const p_svcr )
+{
+  memset( p_svcr, 0, sizeof(*p_svcr) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_svcr_destroy(
+  IN osm_svcr_t* const p_svcr )
+{
+  free( p_svcr);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_svcr_init(
+  IN osm_svcr_t* const p_svcr,
+  IN const ib_service_record_t *p_svc_rec  )
+{
+  CL_ASSERT( p_svcr );
+
+  p_svcr->modified_time = cl_get_time_stamp_sec();
+
+  /* We track the time left for this service in
+     an external field to avoid extra cl_ntoh/hton
+     required for working with the MAD field */
+  p_svcr->lease_period = cl_ntoh32(p_svc_rec->service_lease);
+  p_svcr->service_record = *p_svc_rec;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_svcr_t*
+osm_svcr_new(
+  IN const ib_service_record_t *p_svc_rec )
+{
+  osm_svcr_t* p_svcr;
+
+  CL_ASSERT(p_svc_rec);
+
+  p_svcr = (osm_svcr_t*)malloc( sizeof(*p_svcr) );
+  if( p_svcr )
+  {
+    osm_svcr_construct( p_svcr );
+    osm_svcr_init( p_svcr, p_svc_rec );
+  }
+
+  return( p_svcr );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static
+cl_status_t
+__match_rid_of_svc_rec(
+
+  IN  const cl_list_item_t* const p_list_item,
+  IN  void*                       context )
+{
+  ib_service_record_t* p_svc_rec = (ib_service_record_t  *)context;
+  osm_svcr_t* p_svcr = (osm_svcr_t*)p_list_item;
+  int32_t count;
+
+  count = memcmp(
+    &p_svcr->service_record,
+    p_svc_rec,
+    sizeof(p_svc_rec->service_id) +
+    sizeof(p_svc_rec->service_gid) +
+    sizeof(p_svc_rec->service_pkey) );
+
+  if(count == 0)
+    return CL_SUCCESS;
+  else
+    return CL_NOT_FOUND;
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_svcr_t*
+osm_svcr_get_by_rid(
+  IN osm_subn_t   const *p_subn,
+  IN osm_log_t *p_log,
+  IN ib_service_record_t* const p_svc_rec )
+{
+  cl_list_item_t* p_list_item;
+
+  OSM_LOG_ENTER( p_log, osm_svcr_get_by_rid );
+
+  p_list_item = cl_qlist_find_from_head(
+    &p_subn->sa_sr_list,
+    __match_rid_of_svc_rec,
+    p_svc_rec);
+
+  if( p_list_item == cl_qlist_end( &p_subn->sa_sr_list ) )
+    p_list_item = NULL;
+
+  OSM_LOG_EXIT( p_log );
+  return (osm_svcr_t*)p_list_item;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_svcr_insert_to_db(
+  IN osm_subn_t   *p_subn,
+  IN osm_log_t *p_log,
+  IN osm_svcr_t   *p_svcr)
+{
+  OSM_LOG_ENTER( p_log, osm_svcr_insert_to_db );
+
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "osm_svcr_insert_to_db: "
+           "Inserting new Service Record into Database\n");
+
+  cl_qlist_insert_head(&p_subn->sa_sr_list,
+                       &p_svcr->list_item);
+
+  OSM_LOG_EXIT( p_log );
+}
+
+void
+osm_svcr_remove_from_db(
+  IN osm_subn_t   *p_subn,
+  IN osm_log_t *p_log,
+  IN osm_svcr_t   *p_svcr)
+{
+  OSM_LOG_ENTER( p_log, osm_svcr_remove_from_db );
+
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "osm_svcr_remove_from_db: "
+           "Removing Service Record Name:%s ID:0x%016" PRIx64" from Database\n",
+           p_svcr->service_record.service_name, p_svcr->service_record.service_id
+           );
+
+  cl_qlist_remove_item(&p_subn->sa_sr_list,
+                       &p_svcr->list_item);
+
+  OSM_LOG_EXIT( p_log );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_slvl_map_rcv.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_slvl_map_rcv.c
new file mode 100644 (file)
index 0000000..8621849
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_slvl_map_rcv.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_slvl_rcv_t.
+ * This object represents the SLtoVL Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_slvl_map_rcv.h>
+#include <opensm/osm_node_info_rcv.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_helper.h>
+#include <vendor/osm_vendor_api.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rcv_construct(
+  IN osm_slvl_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rcv_destroy(
+  IN osm_slvl_rcv_t* const p_rcv )
+{
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_slvl_rcv_destroy );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_slvl_rcv_init(
+  IN osm_slvl_rcv_t* const p_rcv,
+  IN osm_req_t* const p_req,
+  IN osm_subn_t* const p_subn,
+  IN osm_log_t* const p_log,
+  IN cl_plock_t* const p_lock )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_slvl_rcv_init );
+
+  osm_slvl_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_req = p_req;
+
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ * WE MIGHT ONLY RECEIVE A GET or SET responses
+ */
+void
+osm_slvl_rcv_process(
+  IN const osm_slvl_rcv_t* const p_rcv,
+  IN osm_madw_t* const p_madw )
+{
+  cl_qmap_t *p_guid_tbl;
+  ib_slvl_table_t *p_slvl_tbl;
+  ib_smp_t *p_smp;
+  osm_port_t *p_port;
+  osm_physp_t *p_physp;
+  osm_node_t *p_node;
+  osm_slvl_context_t *p_context;
+  ib_net64_t port_guid;
+  ib_net64_t node_guid;
+  uint8_t out_port_num, in_port_num;
+
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_slvl_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+  p_context = osm_madw_get_slvl_context_ptr( p_madw );
+  p_slvl_tbl = (ib_slvl_table_t*)ib_smp_get_payload_ptr( p_smp );
+
+  port_guid = p_context->port_guid;
+  node_guid = p_context->node_guid;
+
+  CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_SLVL_TABLE );
+
+  p_guid_tbl = &p_rcv->p_subn->port_guid_tbl;
+  cl_plock_excl_acquire( p_rcv->p_lock );
+  p_port = (osm_port_t*)cl_qmap_get( p_guid_tbl, port_guid );
+
+  if( p_port == (osm_port_t*)cl_qmap_end( p_guid_tbl) )
+  {
+    cl_plock_release( p_rcv->p_lock );
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_slvl_rcv_process: ERR 2C06: "
+             "No port object for port with GUID 0x%" PRIx64
+             "\n\t\t\t\tfor parent node GUID 0x%" PRIx64
+             ", TID 0x%" PRIx64 "\n",
+             cl_ntoh64( port_guid ),
+             cl_ntoh64( node_guid ),
+             cl_ntoh64( p_smp->trans_id ) );
+    goto Exit;
+  }
+
+  p_node = osm_port_get_parent_node( p_port );
+  CL_ASSERT( p_node );
+
+  /* in case of a non switch node the attr modifier should be ignored */
+  if (osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH)
+  {
+    out_port_num = (uint8_t)cl_ntoh32( p_smp->attr_mod & 0xFF000000);
+    in_port_num  = (uint8_t)cl_ntoh32( (p_smp->attr_mod & 0x00FF0000) << 8);
+    p_physp = osm_node_get_physp_ptr( p_node, out_port_num );
+  }
+  else
+  {
+    p_physp = osm_port_get_default_phys_ptr(p_port);
+    out_port_num = p_port->default_port_num;
+    in_port_num  = 0;
+  }
+
+  CL_ASSERT( p_physp );
+
+  /*
+    We do not mind if this is a result of a set or get - all we want is to update
+    the subnet.
+  */
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "osm_slvl_rcv_process: "
+             "Got SLtoVL get response in_port_num %u out_port_num %u with GUID 0x%" PRIx64
+             " for parent node GUID 0x%" PRIx64
+             ", TID 0x%" PRIx64 "\n",
+             in_port_num, out_port_num,
+             cl_ntoh64( port_guid ),
+             cl_ntoh64( node_guid ),
+             cl_ntoh64( p_smp->trans_id ) );
+  }
+
+  /*
+    Determine if we encountered a new Physical Port.
+    If so, Ignore it.
+  */
+  if( !osm_physp_is_valid( p_physp ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_slvl_rcv_process: "
+             "Got invalid port number 0x%X\n",
+             out_port_num );
+    goto Exit;
+  }
+
+  osm_dump_slvl_map_table( p_rcv->p_log,
+                           port_guid, in_port_num,
+                           out_port_num, p_slvl_tbl,
+                           OSM_LOG_DEBUG );
+
+  osm_physp_set_slvl_tbl( p_physp, p_slvl_tbl, in_port_num);
+
+ Exit:
+  cl_plock_release( p_rcv->p_lock );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_slvl_map_rcv_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_slvl_map_rcv_ctrl.c
new file mode 100644 (file)
index 0000000..040eddd
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_slvl_map_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_slvl_rcv_ctrl_t.
+ * This object represents the SLtoVL request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_slvl_map_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_slvl_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_slvl_rcv_process( ((osm_slvl_rcv_ctrl_t*)context)->p_rcv,
+                        (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rcv_ctrl_construct(
+  IN osm_slvl_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rcv_ctrl_destroy(
+  IN osm_slvl_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_slvl_rcv_ctrl_init(
+  IN osm_slvl_rcv_ctrl_t* const p_ctrl,
+  IN osm_slvl_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_slvl_rcv_ctrl_init );
+
+  osm_slvl_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_SLVL,
+    __osm_slvl_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_slvl_rcv_ctrl_init: ERR 2D01: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sm.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sm.c
new file mode 100644 (file)
index 0000000..e298877
--- /dev/null
@@ -0,0 +1,824 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sm.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_sm_t.
+ * This object represents the SM Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.9 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_sm.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_mcast_mgr.h>
+#include <opensm/osm_mcm_info.h>
+#include <complib/cl_thread.h>
+#include <signal.h>
+
+#define  OSM_SM_INITIAL_TID_VALUE 0x1233
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sm_sweeper(
+   IN void *p_ptr )
+{
+   ib_api_status_t status;
+   osm_sm_t *const p_sm = ( osm_sm_t * ) p_ptr;
+
+   OSM_LOG_ENTER( p_sm->p_log, __osm_sm_sweeper );
+
+   if( p_sm->thread_state == OSM_THREAD_STATE_INIT )
+   {
+      p_sm->thread_state = OSM_THREAD_STATE_RUN;
+   }
+
+   /* If the sweep interval was updated before - then run only if 
+    * it is not zero. */
+   while( p_sm->thread_state == OSM_THREAD_STATE_RUN &&
+          p_sm->p_subn->opt.sweep_interval != 0 )
+   {
+      /*  do the sweep only if we are in MASTER state */
+      if( p_sm->p_subn->sm_state == IB_SMINFO_STATE_MASTER ||
+          p_sm->p_subn->sm_state == IB_SMINFO_STATE_DISCOVERING )
+         osm_state_mgr_process( &p_sm->state_mgr, OSM_SIGNAL_SWEEP );
+
+      /*
+       * Wait on the event with a timeout.
+       * Sweeps may be initiated "off schedule" by simply
+       * signaling the event.
+       */
+      status = cl_event_wait_on( &p_sm->signal,
+                                 p_sm->p_subn->opt.sweep_interval * 1000000,
+                                 TRUE );
+
+      if( status == CL_SUCCESS )
+      {
+         if( osm_log_is_active( p_sm->p_log, OSM_LOG_DEBUG ) )
+         {
+            osm_log( p_sm->p_log, OSM_LOG_DEBUG,
+                     "__osm_sm_sweeper: " "Off schedule sweep signalled\n" );
+         }
+      }
+      else
+      {
+         if( status != CL_TIMEOUT )
+         {
+            osm_log( p_sm->p_log, OSM_LOG_ERROR,
+                     "__osm_sm_sweeper: ERR 2E01: "
+                     "Event wait failed (%s)\n", CL_STATUS_MSG( status ) );
+         }
+      }
+   }
+
+   OSM_LOG_EXIT( p_sm->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_construct(
+   IN osm_sm_t * const p_sm )
+{
+   memset( p_sm, 0, sizeof( *p_sm ) );
+   p_sm->thread_state = OSM_THREAD_STATE_NONE;
+   p_sm->sm_trans_id = OSM_SM_INITIAL_TID_VALUE;
+   cl_event_construct( &p_sm->signal );
+   cl_event_construct( &p_sm->subnet_up_event );
+   cl_thread_construct( &p_sm->sweeper );
+   osm_req_construct( &p_sm->req );
+   osm_req_ctrl_construct( &p_sm->req_ctrl );
+   osm_resp_construct( &p_sm->resp );
+   osm_ni_rcv_construct( &p_sm->ni_rcv );
+   osm_ni_rcv_ctrl_construct( &p_sm->ni_rcv_ctrl );
+   osm_pi_rcv_construct( &p_sm->pi_rcv );
+   osm_pi_rcv_ctrl_construct( &p_sm->pi_rcv_ctrl );
+   osm_nd_rcv_construct( &p_sm->nd_rcv );
+   osm_nd_rcv_ctrl_construct( &p_sm->nd_rcv_ctrl );
+   osm_sm_mad_ctrl_construct( &p_sm->mad_ctrl );
+   osm_si_rcv_construct( &p_sm->si_rcv );
+   osm_si_rcv_ctrl_construct( &p_sm->si_rcv_ctrl );
+   osm_lid_mgr_construct( &p_sm->lid_mgr );
+   osm_ucast_mgr_construct( &p_sm->ucast_mgr );
+   osm_link_mgr_construct( &p_sm->link_mgr );
+   osm_state_mgr_construct( &p_sm->state_mgr );
+   osm_state_mgr_ctrl_construct( &p_sm->state_mgr_ctrl );
+   osm_drop_mgr_construct( &p_sm->drop_mgr );
+   osm_lft_rcv_construct( &p_sm->lft_rcv );
+   osm_lft_rcv_ctrl_construct( &p_sm->lft_rcv_ctrl );
+   osm_mft_rcv_construct( &p_sm->mft_rcv );
+   osm_mft_rcv_ctrl_construct( &p_sm->mft_rcv_ctrl );
+   osm_sweep_fail_ctrl_construct( &p_sm->sweep_fail_ctrl );
+   osm_sminfo_rcv_construct( &p_sm->sm_info_rcv );
+   osm_sminfo_rcv_ctrl_construct( &p_sm->sm_info_rcv_ctrl );
+   osm_trap_rcv_construct( &p_sm->trap_rcv );
+   osm_trap_rcv_ctrl_construct( &p_sm->trap_rcv_ctrl );
+   osm_sm_state_mgr_construct( &p_sm->sm_state_mgr );
+   osm_slvl_rcv_construct( &p_sm->slvl_rcv );
+   osm_slvl_rcv_ctrl_construct( &p_sm->slvl_rcv_ctrl );
+   osm_vla_rcv_construct( &p_sm->vla_rcv );
+   osm_vla_rcv_ctrl_construct( &p_sm->vla_rcv_ctrl );
+   osm_pkey_rcv_construct( &p_sm->pkey_rcv );
+   osm_pkey_rcv_ctrl_construct( &p_sm->pkey_rcv_ctrl );
+   osm_mcast_mgr_construct( &p_sm->mcast_mgr );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_shutdown(
+   IN osm_sm_t * const p_sm )
+{
+   boolean_t signal_event = FALSE;
+
+   OSM_LOG_ENTER( p_sm->p_log, osm_sm_shutdown );
+
+   /*
+    * Signal our threads that we're leaving.
+    */
+   if( p_sm->thread_state != OSM_THREAD_STATE_NONE )
+      signal_event = TRUE;
+
+   p_sm->thread_state = OSM_THREAD_STATE_EXIT;
+
+   /*
+    * Don't trigger unless event has been initialized.
+    * Destroy the thread before we tear down the other objects.
+    */
+   if( signal_event )
+      cl_event_signal( &p_sm->signal );
+
+   cl_thread_destroy( &p_sm->sweeper );
+
+   /*
+    * Always destroy controllers before the corresponding
+    * receiver to guarantee that all callbacks from the
+    * dispatcher are complete.
+    */
+   osm_sm_mad_ctrl_destroy( &p_sm->mad_ctrl );
+   osm_trap_rcv_ctrl_destroy( &p_sm->trap_rcv_ctrl );
+   osm_sminfo_rcv_ctrl_destroy( &p_sm->sm_info_rcv_ctrl );
+   osm_req_ctrl_destroy( &p_sm->req_ctrl );
+   osm_ni_rcv_ctrl_destroy( &p_sm->ni_rcv_ctrl );
+   osm_pi_rcv_ctrl_destroy( &p_sm->pi_rcv_ctrl );
+   osm_si_rcv_ctrl_destroy( &p_sm->si_rcv_ctrl );
+   osm_nd_rcv_ctrl_destroy( &p_sm->nd_rcv_ctrl );
+   osm_lft_rcv_ctrl_destroy( &p_sm->lft_rcv_ctrl );
+   osm_mft_rcv_ctrl_destroy( &p_sm->mft_rcv_ctrl );
+   osm_slvl_rcv_ctrl_destroy( &p_sm->slvl_rcv_ctrl );
+   osm_vla_rcv_ctrl_destroy( &p_sm->vla_rcv_ctrl );
+   osm_pkey_rcv_ctrl_destroy( &p_sm->pkey_rcv_ctrl );
+   osm_sweep_fail_ctrl_destroy( &p_sm->sweep_fail_ctrl );
+   osm_state_mgr_ctrl_destroy( &p_sm->state_mgr_ctrl );
+
+   OSM_LOG_EXIT( p_sm->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_destroy(
+   IN osm_sm_t * const p_sm )
+{
+   OSM_LOG_ENTER( p_sm->p_log, osm_sm_destroy );
+   osm_trap_rcv_destroy( &p_sm->trap_rcv );
+   osm_sminfo_rcv_destroy( &p_sm->sm_info_rcv );
+   osm_req_destroy( &p_sm->req );
+   osm_resp_destroy( &p_sm->resp );
+   osm_ni_rcv_destroy( &p_sm->ni_rcv );
+   osm_pi_rcv_destroy( &p_sm->pi_rcv );
+   osm_si_rcv_destroy( &p_sm->si_rcv );
+   osm_nd_rcv_destroy( &p_sm->nd_rcv );
+   osm_lid_mgr_destroy( &p_sm->lid_mgr );
+   osm_ucast_mgr_destroy( &p_sm->ucast_mgr );
+   osm_link_mgr_destroy( &p_sm->link_mgr );
+   osm_drop_mgr_destroy( &p_sm->drop_mgr );
+   osm_lft_rcv_destroy( &p_sm->lft_rcv );
+   osm_mft_rcv_destroy( &p_sm->mft_rcv );
+   osm_slvl_rcv_destroy( &p_sm->slvl_rcv );
+   osm_vla_rcv_destroy( &p_sm->vla_rcv );
+   osm_pkey_rcv_destroy( &p_sm->pkey_rcv );
+   osm_state_mgr_destroy( &p_sm->state_mgr );
+   osm_sm_state_mgr_destroy( &p_sm->sm_state_mgr );
+   osm_mcast_mgr_destroy( &p_sm->mcast_mgr );
+   cl_event_destroy( &p_sm->signal );
+   cl_event_destroy( &p_sm->subnet_up_event );
+
+   osm_log( p_sm->p_log, OSM_LOG_SYS, "Exiting SM\n" ); /* Format Waived */
+   OSM_LOG_EXIT( p_sm->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_init(
+   IN osm_sm_t * const p_sm,
+   IN osm_subn_t * const p_subn,
+   IN osm_db_t * const p_db,
+   IN osm_vendor_t * const p_vendor,
+   IN osm_mad_pool_t * const p_mad_pool,
+   IN osm_vl15_t * const p_vl15,
+   IN osm_log_t * const p_log,
+   IN osm_stats_t * const p_stats,
+   IN cl_dispatcher_t * const p_disp,
+   IN cl_plock_t * const p_lock )
+{
+   ib_api_status_t status = IB_SUCCESS;
+
+   OSM_LOG_ENTER( p_log, osm_sm_init );
+
+   p_sm->p_subn = p_subn;
+   p_sm->p_db = p_db;
+   p_sm->p_vendor = p_vendor;
+   p_sm->p_mad_pool = p_mad_pool;
+   p_sm->p_vl15 = p_vl15;
+   p_sm->p_log = p_log;
+   p_sm->p_disp = p_disp;
+   p_sm->p_lock = p_lock;
+
+   status = cl_event_init( &p_sm->signal, FALSE );
+   if( status != CL_SUCCESS )
+      goto Exit;
+
+   status = cl_event_init( &p_sm->subnet_up_event, FALSE );
+   if( status != CL_SUCCESS )
+      goto Exit;
+
+   status = osm_sm_mad_ctrl_init( &p_sm->mad_ctrl,
+                                  p_sm->p_subn,
+                                  p_sm->p_mad_pool,
+                                  p_sm->p_vl15,
+                                  p_sm->p_vendor,
+                                  p_log, p_stats, p_lock, p_disp );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_req_init( &p_sm->req,
+                          p_mad_pool,
+                          p_vl15, p_subn, p_log, &p_sm->sm_trans_id );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_req_ctrl_init( &p_sm->req_ctrl, &p_sm->req, p_log, p_disp );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_resp_init( &p_sm->resp, p_mad_pool, p_vl15, p_subn, p_log );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_ni_rcv_init( &p_sm->ni_rcv,
+                             &p_sm->req,
+                             p_subn, p_log, &p_sm->state_mgr, p_lock );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_ni_rcv_ctrl_init( &p_sm->ni_rcv_ctrl,
+                                  &p_sm->ni_rcv, p_log, p_disp );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_pi_rcv_init( &p_sm->pi_rcv,
+                             &p_sm->req,
+                             p_subn, p_log, &p_sm->state_mgr, p_lock );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_pi_rcv_ctrl_init( &p_sm->pi_rcv_ctrl,
+                                  &p_sm->pi_rcv, p_log, p_disp );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_si_rcv_init( &p_sm->si_rcv,
+                             p_sm->p_subn,
+                             p_sm->p_log,
+                             &p_sm->req, &p_sm->state_mgr, p_sm->p_lock );
+
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_si_rcv_ctrl_init( &p_sm->si_rcv_ctrl,
+                                  &p_sm->si_rcv, p_sm->p_log, p_sm->p_disp );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_nd_rcv_init( &p_sm->nd_rcv, p_subn, p_log, p_lock );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_nd_rcv_ctrl_init( &p_sm->nd_rcv_ctrl,
+                                  &p_sm->nd_rcv, p_log, p_disp );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_lid_mgr_init( &p_sm->lid_mgr,
+                              &p_sm->req,
+                              p_sm->p_subn,
+                              p_sm->p_db, p_sm->p_log, p_sm->p_lock );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_ucast_mgr_init( &p_sm->ucast_mgr,
+                                &p_sm->req,
+                                p_sm->p_subn,
+                                p_sm->p_log, p_sm->p_lock );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_link_mgr_init( &p_sm->link_mgr,
+                               &p_sm->req,
+                               p_sm->p_subn, p_sm->p_log, p_sm->p_lock );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_state_mgr_init( &p_sm->state_mgr,
+                                p_sm->p_subn,
+                                &p_sm->lid_mgr,
+                                &p_sm->ucast_mgr,
+                                &p_sm->mcast_mgr,
+                                &p_sm->link_mgr,
+                                &p_sm->drop_mgr,
+                                &p_sm->req,
+                                p_stats,
+                                &p_sm->sm_state_mgr,
+                                &p_sm->mad_ctrl,
+                                p_sm->p_lock,
+                                &p_sm->subnet_up_event,
+                                p_sm->p_log );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_state_mgr_ctrl_init( &p_sm->state_mgr_ctrl,
+                                     &p_sm->state_mgr,
+                                     p_sm->p_log, p_sm->p_disp );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_drop_mgr_init( &p_sm->drop_mgr,
+                               p_sm->p_subn,
+                               p_sm->p_log, &p_sm->req, p_sm->p_lock );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_lft_rcv_init( &p_sm->lft_rcv, p_subn, p_log, p_lock );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_lft_rcv_ctrl_init( &p_sm->lft_rcv_ctrl,
+                                   &p_sm->lft_rcv, p_log, p_disp );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_mft_rcv_init( &p_sm->mft_rcv, p_subn, p_log, p_lock );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_mft_rcv_ctrl_init( &p_sm->mft_rcv_ctrl,
+                                   &p_sm->mft_rcv, p_log, p_disp );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_sweep_fail_ctrl_init( &p_sm->sweep_fail_ctrl,
+                                      p_log, &p_sm->state_mgr, p_disp );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_sminfo_rcv_init( &p_sm->sm_info_rcv,
+                                 p_subn,
+                                 p_stats,
+                                 &p_sm->resp,
+                                 p_log,
+                                 &p_sm->state_mgr,
+                                 &p_sm->sm_state_mgr, p_lock );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_sminfo_rcv_ctrl_init( &p_sm->sm_info_rcv_ctrl,
+                                      &p_sm->sm_info_rcv,
+                                      p_sm->p_log, p_disp );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_trap_rcv_init( &p_sm->trap_rcv,
+                               p_subn,
+                               p_stats,
+                               &p_sm->resp, p_log, &p_sm->state_mgr, p_lock );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_trap_rcv_ctrl_init( &p_sm->trap_rcv_ctrl,
+                                    &p_sm->trap_rcv, p_sm->p_log, p_disp );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_sm_state_mgr_init( &p_sm->sm_state_mgr,
+                                   &p_sm->state_mgr,
+                                   p_sm->p_subn, &p_sm->req, p_sm->p_log );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_mcast_mgr_init( &p_sm->mcast_mgr,
+                                &p_sm->req, p_subn, p_log, p_lock );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_slvl_rcv_init( &p_sm->slvl_rcv,
+                               &p_sm->req, p_subn, p_log, p_lock );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_slvl_rcv_ctrl_init( &p_sm->slvl_rcv_ctrl,
+                                    &p_sm->slvl_rcv, p_sm->p_log, p_disp );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_vla_rcv_init( &p_sm->vla_rcv,
+                              &p_sm->req, p_subn, p_log, p_lock );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_vla_rcv_ctrl_init( &p_sm->vla_rcv_ctrl,
+                                   &p_sm->vla_rcv, p_sm->p_log, p_disp );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_pkey_rcv_init( &p_sm->pkey_rcv,
+                               &p_sm->req, p_subn, p_log, p_lock );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   status = osm_pkey_rcv_ctrl_init( &p_sm->pkey_rcv_ctrl,
+                                    &p_sm->pkey_rcv, p_sm->p_log, p_disp );
+   if( status != IB_SUCCESS )
+      goto Exit;
+
+   /*
+    * Now that the component objects are initialized, start
+    * the sweeper thread if the user wants sweeping.
+    */
+   if( p_sm->p_subn->opt.sweep_interval )
+   {
+      p_sm->thread_state = OSM_THREAD_STATE_INIT;
+      status = cl_thread_init( &p_sm->sweeper, __osm_sm_sweeper, p_sm,
+                               "opensm sweeper" );
+      if( status != IB_SUCCESS )
+         goto Exit;
+   }
+
+ Exit:
+   OSM_LOG_EXIT( p_log );
+   return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_sweep(
+   IN osm_sm_t * const p_sm )
+{
+   OSM_LOG_ENTER( p_sm->p_log, osm_sm_sweep );
+   osm_state_mgr_process( &p_sm->state_mgr, OSM_SIGNAL_SWEEP );
+   OSM_LOG_EXIT( p_sm->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_bind(
+   IN osm_sm_t * const p_sm,
+   IN const ib_net64_t port_guid )
+{
+   ib_api_status_t status;
+
+   OSM_LOG_ENTER( p_sm->p_log, osm_sm_bind );
+
+   status = osm_sm_mad_ctrl_bind( &p_sm->mad_ctrl, port_guid );
+
+   if( status != IB_SUCCESS )
+   {
+      osm_log( p_sm->p_log, OSM_LOG_ERROR,
+               "osm_sm_bind: ERR 2E10: "
+               "SM MAD Controller bind failed (%s)\n",
+               ib_get_err_str( status ) );
+      goto Exit;
+   }
+
+ Exit:
+   OSM_LOG_EXIT( p_sm->p_log );
+   return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_sm_mgrp_connect(
+   IN osm_sm_t * const p_sm,
+   IN osm_mgrp_t * const p_mgrp,
+   IN const ib_net64_t port_guid,
+   IN osm_mcast_req_type_t req_type )
+{
+   ib_api_status_t status;
+   osm_mcast_mgr_ctxt_t *ctx2;
+
+   OSM_LOG_ENTER( p_sm->p_log, __osm_sm_mgrp_connect );
+
+   /*
+    * 'Schedule' all the QP0 traffic for when the state manager
+    * isn't busy trying to do something else.
+    */
+   ctx2 =
+      ( osm_mcast_mgr_ctxt_t * ) malloc( sizeof( osm_mcast_mgr_ctxt_t ) );
+   memcpy( &ctx2->mlid, &p_mgrp->mlid, sizeof( p_mgrp->mlid ) );
+   ctx2->req_type = req_type;
+   ctx2->port_guid = port_guid;
+
+   status = osm_state_mgr_process_idle( &p_sm->state_mgr,
+                                        osm_mcast_mgr_process_mgrp_cb,
+                                        NULL, &p_sm->mcast_mgr,
+                                        ( void * )ctx2 );
+
+   OSM_LOG_EXIT( p_sm->p_log );
+   return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sm_mgrp_disconnect(
+   IN osm_sm_t * const p_sm,
+   IN osm_mgrp_t * const p_mgrp,
+   IN const ib_net64_t port_guid )
+{
+   ib_api_status_t status;
+   osm_mcast_mgr_ctxt_t *ctx2;
+
+   OSM_LOG_ENTER( p_sm->p_log, __osm_sm_mgrp_disconnect );
+
+   /*
+    * 'Schedule' all the QP0 traffic for when the state manager
+    * isn't busy trying to do something else.
+    */
+   ctx2 =
+      ( osm_mcast_mgr_ctxt_t * ) malloc( sizeof( osm_mcast_mgr_ctxt_t ) );
+   memcpy( &ctx2->mlid, &p_mgrp->mlid, sizeof( p_mgrp->mlid ) );
+   ctx2->req_type = OSM_MCAST_REQ_TYPE_LEAVE;
+   ctx2->port_guid = port_guid;
+
+   status = osm_state_mgr_process_idle( &p_sm->state_mgr,
+                                        osm_mcast_mgr_process_mgrp_cb,
+                                        NULL, &p_sm->mcast_mgr, ctx2 );
+   if( status != IB_SUCCESS )
+   {
+      osm_log( p_sm->p_log, OSM_LOG_ERROR,
+               "__osm_sm_mgrp_disconnect: ERR 2E11: "
+               "Failure processing multicast group (%s)\n",
+               ib_get_err_str( status ) );
+   }
+
+   OSM_LOG_EXIT( p_sm->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_mcgrp_join(
+   IN osm_sm_t * const p_sm,
+   IN const ib_net16_t mlid,
+   IN const ib_net64_t port_guid,
+   IN osm_mcast_req_type_t req_type )
+{
+   osm_mgrp_t *p_mgrp;
+   osm_port_t *p_port;
+   cl_qmap_t *p_tbl;
+   ib_api_status_t status = IB_SUCCESS;
+   osm_mcm_info_t *p_mcm;
+
+   OSM_LOG_ENTER( p_sm->p_log, osm_sm_mcgrp_join );
+
+   osm_log( p_sm->p_log, OSM_LOG_VERBOSE,
+            "osm_sm_mcgrp_join: "
+            "Port 0x%016" PRIx64 " joining MLID 0x%X\n",
+            cl_ntoh64( port_guid ), cl_ntoh16( mlid ) );
+
+   /*
+    * Acquire the port object for the port joining this group.
+    */
+   CL_PLOCK_EXCL_ACQUIRE( p_sm->p_lock );
+   p_port = ( osm_port_t * ) cl_qmap_get( &p_sm->p_subn->port_guid_tbl,
+                                          port_guid );
+   if( p_port ==
+       ( osm_port_t * ) cl_qmap_end( &p_sm->p_subn->port_guid_tbl ) )
+   {
+      CL_PLOCK_RELEASE( p_sm->p_lock );
+      osm_log( p_sm->p_log, OSM_LOG_ERROR,
+               "osm_sm_mcgrp_join: ERR 2E05: "
+               "No port object for port 0x%016" PRIx64 "\n",
+               cl_ntoh64( port_guid ) );
+      status = IB_INVALID_PARAMETER;
+      goto Exit;
+   }
+
+   /*
+    * If this multicast group does not already exist, create it.
+    */
+   p_tbl = &p_sm->p_subn->mgrp_mlid_tbl;
+   p_mgrp = ( osm_mgrp_t * ) cl_qmap_get( p_tbl, mlid );
+   if( p_mgrp == ( osm_mgrp_t * ) cl_qmap_end( p_tbl ) )
+   {
+      osm_log( p_sm->p_log, OSM_LOG_VERBOSE,
+               "osm_sm_mcgrp_join: "
+               "Creating group, MLID 0x%X\n", cl_ntoh16( mlid ) );
+
+      p_mgrp = osm_mgrp_new( mlid );
+      if( p_mgrp == NULL )
+      {
+         CL_PLOCK_RELEASE( p_sm->p_lock );
+         osm_log( p_sm->p_log, OSM_LOG_ERROR,
+                  "osm_sm_mcgrp_join: ERR 2E06: "
+                  "Unable to allocate multicast group object\n" );
+         status = IB_INSUFFICIENT_MEMORY;
+         goto Exit;
+      }
+
+      cl_qmap_insert( p_tbl, mlid, &p_mgrp->map_item );
+   }
+   else
+   {
+      /*
+       * The group already exists.  If the port is not a
+       * member of the group, then fail immediately.
+       * This can happen since the spinlock is released briefly
+       * before the SA calls this function.
+       */
+      if( !osm_mgrp_is_guid( p_mgrp, port_guid ) )
+      {
+         CL_PLOCK_RELEASE( p_sm->p_lock );
+         osm_log( p_sm->p_log, OSM_LOG_ERROR,
+                  "osm_sm_mcgrp_join: ERR 2E12: "
+                  "Port 0x%016" PRIx64 " not in mcast group 0x%X\n",
+                  cl_ntoh64( port_guid ), cl_ntoh16( mlid ) );
+         status = IB_NOT_FOUND;
+         goto Exit;
+      }
+   }
+
+   /* 
+    * Check if the object (according to mlid) already exists on this port.
+    * If it does - then no need to update it again, and no need to 
+    * create the mc tree again. Just goto Exit.
+    */
+   p_mcm = ( osm_mcm_info_t * ) cl_qlist_head( &p_port->mcm_list );
+   while( p_mcm != ( osm_mcm_info_t * ) cl_qlist_end( &p_port->mcm_list ) )
+   {
+      if( p_mcm->mlid == mlid )
+      {
+         CL_PLOCK_RELEASE( p_sm->p_lock );
+         osm_log( p_sm->p_log, OSM_LOG_DEBUG,
+                  "osm_sm_mcgrp_join: "
+                  "Found mlid object for Port:"
+                  "0x%016" PRIx64 " lid:0x%X\n",
+                  cl_ntoh64( port_guid ), cl_ntoh16( mlid ) );
+         goto Exit;
+      }
+      p_mcm = ( osm_mcm_info_t * ) cl_qlist_next( &p_mcm->list_item );
+   }
+
+   status = osm_port_add_mgrp( p_port, mlid );
+   if( status != IB_SUCCESS )
+   {
+      CL_PLOCK_RELEASE( p_sm->p_lock );
+      osm_log( p_sm->p_log, OSM_LOG_ERROR,
+               "osm_sm_mcgrp_join: ERR 2E03: "
+               "Unable to associate port 0x%" PRIx64 " to mlid 0x%X\n",
+               cl_ntoh64( osm_port_get_guid( p_port ) ),
+               cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) ) );
+      goto Exit;
+   }
+
+   CL_PLOCK_RELEASE( p_sm->p_lock );
+   status = __osm_sm_mgrp_connect( p_sm, p_mgrp, port_guid, req_type );
+
+ Exit:
+   OSM_LOG_EXIT( p_sm->p_log );
+   return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_mcgrp_leave(
+   IN osm_sm_t * const p_sm,
+   IN const ib_net16_t mlid,
+   IN const ib_net64_t port_guid )
+{
+   osm_mgrp_t *p_mgrp;
+   osm_port_t *p_port;
+   cl_qmap_t *p_tbl;
+   ib_api_status_t status = IB_SUCCESS;
+
+   OSM_LOG_ENTER( p_sm->p_log, osm_sm_mcgrp_leave );
+
+   osm_log( p_sm->p_log, OSM_LOG_VERBOSE,
+            "osm_sm_mcgrp_leave: "
+            "Port 0x%" PRIx64 " leaving MLID 0x%X\n",
+            cl_ntoh64( port_guid ), cl_ntoh16( mlid ) );
+
+   /*
+    * Acquire the port object for the port leaving this group.
+    */
+   /* note: p_sm->p_lock is locked by caller, but will be released later
+      this function */
+   p_port = ( osm_port_t * ) cl_qmap_get( &p_sm->p_subn->port_guid_tbl,
+                                          port_guid );
+   if( p_port ==
+       ( osm_port_t * ) cl_qmap_end( &p_sm->p_subn->port_guid_tbl ) )
+   {
+      CL_PLOCK_RELEASE( p_sm->p_lock );
+      osm_log( p_sm->p_log, OSM_LOG_ERROR,
+               "osm_sm_mcgrp_leave: ERR 2E04: "
+               "No port object for port 0x%" PRIx64 "\n",
+               cl_ntoh64( port_guid ) );
+      status = IB_INVALID_PARAMETER;
+      goto Exit;
+   }
+
+   /*
+    * Get the multicast group object for this group.
+    */
+   p_tbl = &p_sm->p_subn->mgrp_mlid_tbl;
+   p_mgrp = ( osm_mgrp_t * ) cl_qmap_get( p_tbl, mlid );
+   if( p_mgrp == ( osm_mgrp_t * ) cl_qmap_end( p_tbl ) )
+   {
+      CL_PLOCK_RELEASE( p_sm->p_lock );
+      osm_log( p_sm->p_log, OSM_LOG_ERROR,
+               "osm_sm_mcgrp_leave: ERR 2E08: "
+               "No multicast group for MLID 0x%X\n", cl_ntoh16( mlid ) );
+      status = IB_INVALID_PARAMETER;
+      goto Exit;
+   }
+
+   /*
+    * Walk the list of ports in the group, and remove the appropriate one.
+    */
+   osm_mgrp_remove_port( p_sm->p_subn, p_sm->p_log, p_mgrp, port_guid );
+
+   osm_port_remove_mgrp( p_port, mlid );
+
+   CL_PLOCK_RELEASE( p_sm->p_lock );
+
+   __osm_sm_mgrp_disconnect( p_sm, p_mgrp, port_guid );
+
+ Exit:
+   OSM_LOG_EXIT( p_sm->p_log );
+   return ( status );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sm_mad_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sm_mad_ctrl.c
new file mode 100644 (file)
index 0000000..87b5642
--- /dev/null
@@ -0,0 +1,1049 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sm_mad_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_sm_mad_ctrl_t.
+ * This object represents the SM MAD request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_sm_mad_ctrl.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_opensm.h>
+
+/****f* opensm: SM/__osm_sm_mad_ctrl_retire_trans_mad
+ * NAME
+ * __osm_sm_mad_ctrl_retire_trans_mad
+ *
+ * DESCRIPTION
+ * This function handles clean-up of MADs associated with the SM's
+ * outstanding transactions on the wire.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sm_mad_ctrl_retire_trans_mad(
+  IN osm_sm_mad_ctrl_t* const p_ctrl,
+  IN osm_madw_t* const p_madw )
+{
+  uint32_t outstanding;
+  cl_status_t status;
+
+  OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_retire_trans_mad );
+
+  CL_ASSERT( p_madw );
+  /*
+    Return the MAD & wrapper to the pool.
+  */
+  if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+             "__osm_sm_mad_ctrl_retire_trans_mad: "
+             "Retiring MAD with TID 0x%" PRIx64 "\n",
+             cl_ntoh64( osm_madw_get_smp_ptr( p_madw )->trans_id ) );
+  }
+
+  osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+
+  outstanding = cl_atomic_dec( &p_ctrl->p_stats->qp0_mads_outstanding );
+
+  if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+             "__osm_sm_mad_ctrl_retire_trans_mad: "
+             "%u QP0 MADs outstanding\n",
+             p_ctrl->p_stats->qp0_mads_outstanding );
+  }
+
+  if( outstanding == 0 )
+  {
+    /*
+      The wire is clean.
+      Signal the state manager.
+    */
+    if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+               "__osm_sm_mad_ctrl_retire_trans_mad: "
+               "Posting Dispatcher message %s\n",
+               osm_get_disp_msg_str( OSM_MSG_NO_SMPS_OUTSTANDING ) );
+    }
+
+    status = cl_disp_post( p_ctrl->h_disp,
+                           OSM_MSG_NO_SMPS_OUTSTANDING,
+                           (void *)OSM_SIGNAL_NO_PENDING_TRANSACTIONS,
+                           NULL,
+                           NULL );
+
+    if( status != CL_SUCCESS )
+    {
+      osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+               "__osm_sm_mad_ctrl_retire_trans_mad: ERR 3101: "
+               "Dispatcher post message failed (%s)\n",
+               CL_STATUS_MSG( status ) );
+      goto Exit;
+    }
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_ctrl->p_log );
+}
+/************/
+
+/****f* opensm: SM/__osm_sm_mad_ctrl_disp_done_callback
+ * NAME
+ * __osm_sm_mad_ctrl_disp_done_callback
+ *
+ * DESCRIPTION
+ * This function is the Dispatcher callback that indicates
+ * a received MAD has been processed by the recipient.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sm_mad_ctrl_disp_done_callback(
+  IN void*              context,
+  IN void*              p_data )
+{
+  osm_sm_mad_ctrl_t*       const p_ctrl = (osm_sm_mad_ctrl_t*)context;
+  osm_madw_t*              const p_madw = (osm_madw_t*)p_data;
+  ib_smp_t              *p_smp;
+
+  OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_disp_done_callback );
+
+  /*
+    If the MAD that just finished processing was a response,
+    then retire the transaction, since we must have generated
+    the request.
+
+    Otherwise, retire the transaction if a response was expected,
+    as in the case of a send failure. If a response was not expected,
+    just put the MAD back in the pool, because the MAD was a query
+    from some outside agent, e.g. Get(SMInfo) from another SM.
+  */
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+  if( ib_smp_is_response( p_smp ) )
+  {
+    CL_ASSERT( p_madw->resp_expected == FALSE );
+    __osm_sm_mad_ctrl_retire_trans_mad( p_ctrl, p_madw );
+  }
+  else
+  {
+    if( p_madw->resp_expected == TRUE )
+      __osm_sm_mad_ctrl_retire_trans_mad( p_ctrl, p_madw );
+    else
+      osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+  }
+
+  OSM_LOG_EXIT( p_ctrl->p_log );
+}
+/************/
+
+/****f* opensm: SM/__osm_sm_mad_ctrl_update_wire_stats
+ * NAME
+ * __osm_sm_mad_ctrl_update_wire_stats
+ *
+ * DESCRIPTION
+ * Updates wire stats for outstanding MADs and calls the VL15 poller.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sm_mad_ctrl_update_wire_stats(
+  IN osm_sm_mad_ctrl_t* const p_ctrl )
+{
+  uint32_t mads_on_wire;
+
+  OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_update_wire_stats );
+
+  mads_on_wire = cl_atomic_dec(
+    &p_ctrl->p_stats->qp0_mads_outstanding_on_wire );
+
+  if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+             "__osm_sm_mad_ctrl_update_wire_stats: "
+             "%u SMPs on the wire, %u outstanding\n", mads_on_wire,
+             p_ctrl->p_stats->qp0_mads_outstanding );
+  }
+
+  /*
+    We can signal the VL15 controller to send another MAD
+    if any are waiting for transmission.
+  */
+  osm_vl15_poll( p_ctrl->p_vl15 );
+  OSM_LOG_EXIT( p_ctrl->p_log );
+}
+
+/****f* opensm: SM/__osm_sm_mad_ctrl_process_get_resp
+ * NAME
+ * __osm_sm_mad_ctrl_process_get_resp
+ *
+ * DESCRIPTION
+ * This function handles method GetResp() for received MADs.
+ * This is the most common path for QP0 MADs.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sm_mad_ctrl_process_get_resp(
+  IN osm_sm_mad_ctrl_t* const p_ctrl,
+  IN osm_madw_t *p_madw,
+  IN void* transaction_context )
+{
+  ib_smp_t* p_smp;
+  cl_status_t status;
+  osm_madw_t* p_old_madw;
+  cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
+
+  OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_process_get_resp );
+
+  CL_ASSERT( p_madw );
+  CL_ASSERT( transaction_context );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+
+  if( p_smp->mgmt_class == IB_MCLASS_SUBN_DIR )
+  {
+    if( !ib_smp_is_d( p_smp ) )
+    {
+      osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+               "__osm_sm_mad_ctrl_process_get_resp: ERR 3102: "
+               "'D' bit not set in returned SMP\n" );
+      osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_ERROR );
+    }
+  }
+
+  p_old_madw = (osm_madw_t*)transaction_context;
+
+  __osm_sm_mad_ctrl_update_wire_stats( p_ctrl );
+
+  /*
+    Copy the MAD Wrapper context from the requesting MAD
+    to the new MAD.  This mechanism allows the recipient
+    controller to recover its own context regarding this
+    MAD transaction.  Once we've copied the context, we
+    can return the original MAD to the pool.
+  */
+  osm_madw_copy_context( p_madw, p_old_madw );
+  osm_mad_pool_put( p_ctrl->p_mad_pool, p_old_madw );
+
+  /*
+    Note that attr_id (like the rest of the MAD) is in
+    network byte order.
+  */
+  switch( p_smp->attr_id )
+  {
+  case IB_MAD_ATTR_NODE_DESC:
+    msg_id = OSM_MSG_MAD_NODE_DESC;
+    break;
+  case IB_MAD_ATTR_NODE_INFO:
+    msg_id = OSM_MSG_MAD_NODE_INFO;
+    break;
+  case IB_MAD_ATTR_SWITCH_INFO:
+    msg_id = OSM_MSG_MAD_SWITCH_INFO;
+    break;
+  case IB_MAD_ATTR_PORT_INFO:
+    msg_id = OSM_MSG_MAD_PORT_INFO;
+    break;
+  case IB_MAD_ATTR_LIN_FWD_TBL:
+    msg_id = OSM_MSG_MAD_LFT;
+    break;
+  case IB_MAD_ATTR_MCAST_FWD_TBL:
+    msg_id = OSM_MSG_MAD_MFT;
+    break;
+  case IB_MAD_ATTR_SM_INFO:
+    msg_id = OSM_MSG_MAD_SM_INFO;
+    break;
+  case IB_MAD_ATTR_SLVL_TABLE:
+    msg_id = OSM_MSG_MAD_SLVL;
+    break;
+  case IB_MAD_ATTR_VL_ARBITRATION:
+    msg_id = OSM_MSG_MAD_VL_ARB;
+    break;
+  case IB_MAD_ATTR_P_KEY_TABLE:
+    msg_id = OSM_MSG_MAD_PKEY;
+    break;
+
+  case IB_MAD_ATTR_GUID_INFO:
+  case IB_MAD_ATTR_CLASS_PORT_INFO:
+  case IB_MAD_ATTR_NOTICE:
+  case IB_MAD_ATTR_INFORM_INFO:
+  default:
+    osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+             "__osm_sm_mad_ctrl_process_get_resp: ERR 3103: "
+             "Unsupported attribute = 0x%X\n",
+             cl_ntoh16( p_smp->attr_id ) );
+    osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_ERROR );
+    goto Exit;
+  }
+
+  if( msg_id != CL_DISP_MSGID_NONE )
+  {
+    /*
+      Post this MAD to the dispatcher for asynchronous
+      processing by the appropriate controller.
+    */
+
+    if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+               "__osm_sm_mad_ctrl_process_get_resp: "
+               "Posting Dispatcher message %s\n",
+               osm_get_disp_msg_str( msg_id ) );
+    }
+
+    status = cl_disp_post( p_ctrl->h_disp,
+                           msg_id,
+                           p_madw,
+                           __osm_sm_mad_ctrl_disp_done_callback,
+                           p_ctrl );
+
+    if( status != CL_SUCCESS )
+    {
+      osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+               "__osm_sm_mad_ctrl_process_get_resp: ERR 3104: "
+               "Dispatcher post message failed (%s) for attribute = 0x%X\n",
+               CL_STATUS_MSG( status ),
+               cl_ntoh16( p_smp->attr_id ) );
+      goto Exit;
+    }
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_ctrl->p_log );
+}
+
+/****f* opensm: SM/__osm_sm_mad_ctrl_process_get
+ * NAME
+ * __osm_sm_mad_ctrl_process_get
+ *
+ * DESCRIPTION
+ * This function handles method Get() for received MADs.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sm_mad_ctrl_process_get(
+  IN osm_sm_mad_ctrl_t* const p_ctrl,
+  IN osm_madw_t *p_madw )
+{
+  ib_smp_t* p_smp;
+  cl_status_t status;
+  cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
+
+  OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_process_get );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+
+  /*
+    Note that attr_id (like the rest of the MAD) is in
+    network byte order.
+  */
+  switch( p_smp->attr_id )
+  {
+  case IB_MAD_ATTR_SM_INFO:
+    msg_id = OSM_MSG_MAD_SM_INFO;
+    break;
+
+  default:
+    osm_log( p_ctrl->p_log, OSM_LOG_VERBOSE,
+             "__osm_sm_mad_ctrl_process_get: "
+             "Ignoring SubnGet MAD - unsupported attribute = 0x%X\n",
+             cl_ntoh16( p_smp->attr_id ) );
+    break;
+  }
+
+  if( msg_id != CL_DISP_MSGID_NONE )
+  {
+    /*
+      Post this MAD to the dispatcher for asynchronous
+      processing by the appropriate controller.
+    */
+
+    if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+               "__osm_sm_mad_ctrl_process_get: "
+               "Posting Dispatcher message %s\n",
+               osm_get_disp_msg_str( msg_id ) );
+    }
+
+    status = cl_disp_post( p_ctrl->h_disp,
+                           msg_id,
+                           p_madw,
+                           __osm_sm_mad_ctrl_disp_done_callback,
+                           p_ctrl );
+
+    if( status != CL_SUCCESS )
+    {
+      osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+               "__osm_sm_mad_ctrl_process_get: ERR 3106: "
+               "Dispatcher post message failed (%s)\n",
+               CL_STATUS_MSG( status ) );
+      goto Exit;
+    }
+  }
+  else
+  {
+    /*
+      There is an unknown MAD attribute type for which there is
+      no recipient.  Simply retire the MAD here.
+    */
+    osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_ctrl->p_log );
+}
+/*
+ * PARAMETERS
+ *
+ * RETURN VALUES
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* opensm: SM/__osm_sm_mad_ctrl_process_set
+ * NAME
+ * __osm_sm_mad_ctrl_process_set
+ *
+ * DESCRIPTION
+ * This function handles method Set() for received MADs.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sm_mad_ctrl_process_set(
+  IN osm_sm_mad_ctrl_t* const p_ctrl,
+  IN osm_madw_t *p_madw )
+{
+  ib_smp_t* p_smp;
+  cl_status_t status;
+  cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
+
+  OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_process_set );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+
+  /*
+    Note that attr_id (like the rest of the MAD) is in
+    network byte order.
+  */
+  switch( p_smp->attr_id )
+  {
+  case IB_MAD_ATTR_SM_INFO:
+    msg_id = OSM_MSG_MAD_SM_INFO;
+    break;
+
+  default:
+    osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+             "__osm_sm_mad_ctrl_process_set: ERR 3107: "
+             "Unsupported attribute = 0x%X\n",
+             cl_ntoh16( p_smp->attr_id ) );
+    osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_ERROR );
+    break;
+  }
+
+  if( msg_id != CL_DISP_MSGID_NONE )
+  {
+    /*
+      Post this MAD to the dispatcher for asynchronous
+      processing by the appropriate controller.
+    */
+
+    if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+               "__osm_sm_mad_ctrl_process_set: "
+               "Posting Dispatcher message %s\n",
+               osm_get_disp_msg_str( msg_id ) );
+    }
+
+    status = cl_disp_post( p_ctrl->h_disp,
+                           msg_id,
+                           p_madw,
+                           __osm_sm_mad_ctrl_disp_done_callback,
+                           p_ctrl );
+
+    if( status != CL_SUCCESS )
+    {
+      osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+               "__osm_sm_mad_ctrl_process_set: ERR 3108: "
+               "Dispatcher post message failed (%s)\n",
+               CL_STATUS_MSG( status ) );
+      goto Exit;
+    }
+  }
+  else
+  {
+    /*
+      There is an unknown MAD attribute type for which there is
+      no recipient.  Simply retire the MAD here.
+    */
+    osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_ctrl->p_log );
+}
+/*
+ * PARAMETERS
+ *
+ * RETURN VALUES
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* opensm: SM/__osm_sm_mad_ctrl_process_trap
+ * NAME
+ * __osm_sm_mad_ctrl_process_trap
+ *
+ * DESCRIPTION
+ * This function handles method Trap() for received MADs.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sm_mad_ctrl_process_trap(
+  IN osm_sm_mad_ctrl_t* const p_ctrl,
+  IN osm_madw_t *p_madw )
+{
+  ib_smp_t* p_smp;
+  cl_status_t status;
+  cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
+
+  OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_process_trap );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+
+  /* Make sure OpenSM is master. If not - then we should not process the trap */
+  if (p_ctrl->p_subn->sm_state != IB_SMINFO_STATE_MASTER)
+  {
+    osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+             "__osm_sm_mad_ctrl_process_trap: "
+             "Received trap but OpenSM is not in MASTER state. "
+             "Dropping mad\n");
+    osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+    goto Exit;
+  }
+
+  /*
+    Note that attr_id (like the rest of the MAD) is in
+    network byte order.
+  */
+  switch( p_smp->attr_id )
+  {
+  case IB_MAD_ATTR_NOTICE:
+    msg_id = OSM_MSG_MAD_NOTICE;
+    break;
+
+  default:
+    osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+             "__osm_sm_mad_ctrl_process_trap: ERR 3109: "
+             "Unsupported attribute = 0x%X\n",
+             cl_ntoh16( p_smp->attr_id ) );
+    osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_ERROR );
+    break;
+  }
+
+  if( msg_id != CL_DISP_MSGID_NONE )
+  {
+    /*
+      Post this MAD to the dispatcher for asynchronous
+      processing by the appropriate controller.
+    */
+
+    if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+               "__osm_sm_mad_ctrl_process_trap: "
+               "Posting Dispatcher message %s\n",
+               osm_get_disp_msg_str( msg_id ) );
+    }
+
+    status = cl_disp_post( p_ctrl->h_disp,
+                           msg_id,
+                           p_madw,
+                           __osm_sm_mad_ctrl_disp_done_callback,
+                           p_ctrl );
+
+    if( status != CL_SUCCESS )
+    {
+      osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+               "__osm_sm_mad_ctrl_process_trap: ERR 3110: "
+               "Dispatcher post message failed (%s)\n",
+               CL_STATUS_MSG( status ) );
+      goto Exit;
+    }
+  }
+  else
+  {
+    /*
+      There is an unknown MAD attribute type for which there is
+      no recipient.  Simply retire the MAD here.
+    */
+    osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_ctrl->p_log );
+}
+/*
+ * PARAMETERS
+ *
+ * RETURN VALUES
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* opensm: SM/__osm_sm_mad_ctrl_rcv_callback
+ * NAME
+ * __osm_sm_mad_ctrl_rcv_callback
+ *
+ * DESCRIPTION
+ * This is the callback from the transport layer for received MADs.
+ *
+ * SYNOPSIS
+ */
+void
+__osm_sm_mad_ctrl_rcv_callback(
+  IN osm_madw_t *p_madw,
+  IN void *bind_context,
+  IN osm_madw_t *p_req_madw )
+{
+  osm_sm_mad_ctrl_t* p_ctrl = (osm_sm_mad_ctrl_t*)bind_context;
+  ib_smp_t* p_smp;
+  ib_net16_t status;
+
+  OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_rcv_callback );
+
+  CL_ASSERT( p_madw );
+
+  /*
+    A MAD was received from the wire, possibly in response to a request.
+  */
+  cl_atomic_inc( &p_ctrl->p_stats->qp0_mads_rcvd );
+
+  if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+             "__osm_sm_mad_ctrl_rcv_callback: "
+             "%u QP0 MADs received\n",
+             p_ctrl->p_stats->qp0_mads_rcvd );
+  }
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+
+  /* if we are closing down simply do nothing */
+  if (osm_exit_flag)
+  {
+    osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+             "__osm_sm_mad_ctrl_rcv_callback: "
+             "Ignoring received mad - since we are exiting\n");
+
+    osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_DEBUG );
+
+    /* retire the mad or put it back */
+    if( ib_smp_is_response( p_smp ) ||
+        (p_smp->method == IB_MAD_METHOD_TRAP_REPRESS))
+    {
+      CL_ASSERT( p_madw->resp_expected == FALSE );
+      __osm_sm_mad_ctrl_retire_trans_mad( p_ctrl, p_madw );
+    }
+    else
+    {
+      if( p_madw->resp_expected == TRUE )
+        __osm_sm_mad_ctrl_retire_trans_mad( p_ctrl, p_madw );
+      else
+        osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+    }
+
+    goto Exit;
+  }
+
+  if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_FRAMES ) )
+    osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_FRAMES );
+
+  if( p_smp->mgmt_class == IB_MCLASS_SUBN_DIR )
+  {
+    status = ib_smp_get_status( p_smp );
+  }
+  else
+  {
+    status = p_smp->status;
+  }
+
+  if( status != 0 )
+  {
+    osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+             "__osm_sm_mad_ctrl_rcv_callback: ERR 3111: "
+             "Error status = 0x%X\n", status );
+    osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_ERROR );
+  }
+
+  switch( p_smp->method )
+  {
+  case IB_MAD_METHOD_GET_RESP:
+    CL_ASSERT( p_req_madw != NULL );
+    __osm_sm_mad_ctrl_process_get_resp( p_ctrl, p_madw, p_req_madw );
+    break;
+
+  case IB_MAD_METHOD_GET:
+    CL_ASSERT( p_req_madw == NULL );
+    __osm_sm_mad_ctrl_process_get( p_ctrl, p_madw );
+    break;
+
+  case IB_MAD_METHOD_TRAP:
+    CL_ASSERT( p_req_madw == NULL );
+    __osm_sm_mad_ctrl_process_trap( p_ctrl, p_madw );
+    break;
+
+  case IB_MAD_METHOD_SET:
+    CL_ASSERT( p_req_madw == NULL );
+    __osm_sm_mad_ctrl_process_set( p_ctrl, p_madw );
+    break;
+
+  case IB_MAD_METHOD_SEND:
+  case IB_MAD_METHOD_REPORT:
+  case IB_MAD_METHOD_REPORT_RESP:
+  case IB_MAD_METHOD_TRAP_REPRESS:
+  default:
+    osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+             "__osm_sm_mad_ctrl_rcv_callback: ERR 3112: "
+             "Unsupported method = 0x%X\n", p_smp->method );
+    osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_ERROR );
+    osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_ctrl->p_log );
+}
+/*
+ * PARAMETERS
+ *
+ * RETURN VALUES
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* opensm: SM/__osm_sm_mad_ctrl_send_err_cb
+ * NAME
+ * __osm_sm_mad_ctrl_send_err_cb
+ *
+ * DESCRIPTION
+ * This is the callback from the transport layer for send errors
+ * on MADs that were expecting a response.
+ *
+ * SYNOPSIS
+ */
+void
+__osm_sm_mad_ctrl_send_err_cb(
+  IN void *bind_context,
+  IN osm_madw_t *p_madw )
+{
+  osm_sm_mad_ctrl_t* p_ctrl = (osm_sm_mad_ctrl_t*)bind_context;
+#if 0
+  osm_physp_t* p_physp;
+#endif
+  ib_api_status_t status;
+  ib_smp_t* p_smp;
+
+  OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_send_err_cb );
+
+  CL_ASSERT( p_madw ); 
+
+  osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+           "__osm_sm_mad_ctrl_send_err_cb: ERR 3113: "
+           "MAD completed in error (%s)\n",
+           ib_get_err_str( p_madw->status ) );
+
+  /* 
+     If this was a SubnSet MAD, then this error might indicate a problem
+     in configuring the subnet. In this case - need to mark that there was
+     such a problem. The subnet will not be up, and the next sweep should
+     be a heavy sweep as well.
+  */
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+  if (p_smp->method == IB_MAD_METHOD_SET && 
+      ( p_smp->attr_id == IB_MAD_ATTR_PORT_INFO || 
+        p_smp->attr_id == IB_MAD_ATTR_MCAST_FWD_TBL ||
+        p_smp->attr_id == IB_MAD_ATTR_SWITCH_INFO ||
+        p_smp->attr_id == IB_MAD_ATTR_LIN_FWD_TBL ) )
+  {
+    osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+             "__osm_sm_mad_ctrl_send_err_cb: ERR 3119: "
+             "Set method failed\n" );
+    p_ctrl->p_subn->subnet_initialization_error = TRUE;
+  }
+
+  /*
+     Since we did not get any response we suspect the DR path 
+     used for the target port. 
+     Find it and replace it with an alternate path.
+     This is true only if the destination lid is not 0xFFFF, since
+     then we are aiming for a specific path and not specific destination
+     lid.
+  */
+  /* For now - do not add the alternate dr path to the release */
+#if 0
+  if ( p_madw->mad_addr.dest_lid != 0xFFFF )
+  {
+    p_physp =
+      osm_get_physp_by_mad_addr(p_ctrl->p_log,
+                                p_ctrl->p_subn,
+                                &(p_madw->mad_addr));
+    if (!p_physp)
+    {
+      osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+               "__osm_sm_mad_ctrl_send_err_cb: ERR 3114: "
+               "Failed to find the corresponding phys port\n");
+    }
+    else
+    {
+      osm_physp_replace_dr_path_with_alternate_dr_path(
+      p_ctrl->p_log, p_ctrl->p_subn, p_physp, p_madw->h_bind );
+    }
+  }
+#endif
+
+  /*
+    An error occurred.  No response was received to a request MAD.
+    Retire the original request MAD.
+  */
+
+  osm_dump_dr_smp( p_ctrl->p_log, osm_madw_get_smp_ptr( p_madw ),
+                   OSM_LOG_ERROR );
+
+  __osm_sm_mad_ctrl_update_wire_stats( p_ctrl );
+
+  if( osm_madw_get_err_msg( p_madw ) != CL_DISP_MSGID_NONE )
+  {
+    if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+               "__osm_sm_mad_ctrl_send_err_cb: "
+               "Posting Dispatcher message %s\n",
+               osm_get_disp_msg_str( osm_madw_get_err_msg( p_madw ) ) );
+    }
+
+    status = cl_disp_post( p_ctrl->h_disp,
+                           osm_madw_get_err_msg( p_madw ),
+                           p_madw,
+                           __osm_sm_mad_ctrl_disp_done_callback,
+                           p_ctrl );
+    if( status != CL_SUCCESS )
+    {
+      osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+               "__osm_sm_mad_ctrl_send_err_cb: ERR 3115: "
+               "Dispatcher post message failed (%s)\n",
+               CL_STATUS_MSG( status ) );
+    }
+  }
+  else
+  {
+    /*
+      No error message was provided, just retire the MAD.
+    */
+    __osm_sm_mad_ctrl_retire_trans_mad( p_ctrl, p_madw );
+  }
+
+  OSM_LOG_EXIT( p_ctrl->p_log );
+}
+/*
+ * PARAMETERS
+ *
+ * RETURN VALUES
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_mad_ctrl_construct(
+  IN osm_sm_mad_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_mad_ctrl_destroy(
+  IN osm_sm_mad_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  
+  if (p_ctrl->h_bind != CL_DISP_INVALID_HANDLE)
+  {
+    osm_vendor_unbind( p_ctrl->h_bind );
+  }
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_mad_ctrl_init(
+  IN osm_sm_mad_ctrl_t* const p_ctrl,
+  IN osm_subn_t* const p_subn,
+  IN osm_mad_pool_t* const p_mad_pool,
+  IN osm_vl15_t* const p_vl15,
+  IN osm_vendor_t* const p_vendor,
+  IN osm_log_t* const p_log,
+  IN osm_stats_t* const p_stats,
+  IN cl_plock_t* const p_lock,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_sm_mad_ctrl_init );
+
+  osm_sm_mad_ctrl_construct( p_ctrl );
+
+  p_ctrl->p_subn = p_subn;
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_disp = p_disp;
+  p_ctrl->p_mad_pool = p_mad_pool;
+  p_ctrl->p_vendor = p_vendor;
+  p_ctrl->p_stats = p_stats;
+  p_ctrl->p_lock = p_lock;
+  p_ctrl->p_vl15 = p_vl15;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    CL_DISP_MSGID_NONE,
+    NULL,
+    NULL );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_sm_mad_ctrl_init: ERR 3116: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_mad_ctrl_bind(
+  IN osm_sm_mad_ctrl_t* const p_ctrl,
+  IN const ib_net64_t port_guid )
+{
+  osm_bind_info_t bind_info;
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_ctrl->p_log, osm_sm_mad_ctrl_bind );
+
+  if( p_ctrl->h_bind != OSM_BIND_INVALID_HANDLE )
+  {
+    osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+             "osm_sm_mad_ctrl_bind: ERR 3117: "
+             "Multiple binds not allowed\n" );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  bind_info.class_version = 1;
+  bind_info.is_report_processor = FALSE;
+  bind_info.is_responder = TRUE;
+  bind_info.is_trap_processor = TRUE;
+  bind_info.mad_class = IB_MCLASS_SUBN_DIR;
+  bind_info.port_guid = port_guid;
+  bind_info.recv_q_size = OSM_SM_DEFAULT_QP0_RCV_SIZE;
+  bind_info.send_q_size = OSM_SM_DEFAULT_QP0_SEND_SIZE;
+
+  osm_log( p_ctrl->p_log, OSM_LOG_VERBOSE,
+           "osm_sm_mad_ctrl_bind: "
+           "Binding to port 0x%" PRIx64 "\n",
+           cl_ntoh64( port_guid ) );
+
+  p_ctrl->h_bind = osm_vendor_bind( p_ctrl->p_vendor,
+                                    &bind_info,
+                                    p_ctrl->p_mad_pool,
+                                    __osm_sm_mad_ctrl_rcv_callback,
+                                    __osm_sm_mad_ctrl_send_err_cb,
+                                    p_ctrl );
+
+  if( p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE )
+  {
+    status = IB_ERROR;
+    osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+             "osm_sm_mad_ctrl_bind: ERR 3118: "
+             "Vendor specific bind failed\n" );
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_ctrl->p_log );
+  return( status );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sm_state_mgr.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sm_state_mgr.c
new file mode 100644 (file)
index 0000000..9a0b87f
--- /dev/null
@@ -0,0 +1,872 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sm_state_mgr.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_state_mgr_t.
+ * This file implements the SM State Manager object.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <time.h>
+#include <opensm/osm_state_mgr.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_port.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_sm_state_mgr.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sm_state_mgr_standby_msg(
+   IN const osm_sm_state_mgr_t * p_sm_mgr )
+{
+   osm_log( p_sm_mgr->p_log, OSM_LOG_SYS, "Entering STANDBY state\n" );   /* Format Waived */
+
+   if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_VERBOSE ) )
+   {
+      osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE,
+               "__osm_sm_state_mgr_standby_msg: "
+               "\n\n\n********************************"
+               "**********************************\n"
+               "******************** ENTERING SM STANDBY"
+               " STATE *******************\n"
+               "**************************************"
+               "****************************\n\n\n" );
+   }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sm_state_mgr_master_msg(
+   IN const osm_sm_state_mgr_t * p_sm_mgr )
+{
+   osm_log( p_sm_mgr->p_log, OSM_LOG_SYS, "Entering MASTER state\n" );   /* Format Waived */
+
+   if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_VERBOSE ) )
+   {
+      osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE,
+               "__osm_sm_state_mgr_master_msg: "
+               "\n\n\n********************************"
+               "**********************************\n"
+               "******************** ENTERING SM MASTER"
+               " STATE ********************\n"
+               "**************************************"
+               "****************************\n\n\n" );
+   }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sm_state_mgr_discovering_msg(
+   IN const osm_sm_state_mgr_t * p_sm_mgr )
+{
+   if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_VERBOSE ) )
+   {
+      osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE,
+               "__osm_sm_state_mgr_discovering_msg: "
+               "\n\n\n********************************"
+               "**********************************\n"
+               "******************** ENTERING SM DISCOVERING"
+               " STATE ***************\n"
+               "**************************************"
+               "****************************\n\n\n" );
+   }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sm_state_mgr_notactive_msg(
+   IN const osm_sm_state_mgr_t * p_sm_mgr )
+{
+   if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_VERBOSE ) )
+   {
+      osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE,
+               "__osm_sm_state_mgr_notactive_msg: "
+               "\n\n\n********************************"
+               "**********************************\n"
+               "******************** ENTERING SM NOT-ACTIVE"
+               " STATE **********************\n"
+               "**************************************"
+               "****************************\n\n\n" );
+   }
+}
+
+#if 0
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sm_state_mgr_send_local_port_info_req(
+   IN osm_sm_state_mgr_t * p_sm_mgr )
+{
+   osm_madw_context_t context;
+   osm_port_t *p_port;
+   ib_net64_t port_guid = p_sm_mgr->p_subn->sm_port_guid;
+   ib_api_status_t status;
+
+   OSM_LOG_ENTER( p_sm_mgr->p_log,
+                  __osm_sm_state_mgr_send_local_port_info_req );
+   /*
+    * Send a query of SubnGet(PortInfo) to our own port, in order to
+    * update the master_sm_base_lid of the subnet.
+    */
+   memset( &context, 0, sizeof( context ) );
+   p_port = ( osm_port_t * ) cl_qmap_get( &p_sm_mgr->p_subn->port_guid_tbl,
+                                          port_guid );
+   if( p_port ==
+       ( osm_port_t * ) cl_qmap_end( &p_sm_mgr->p_subn->port_guid_tbl ) )
+   {
+      osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_sm_state_mgr_send_local_port_info_req: ERR 3205: "
+               "No port object for port 0x%016" PRIx64 "\n",
+               cl_ntoh64( port_guid ) );
+      goto Exit;
+   }
+
+   context.pi_context.port_guid = port_guid;
+   context.pi_context.node_guid = p_port->p_node->node_info.node_guid;
+   context.pi_context.set_method = FALSE;
+   context.pi_context.ignore_errors = FALSE;
+   /* mark the update_master_sm_base_lid with TRUE - we want to update it */
+   /* with the new master lid value. */
+   context.pi_context.update_master_sm_base_lid = TRUE;
+   context.pi_context.light_sweep = FALSE;
+   context.pi_context.active_transition = FALSE;
+
+   status = osm_req_get( p_sm_mgr->p_req,
+                         osm_physp_get_dr_path_ptr
+                         ( osm_port_get_default_phys_ptr( p_port ) ),
+                         IB_MAD_ATTR_PORT_INFO,
+                         cl_hton32( p_port->default_port_num ),
+                         CL_DISP_MSGID_NONE, &context );
+
+   if( status != IB_SUCCESS )
+   {
+      osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_sm_state_mgr_send_local_port_info_req: ERR 3202: "
+               "Failure requesting PortInfo (%s)\n",
+               ib_get_err_str( status ) );
+   }
+
+ Exit:
+   OSM_LOG_EXIT( p_sm_mgr->p_log );
+}
+#endif
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sm_state_mgr_send_master_sm_info_req(
+   IN osm_sm_state_mgr_t * p_sm_mgr )
+{
+   osm_madw_context_t context;
+   const osm_port_t *p_port;
+   ib_api_status_t status;
+
+   OSM_LOG_ENTER( p_sm_mgr->p_log,
+                  __osm_sm_state_mgr_send_master_sm_info_req );
+
+   memset( &context, 0, sizeof( context ) );
+   if( p_sm_mgr->p_subn->sm_state == IB_SMINFO_STATE_STANDBY )
+   {
+      /*
+       * We are in STANDBY state - this means we need to poll on the master
+       * SM (according to master_guid)
+       * Send a query of SubnGet(SMInfo) to the subn master_sm_base_lid object.
+       */
+      p_port = ( osm_port_t * ) cl_qmap_get( &p_sm_mgr->p_subn->port_guid_tbl,
+                                             p_sm_mgr->master_guid );
+   }
+   else
+   {
+      /*
+       * We are not in STANDBY - this means we are in MASTER state - so we need
+       * to poll on the SM that is saved in p_polling_sm under p_sm_mgr.
+       * Send a query of SubnGet(SMInfo) to that SM.
+       */
+      p_port = p_sm_mgr->p_polling_sm->p_port;
+   }
+   if( p_port == NULL )
+   {
+      osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_sm_state_mgr_send_master_sm_info_req: ERR 3203: "
+               "No port object for GUID 0x%016" PRIx64 "\n",
+               cl_ntoh64(p_sm_mgr->master_guid) );
+      goto Exit;
+   }
+
+   context.smi_context.port_guid = p_port->guid;
+   context.smi_context.set_method = FALSE;
+
+   status = osm_req_get( p_sm_mgr->p_req,
+                         osm_physp_get_dr_path_ptr
+                         ( osm_port_get_default_phys_ptr( p_port ) ),
+                         IB_MAD_ATTR_SM_INFO, 0, CL_DISP_MSGID_NONE,
+                         &context );
+
+   if( status != IB_SUCCESS )
+   {
+      osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_sm_state_mgr_send_master_sm_info_req: ERR 3204: "
+               "Failure rquesting SMInfo (%s)\n", ib_get_err_str( status ) );
+   }
+
+ Exit:
+   OSM_LOG_EXIT( p_sm_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sm_state_mgr_start_polling(
+   IN osm_sm_state_mgr_t * p_sm_mgr )
+{
+   uint32_t sminfo_polling_timeout =
+      p_sm_mgr->p_subn->opt.sminfo_polling_timeout;
+   cl_status_t cl_status;
+
+   OSM_LOG_ENTER( p_sm_mgr->p_log, __osm_sm_state_mgr_start_polling );
+
+   /*
+    * Init the retry_nubmer back to zero - need to restart counting
+    */
+   p_sm_mgr->retry_number = 0;
+
+   /*
+    * Send a SubnGet(SMInfo) query to the current (or new) master found.
+    */
+   __osm_sm_state_mgr_send_master_sm_info_req( p_sm_mgr );
+
+   /*
+    * Start a timer that will wake up every sminfo_polling_timeout milliseconds.
+    * The callback of the timer will send a SubnGet(SMInfo) to the Master SM
+    * and restart the timer
+    */
+   cl_status = cl_timer_start( &p_sm_mgr->polling_timer,
+                               sminfo_polling_timeout );
+   if( cl_status != CL_SUCCESS )
+   {
+      osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_sm_state_mgr_start_polling : ERR 3210: "
+               "Failed to start timer\n" );
+   }
+
+   OSM_LOG_EXIT( p_sm_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sm_state_mgr_polling_callback(
+   IN void *context )
+{
+   osm_sm_state_mgr_t *p_sm_mgr = ( osm_sm_state_mgr_t * ) context;
+   uint32_t sminfo_polling_timeout =
+      p_sm_mgr->p_subn->opt.sminfo_polling_timeout;
+   cl_status_t cl_status;
+
+   OSM_LOG_ENTER( p_sm_mgr->p_log, __osm_sm_state_mgr_polling_callback );
+
+   /*
+    * We can be here in one of two cases:
+    * 1. We are a STANDBY sm polling on the master SM.
+    * 2. We are a MASTER sm, waiting for a handover from a remote master sm.
+    * If we are not in one of these cases - don't need to restart the poller.
+    */
+   if( !( ( p_sm_mgr->p_subn->sm_state == IB_SMINFO_STATE_MASTER &&
+            p_sm_mgr->p_polling_sm != NULL ) ||
+          ( p_sm_mgr->p_subn->sm_state == IB_SMINFO_STATE_STANDBY ) ) )
+   {
+      goto Exit;
+   }
+
+   /*
+    * If we are a STANDBY sm and the osm_exit_flag is 1, then let's signal
+    * the subnet_up. This is relevant for the case of running only once. In that
+    * case - the program is stuck until this signal is received. In other
+    * cases - it is not relevant whether or not the signal is on - since we are
+    * currently in exit flow
+    */
+   if( p_sm_mgr->p_subn->sm_state == IB_SMINFO_STATE_STANDBY &&
+       osm_exit_flag == 1 )
+   {
+      osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE,
+               "__osm_sm_state_mgr_polling_callback : "
+               "Signalling subnet_up_event\n" );
+      cl_event_signal( p_sm_mgr->p_state_mgr->p_subnet_up_event );
+      goto Exit;
+   }
+
+   /*
+    * Incr the retry number.
+    * If it reached the max_retry_number in the subnet opt - call
+    * osm_sm_state_mgr_process with signal OSM_SM_SIGNAL_POLLING_TIMEOUT
+    */
+   p_sm_mgr->retry_number++;
+   osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE,
+            "__osm_sm_state_mgr_polling_callback : "
+            "Retry number:%d\n", p_sm_mgr->retry_number );
+
+   if( p_sm_mgr->retry_number >= p_sm_mgr->p_subn->opt.polling_retry_number )
+   {
+      osm_log( p_sm_mgr->p_log, OSM_LOG_DEBUG,
+               "__osm_sm_state_mgr_polling_callback : "
+               "Reached polling_retry_number value in retry_number. "
+               "Go to DISCOVERY state\n" );
+      osm_sm_state_mgr_process( p_sm_mgr, OSM_SM_SIGNAL_POLLING_TIMEOUT );
+      goto Exit;
+   }
+
+   /* Send a SubnGet(SMInfo) request to the remote sm (depends on our state) */
+   __osm_sm_state_mgr_send_master_sm_info_req( p_sm_mgr );
+
+   /* restart the timer */
+   cl_status = cl_timer_start( &p_sm_mgr->polling_timer,
+                               sminfo_polling_timeout );
+   if( cl_status != CL_SUCCESS )
+   {
+      osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_sm_state_mgr_polling_callback : ERR 3211: "
+               "Failed to restart timer\n" );
+   }
+
+ Exit:
+   OSM_LOG_EXIT( p_sm_mgr->p_log );
+   return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_state_mgr_construct(
+   IN osm_sm_state_mgr_t * const p_sm_mgr )
+{
+   memset( p_sm_mgr, 0, sizeof( *p_sm_mgr ) );
+   cl_spinlock_construct( &p_sm_mgr->state_lock );
+   cl_timer_construct( &p_sm_mgr->polling_timer );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_state_mgr_destroy(
+   IN osm_sm_state_mgr_t * const p_sm_mgr )
+{
+   CL_ASSERT( p_sm_mgr );
+
+   OSM_LOG_ENTER( p_sm_mgr->p_log, osm_sm_state_mgr_destroy );
+
+   cl_spinlock_destroy( &p_sm_mgr->state_lock );
+   cl_timer_destroy( &p_sm_mgr->polling_timer );
+
+   OSM_LOG_EXIT( p_sm_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_state_mgr_init(
+   IN osm_sm_state_mgr_t * const p_sm_mgr,
+   IN osm_state_mgr_t * const p_state_mgr,
+   IN osm_subn_t * const p_subn,
+   IN osm_req_t * const p_req,
+   IN osm_log_t * const p_log )
+{
+   cl_status_t status;
+
+   OSM_LOG_ENTER( p_log, osm_sm_state_mgr_init );
+
+   CL_ASSERT( p_subn );
+   CL_ASSERT( p_state_mgr );
+   CL_ASSERT( p_req );
+
+   osm_sm_state_mgr_construct( p_sm_mgr );
+
+   p_sm_mgr->p_log = p_log;
+   p_sm_mgr->p_req = p_req;
+   p_sm_mgr->p_subn = p_subn;
+   p_sm_mgr->p_state_mgr = p_state_mgr;
+
+   /* init the state of the SM to idle */
+   p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_INIT;
+
+   status = cl_spinlock_init( &p_sm_mgr->state_lock );
+   if( status != CL_SUCCESS )
+   {
+      osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+               "osm_sm_state_mgr_init: ERR 3201: "
+               "Spinlock init failed (%s)\n", CL_STATUS_MSG( status ) );
+   }
+
+   status = cl_timer_init( &p_sm_mgr->polling_timer,
+                           __osm_sm_state_mgr_polling_callback, p_sm_mgr );
+
+   if( status != CL_SUCCESS )
+   {
+      osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+               "osm_sm_state_mgr_init: ERR 3206: "
+               "Timer init failed (%s)\n", CL_STATUS_MSG( status ) );
+   }
+
+   OSM_LOG_EXIT( p_sm_mgr->p_log );
+   return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sm_state_mgr_signal_error(
+   IN const osm_sm_state_mgr_t * const p_sm_mgr,
+   IN const osm_sm_signal_t signal )
+{
+   osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+            "__osm_sm_state_mgr_signal_error: ERR 3207: "
+            "Invalid signal %s in state %s\n",
+            osm_get_sm_mgr_signal_str( signal ),
+            osm_get_sm_mgr_state_str( p_sm_mgr->p_subn->sm_state ) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_state_mgr_signal_master_is_alive(
+   IN osm_sm_state_mgr_t * const p_sm_mgr )
+{
+   OSM_LOG_ENTER( p_sm_mgr->p_log, osm_sm_state_mgr_signal_master_is_alive );
+   p_sm_mgr->retry_number = 0;
+   OSM_LOG_EXIT( p_sm_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_state_mgr_process(
+   IN osm_sm_state_mgr_t * const p_sm_mgr,
+   IN osm_sm_signal_t signal )
+{
+   ib_api_status_t status = IB_SUCCESS;
+
+   CL_ASSERT( p_sm_mgr );
+
+   OSM_LOG_ENTER( p_sm_mgr->p_log, osm_sm_state_mgr_process );
+
+   /*
+    * The state lock prevents many race conditions from screwing
+    * up the state transition process.
+    */
+   cl_spinlock_acquire( &p_sm_mgr->state_lock );
+
+   if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_DEBUG ) )
+   {
+      osm_log( p_sm_mgr->p_log, OSM_LOG_DEBUG,
+               "osm_sm_state_mgr_process: "
+               "Received signal %s in state %s\n",
+               osm_get_sm_mgr_signal_str( signal ),
+               osm_get_sm_mgr_state_str( p_sm_mgr->p_subn->sm_state ) );
+   }
+
+   switch ( p_sm_mgr->p_subn->sm_state )
+   {
+   case IB_SMINFO_STATE_INIT:
+      switch ( signal )
+      {
+      case OSM_SM_SIGNAL_INIT:
+         /*
+          * Update the state of the SM to DISCOVERING
+          */
+         __osm_sm_state_mgr_discovering_msg( p_sm_mgr );
+         p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_DISCOVERING;
+         break;
+
+      default:
+         __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+         status = IB_INVALID_PARAMETER;
+         break;
+      }
+      break;
+
+   case IB_SMINFO_STATE_DISCOVERING:
+      switch ( signal )
+      {
+      case OSM_SM_SIGNAL_DISCOVERY_COMPLETED:
+         /*
+          * Update the state of the SM to MASTER
+          */
+         __osm_sm_state_mgr_master_msg( p_sm_mgr );
+         /* Turn on the moved_to_master_state flag */
+         p_sm_mgr->p_subn->moved_to_master_state = TRUE;
+         /* Turn on the first_time_master_sweep flag */
+         if( p_sm_mgr->p_subn->first_time_master_sweep == FALSE )
+            p_sm_mgr->p_subn->first_time_master_sweep = TRUE;
+
+         p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_MASTER;
+         /*
+          * Make sure to set the subnet master_sm_base_lid
+          * to the sm_base_lid value
+          */
+         p_sm_mgr->p_subn->master_sm_base_lid = p_sm_mgr->p_subn->sm_base_lid;
+         break;
+      case OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED:
+         /*
+          * Stop the discovering
+          */
+         osm_state_mgr_process( p_sm_mgr->p_state_mgr,
+                                OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED );
+         break;
+      case OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED_DONE:
+         /*
+          * Finished all discovery actions - move to STANDBY
+          * start the polling
+          */
+         __osm_sm_state_mgr_standby_msg( p_sm_mgr );
+         p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_STANDBY;
+         /*
+          * Since another SM is doing the LFT config - we should not
+          * ignore the results of it
+          */
+         p_sm_mgr->p_subn->ignore_existing_lfts = FALSE;
+
+         __osm_sm_state_mgr_start_polling( p_sm_mgr );
+         break;
+      case OSM_SM_SIGNAL_HANDOVER:
+        /*
+         * Do nothing. We will discover it later on. If we already discovered
+         * this SM, and got the HANDOVER - this means the remote SM is of 
+         * lower priority. In this case we will stop polling it (since it is
+         * a lower priority SM in STANDBY state).
+         */
+         break;
+      default:
+         __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+         status = IB_INVALID_PARAMETER;
+         break;
+      }
+      break;
+
+   case IB_SMINFO_STATE_STANDBY:
+      switch ( signal )
+      {
+      case OSM_SM_SIGNAL_POLLING_TIMEOUT:
+      case OSM_SM_SIGNAL_DISCOVER:
+         /*
+          * case 1: Polling timeout occured - this means that the Master SM
+          * no longer alive.
+          * case 2: Got a signal to move to DISCOVERING
+          * Move to DISCOVERING state, and start sweeping
+          */
+         __osm_sm_state_mgr_discovering_msg( p_sm_mgr );
+         p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_DISCOVERING;
+         p_sm_mgr->p_subn->coming_out_of_standby = TRUE;
+         osm_state_mgr_process( p_sm_mgr->p_state_mgr, OSM_SIGNAL_EXIT_STBY );
+         break;
+      case OSM_SM_SIGNAL_DISABLE:
+         /*
+          * Update the state to NOT_ACTIVE
+          */
+         __osm_sm_state_mgr_notactive_msg( p_sm_mgr );
+         p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_NOTACTIVE;
+         break;
+      case OSM_SM_SIGNAL_HANDOVER:
+         /*
+          * Update state to MASTER, and start sweeping
+          * OPTIONAL: send ACKNOWLEDGE
+          */
+         __osm_sm_state_mgr_master_msg( p_sm_mgr );
+         /* Turn on the moved_to_master_state flag */
+         p_sm_mgr->p_subn->moved_to_master_state = TRUE;
+         /* Turn on the first_time_master_sweep flag */
+         if( p_sm_mgr->p_subn->first_time_master_sweep == FALSE )
+            p_sm_mgr->p_subn->first_time_master_sweep = TRUE;
+         /* Turn on the force_immediate_heavy_sweep - we want a
+          * heavy sweep to occur on the first sweep of this SM. */
+         p_sm_mgr->p_subn->force_immediate_heavy_sweep = TRUE;
+
+         p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_MASTER;
+         /*
+          * Make sure to set the subnet master_sm_base_lid
+          * to the sm_base_lid value
+          */
+         p_sm_mgr->p_subn->master_sm_base_lid = p_sm_mgr->p_subn->sm_base_lid;
+         p_sm_mgr->p_subn->coming_out_of_standby = TRUE;
+         osm_state_mgr_process( p_sm_mgr->p_state_mgr, OSM_SIGNAL_EXIT_STBY );
+         break;
+      case OSM_SM_SIGNAL_ACKNOWLEDGE:
+         /*
+          * Do nothing - already moved to STANDBY
+          */
+         break;
+      default:
+         __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+         status = IB_INVALID_PARAMETER;
+         break;
+      }
+      break;
+
+   case IB_SMINFO_STATE_NOTACTIVE:
+      switch ( signal )
+      {
+      case OSM_SM_SIGNAL_STANDBY:
+         /*
+          * Update the state to STANDBY
+          * start the polling
+          */
+         __osm_sm_state_mgr_standby_msg( p_sm_mgr );
+         p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_STANDBY;
+         __osm_sm_state_mgr_start_polling( p_sm_mgr );
+         break;
+      default:
+         __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+         status = IB_INVALID_PARAMETER;
+         break;
+      }
+      break;
+
+   case IB_SMINFO_STATE_MASTER:
+      switch ( signal )
+      {
+      case OSM_SM_SIGNAL_POLLING_TIMEOUT:
+         /*
+          * we received a polling timeout - this means that we waited for
+          * a remote master sm to send us a handover, but didn't get it, and
+          * didn't get a response from that remote sm.
+          * We want to force a heavy sweep - hopefully this occurred because
+          * the remote sm died, and we'll find this out and configure the
+          * subnet after a heavy sweep.
+          * We also want to clear the p_polling_sm object - since we are
+          * done polling on that remote sm - we are sweeping again.
+          */
+      case OSM_SM_SIGNAL_HANDOVER:
+         /*
+          * If we received a handover in a master state - then we want to
+          * force a heavy sweep. This means that either we are in a sweep
+          * currently - in this case - no change, or we are in idle state -
+          * since we recognized a master SM before - so we want to make a
+          * heavy sweep and reconfigure the new subnet.
+          * We also want to clear the p_polling_sm object - since we are
+          * done polling on that remote sm - we got a handover from it.
+          */
+         osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE,
+                  "osm_sm_state_mgr_process: "
+                  "Forcing immediate heavy sweep. "
+                  "Received OSM_SM_SIGNAL_HANDOVER or OSM_SM_SIGNAL_POLLING_TIMEOUT\n" );
+         p_sm_mgr->p_polling_sm = NULL;
+         p_sm_mgr->p_subn->force_immediate_heavy_sweep = TRUE;
+         osm_state_mgr_process( p_sm_mgr->p_state_mgr, OSM_SIGNAL_SWEEP );
+         break;
+      case OSM_SM_SIGNAL_HANDOVER_SENT:
+         /*
+          * Just sent a HANDOVER signal - move to STANDBY
+          * start the polling
+          */
+         __osm_sm_state_mgr_standby_msg( p_sm_mgr );
+         p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_STANDBY;
+         __osm_sm_state_mgr_start_polling( p_sm_mgr );
+         break;
+      case OSM_SM_SIGNAL_WAIT_FOR_HANDOVER:
+         /*
+          * We found a remote master SM, and we are waiting for it
+          * to handover the mastership to us. Need to start polling
+          * on that SM, to make sure it is alive, if it isn't - then
+          * we should move back to discovering, since something must
+          * have happened to it.
+          */
+         __osm_sm_state_mgr_start_polling( p_sm_mgr );
+         break;
+      case OSM_SM_SIGNAL_DISCOVER:
+         __osm_sm_state_mgr_discovering_msg( p_sm_mgr );
+         p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_DISCOVERING;
+         break;
+      default:
+         __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+         status = IB_INVALID_PARAMETER;
+         break;
+      }
+      break;
+
+   default:
+      osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+               "osm_sm_state_mgr_process: ERR 3208: "
+               "Invalid state %s\n",
+               osm_get_sm_mgr_state_str( p_sm_mgr->p_subn->sm_state ) );
+
+   }
+
+   cl_spinlock_release( &p_sm_mgr->state_lock );
+
+   OSM_LOG_EXIT( p_sm_mgr->p_log );
+   return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_state_mgr_check_legality(
+   IN osm_sm_state_mgr_t * const p_sm_mgr,
+   IN osm_sm_signal_t signal )
+{
+   ib_api_status_t status = IB_SUCCESS;
+
+   CL_ASSERT( p_sm_mgr );
+
+   OSM_LOG_ENTER( p_sm_mgr->p_log, osm_sm_state_mgr_check_legality );
+
+   /*
+    * The state lock prevents many race conditions from screwing
+    * up the state transition process.
+    */
+   cl_spinlock_acquire( &p_sm_mgr->state_lock );
+
+   if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_DEBUG ) )
+   {
+      osm_log( p_sm_mgr->p_log, OSM_LOG_DEBUG,
+               "osm_sm_state_mgr_check_legality: "
+               "Received signal %s in state %s\n",
+               osm_get_sm_mgr_signal_str( signal ),
+               osm_get_sm_mgr_state_str( p_sm_mgr->p_subn->sm_state ) );
+   }
+
+   switch ( p_sm_mgr->p_subn->sm_state )
+   {
+   case IB_SMINFO_STATE_INIT:
+      switch ( signal )
+      {
+      case OSM_SM_SIGNAL_INIT:
+         status = IB_SUCCESS;
+         break;
+      default:
+         __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+         status = IB_INVALID_PARAMETER;
+         break;
+      }
+      break;
+
+   case IB_SMINFO_STATE_DISCOVERING:
+      switch ( signal )
+      {
+      case OSM_SM_SIGNAL_DISCOVERY_COMPLETED:
+      case OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED:
+      case OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED_DONE:
+      case OSM_SM_SIGNAL_HANDOVER:
+         status = IB_SUCCESS;
+         break;
+      default:
+         __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+         status = IB_INVALID_PARAMETER;
+         break;
+      }
+      break;
+
+   case IB_SMINFO_STATE_STANDBY:
+      switch ( signal )
+      {
+      case OSM_SM_SIGNAL_POLLING_TIMEOUT:
+      case OSM_SM_SIGNAL_DISCOVER:
+      case OSM_SM_SIGNAL_DISABLE:
+      case OSM_SM_SIGNAL_HANDOVER:
+      case OSM_SM_SIGNAL_ACKNOWLEDGE:
+         status = IB_SUCCESS;
+         break;
+      default:
+         __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+         status = IB_INVALID_PARAMETER;
+         break;
+      }
+      break;
+
+   case IB_SMINFO_STATE_NOTACTIVE:
+      switch ( signal )
+      {
+      case OSM_SM_SIGNAL_STANDBY:
+         status = IB_SUCCESS;
+         break;
+      default:
+         __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+         status = IB_INVALID_PARAMETER;
+         break;
+      }
+      break;
+
+   case IB_SMINFO_STATE_MASTER:
+      switch ( signal )
+      {
+      case OSM_SM_SIGNAL_HANDOVER:
+      case OSM_SM_SIGNAL_HANDOVER_SENT:
+         status = IB_SUCCESS;
+         break;
+      default:
+         __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+         status = IB_INVALID_PARAMETER;
+         break;
+      }
+      break;
+
+   default:
+      osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+               "osm_sm_state_mgr_check_legality: ERR 3209: "
+               "Invalid state %s\n",
+               osm_get_sm_mgr_state_str( p_sm_mgr->p_subn->sm_state ) );
+      status = IB_INVALID_PARAMETER;
+
+   }
+
+   cl_spinlock_release( &p_sm_mgr->state_lock );
+
+   OSM_LOG_EXIT( p_sm_mgr->p_log );
+   return ( status );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sminfo_rcv.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sminfo_rcv.c
new file mode 100644 (file)
index 0000000..646ff1b
--- /dev/null
@@ -0,0 +1,768 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sminfo_rcv.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_sminfo_rcv_t.
+ * This object represents the SMInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_sminfo_rcv.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_sm_state_mgr.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sminfo_rcv_construct(
+  IN osm_sminfo_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sminfo_rcv_destroy(
+  IN osm_sminfo_rcv_t* const p_rcv )
+{
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_sminfo_rcv_destroy );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sminfo_rcv_init(
+  IN osm_sminfo_rcv_t* const p_rcv,
+  IN osm_subn_t* const p_subn,
+  IN osm_stats_t* const p_stats,
+  IN osm_resp_t* const p_resp,
+  IN osm_log_t* const p_log,
+  IN osm_state_mgr_t* const p_state_mgr,
+  IN osm_sm_state_mgr_t* const p_sm_state_mgr,
+  IN cl_plock_t* const p_lock )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_sminfo_rcv_init );
+
+  osm_sminfo_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_stats = p_stats;
+  p_rcv->p_resp = p_resp;
+  p_rcv->p_state_mgr = p_state_mgr;
+  p_rcv->p_sm_state_mgr = p_sm_state_mgr;
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ Return TRUE if the remote sm given (by ib_sm_info_t) is higher,
+ return FALSE otherwise.
+ By higher - we mean: SM with higher priority or with same priority
+ and lower GUID.
+**********************************************************************/
+static inline boolean_t
+__osm_sminfo_rcv_remote_sm_is_higher(
+  IN const osm_sminfo_rcv_t* p_rcv,
+  IN const ib_sm_info_t*     p_remote_sm )
+{
+
+  return( osm_sm_is_greater_than( ib_sminfo_get_priority( p_remote_sm ),
+      p_remote_sm->guid,
+      p_rcv->p_subn->opt.sm_priority,
+      p_rcv->p_subn->sm_port_guid) );
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sminfo_rcv_process_get_request(
+  IN const osm_sminfo_rcv_t*  const p_rcv,
+  IN const osm_madw_t*     const p_madw )
+{
+  uint8_t                  payload[IB_SMP_DATA_SIZE];
+  ib_smp_t*                p_smp;
+  ib_sm_info_t*            p_smi = (ib_sm_info_t*)payload;
+  ib_api_status_t          status;
+  ib_sm_info_t*            p_remote_smi;
+  
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sminfo_rcv_process_get_request );
+
+  CL_ASSERT( p_madw );
+
+  /*
+    No real need to grab the lock for this function.
+  */
+  memset( payload, 0, sizeof( payload ) );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+
+  CL_ASSERT( p_smp->method == IB_MAD_METHOD_GET );
+
+  p_smi->guid = p_rcv->p_subn->sm_port_guid;
+  p_smi->act_count = cl_hton32( p_rcv->p_stats->qp0_mads_sent );
+  p_smi->pri_state = (uint8_t)(p_rcv->p_subn->sm_state |
+                               p_rcv->p_subn->opt.sm_priority << 4);
+  /*
+    p.750 row 11 - Return 0 for the SM key unless we authenticate the 
+    requester as the master SM.
+  */
+  p_remote_smi = ib_smp_get_payload_ptr ( osm_madw_get_smp_ptr (p_madw) );
+  if (ib_sminfo_get_state( p_remote_smi ) == IB_SMINFO_STATE_MASTER )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_sminfo_rcv_process_get_request: "
+             "Responding to master SM with real sm_key\n" );
+    p_smi->sm_key = p_rcv->p_subn->opt.sm_key;
+  }
+  else 
+  {
+    /* The requester is not authenticated as master - set sm_key to zero. */
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_sminfo_rcv_process_get_request: "
+             "Responding to SM not master with zero sm_key\n" );
+    p_smi->sm_key = 0;
+  }
+
+  status = osm_resp_send( p_rcv->p_resp, p_madw, 0, payload );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sminfo_rcv_process_get_request: ERR 2F02: "
+             "Error sending response (%s)\n",
+             ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ * Check if the p_smp received is legal.
+ * Current checks:
+ *   MADHeader:AttributeModifiers of ACKNOWLEDGE that was not sent by a
+ *             Standby SM.
+ *   MADHeader:AttributeModifiers of HANDOVER/DISABLE/STANDBY/DISCOVER
+ *             that was not sent by a Master SM.
+ * FUTURE - TO DO:
+ *   Check that the SM_Key is matching.
+ **********************************************************************/
+static ib_api_status_t
+__osm_sminfo_rcv_check_set_req_legality(
+  IN const ib_smp_t* const p_smp )
+{
+  ib_sm_info_t*   p_smi;
+
+  p_smi = ib_smp_get_payload_ptr( p_smp );
+
+  if (p_smp->attr_mod == IB_SMINFO_ATTR_MOD_ACKNOWLEDGE)
+  {
+    if ( ib_sminfo_get_state( p_smi ) == IB_SMINFO_STATE_STANDBY )
+    {
+      return( IB_SUCCESS );
+    }
+  }
+  else if ( p_smp->attr_mod == IB_SMINFO_ATTR_MOD_HANDOVER ||
+            p_smp->attr_mod == IB_SMINFO_ATTR_MOD_DISABLE ||
+            p_smp->attr_mod == IB_SMINFO_ATTR_MOD_STANDBY ||
+            p_smp->attr_mod == IB_SMINFO_ATTR_MOD_DISCOVER )
+  {
+    if ( ib_sminfo_get_state( p_smi ) == IB_SMINFO_STATE_MASTER )
+    {
+      return( IB_SUCCESS );
+    }
+  }
+
+  return( IB_INVALID_PARAMETER );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sminfo_rcv_process_set_request(
+  IN const osm_sminfo_rcv_t*  const p_rcv,
+  IN const osm_madw_t*        const p_madw )
+{
+  uint8_t                 payload[IB_SMP_DATA_SIZE];
+  ib_smp_t*               p_smp;
+  ib_sm_info_t*           p_smi = (ib_sm_info_t*)payload;
+  ib_sm_info_t*           p_rcv_smi;
+  ib_api_status_t         status;
+  osm_sm_signal_t         sm_signal;
+  ib_sm_info_t*           p_remote_smi;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sminfo_rcv_process_set_request );
+
+  CL_ASSERT( p_madw );
+
+  /*
+    No real need to grab the lock for this function.
+  */
+  memset( payload, 0, sizeof( payload ) );
+
+  /* get the lock */
+  CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+  p_rcv_smi = ib_smp_get_payload_ptr( p_smp );
+
+  if( p_smp->method != IB_MAD_METHOD_SET )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sminfo_rcv_process_set_request: ERR 2F03: "
+             "Unsupported method 0x%X\n",
+             p_smp->method );
+    CL_PLOCK_RELEASE( p_rcv->p_lock );
+    goto Exit;
+  }
+
+  p_smi->guid = p_rcv->p_subn->sm_port_guid;
+  p_smi->act_count = cl_hton32( p_rcv->p_stats->qp0_mads_sent );
+  p_smi->pri_state = (uint8_t)(p_rcv->p_subn->sm_state |
+                               p_rcv->p_subn->opt.sm_priority << 4);
+  /*
+    p.750 row 11 - Return 0 for the SM key unless we authenticate the 
+    requester as the master SM.
+  */
+  p_remote_smi = ib_smp_get_payload_ptr ( osm_madw_get_smp_ptr (p_madw) );
+  if (ib_sminfo_get_state( p_remote_smi ) == IB_SMINFO_STATE_MASTER )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_sminfo_rcv_process_set_request: "
+             "Responding to master SM with real sm_key\n" );
+    p_smi->sm_key = p_rcv->p_subn->opt.sm_key;
+  }
+  else 
+  {
+    /* The requester is not authenticated as master - set sm_key to zero. */
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_sminfo_rcv_process_set_request: "
+             "Responding to SM not master with zero sm_key\n" );
+    p_smi->sm_key = 0;
+  }
+
+  /* Check the legality of the packet */
+  status = __osm_sminfo_rcv_check_set_req_legality( p_smp );
+  if ( status != IB_SUCCESS )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sminfo_rcv_process_set_request: ERR 2F04: "
+             "Check legality failed. AttributeModifier:0x%X RemoteState:%s\n",
+             p_smp->attr_mod,
+             osm_get_sm_mgr_state_str(ib_sminfo_get_state( p_rcv_smi ) ) );
+    /* send a response with error code */
+    status = osm_resp_send( p_rcv->p_resp, p_madw, 7, payload );
+    if( status != IB_SUCCESS )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_sminfo_rcv_process_set_request: ERR 2F05: "
+               "Error sending response (%s)\n",
+               ib_get_err_str( status ) );
+    }
+    CL_PLOCK_RELEASE( p_rcv->p_lock );
+    goto Exit;
+  }
+
+  /* translate from IB_SMINFO_ATTR to OSM_SM_SIGNAL */
+  switch (p_smp->attr_mod)
+  {
+  case IB_SMINFO_ATTR_MOD_HANDOVER:
+    sm_signal = OSM_SM_SIGNAL_HANDOVER;
+    break;
+  case IB_SMINFO_ATTR_MOD_ACKNOWLEDGE:
+    sm_signal = OSM_SM_SIGNAL_ACKNOWLEDGE;
+    break;
+  case IB_SMINFO_ATTR_MOD_DISABLE:
+    sm_signal = OSM_SM_SIGNAL_DISABLE;
+    break;
+  case IB_SMINFO_ATTR_MOD_STANDBY:
+    sm_signal = OSM_SM_SIGNAL_STANDBY;
+    break;
+  case IB_SMINFO_ATTR_MOD_DISCOVER:
+    sm_signal = OSM_SM_SIGNAL_DISCOVER;
+    break;
+  default:
+    /*
+      This code shouldn't be reached - checked in the
+      check legality
+    */
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sminfo_rcv_process_set_request: ERR 2F06: "
+             "THIS CODE SHOULD NOT BE REACHED!!\n");
+    CL_PLOCK_RELEASE( p_rcv->p_lock );
+    goto Exit;
+  }
+
+  /* check legality of the needed transition in the SM state machine */
+  status = osm_sm_state_mgr_check_legality( p_rcv->p_sm_state_mgr,
+                                            sm_signal );
+  if ( status != IB_SUCCESS )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sminfo_rcv_process_set_request: ERR 2F07: "
+             "Check legality of SM needed transition. AttributeModifier:0x%X RemoteState:%s\n",
+             p_smp->attr_mod,
+             osm_get_sm_mgr_state_str(ib_sminfo_get_state( p_rcv_smi ) ) );
+    /* send a response with error code */
+    status = osm_resp_send( p_rcv->p_resp, p_madw, 7, payload );
+    if( status != IB_SUCCESS )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_sminfo_rcv_process_set_request: ERR 2F08: "
+               "Error sending response (%s)\n",
+               ib_get_err_str( status ) );
+    }
+    CL_PLOCK_RELEASE( p_rcv->p_lock );
+    goto Exit;
+  }
+
+  /* the SubnSet(SMInfo) command is ok. Send a response. */
+  status = osm_resp_send( p_rcv->p_resp, p_madw, 0, payload );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sminfo_rcv_process_set_request: ERR 2F09: "
+             "Error sending response (%s)\n",
+             ib_get_err_str( status ) );
+  }
+
+  /* it is a legal packet - act according to it */
+
+  /* if the AttributeModifier is STANDBY - need to save on the */
+  /* p_sm_state_mgr in the master_guid variable - the guid of the */
+  /* current master. */
+  if ( p_smp->attr_mod == IB_SMINFO_ATTR_MOD_STANDBY )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "__osm_sminfo_rcv_process_set_request: "
+             "Received a STANDBY signal. Updating "
+             "sm_state_mgr master_guid: 0x%016" PRIx64 "\n",
+             cl_ntoh64(p_rcv_smi->guid) );
+    p_rcv->p_sm_state_mgr->master_guid = p_rcv_smi->guid;
+  }
+
+  /* call osm_sm_state_mgr_process with the received signal. */
+  CL_PLOCK_RELEASE( p_rcv->p_lock );
+  status = osm_sm_state_mgr_process( p_rcv->p_sm_state_mgr,
+                                     sm_signal );
+
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sminfo_rcv_process_set_request: ERR 2F10: "
+             "Error in SM state transition (%s)\n",
+             ib_get_err_str( status ) );
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ * Return a signal with which to call the osm_state_mgr_process.
+ * This is done since we are locked by p_rcv->p_lock in this function, 
+ * and thus cannot call osm_state_mgr_process (that locks the state_lock).
+ * If return OSM_SIGNAL_NONE - do not call osm_state_mgr_process.
+ **********************************************************************/
+static osm_signal_t
+__osm_sminfo_rcv_process_get_sm(
+  IN const osm_sminfo_rcv_t*  const p_rcv,
+  IN const osm_remote_sm_t*   const p_sm )
+{
+  const ib_sm_info_t*         p_smi;
+  osm_signal_t ret_val = OSM_SIGNAL_NONE;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sminfo_rcv_process_get_sm );
+
+  p_smi = &p_sm->smi;
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "__osm_sminfo_rcv_process_get_sm: "
+             "Detected SM 0x%016" PRIx64 " in state %u\n",
+             cl_ntoh64( p_smi->guid ), ib_sminfo_get_state( p_smi ) );
+  }
+
+  /*
+    Check the state of this SM vs. our own.
+  */
+  switch( p_rcv->p_subn->sm_state )
+  {
+  case IB_SMINFO_STATE_NOTACTIVE:
+    break;
+
+  case IB_SMINFO_STATE_DISCOVERING:
+    switch( ib_sminfo_get_state( p_smi ) )
+    {
+    case IB_SMINFO_STATE_NOTACTIVE:
+      break;
+    case IB_SMINFO_STATE_MASTER:
+      ret_val = OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED;
+      /* save on the p_sm_state_mgr the guid of the current master. */
+      osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+               "__osm_sminfo_rcv_process_get_sm: "
+               "Found master SM. Updating sm_state_mgr master_guid: 0x%016" PRIx64 "\n",
+               cl_ntoh64( p_sm->p_port->guid ) );
+      p_rcv->p_sm_state_mgr->master_guid = p_sm->p_port->guid;
+      break;
+    case IB_SMINFO_STATE_DISCOVERING:
+    case IB_SMINFO_STATE_STANDBY:
+      if ( __osm_sminfo_rcv_remote_sm_is_higher(p_rcv, p_smi) == TRUE )
+      {
+        /* the remote is a higher sm - need to stop sweeping */
+        ret_val = OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED;
+        /* save on the p_sm_state_mgr the guid of the higher SM we found - */
+        /* we will poll it - as long as it lives - we should be in Standby. */
+        osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+                 "__osm_sminfo_rcv_process_get_sm: "
+                 "Found higher SM. Updating sm_state_mgr master_guid:"
+                 " 0x%016" PRIx64 "\n",
+                 cl_ntoh64(p_sm->p_port->guid) );
+        p_rcv->p_sm_state_mgr->master_guid = p_sm->p_port->guid;
+      }
+      break;
+    default:
+      break;
+    }
+    break;
+
+  case IB_SMINFO_STATE_STANDBY:
+    /* if the guid of the SM that sent us this response is equal to the */
+    /* p_sm_mgr->master_guid - then this is a signal that the polling */
+    switch( ib_sminfo_get_state( p_smi ) )
+    {
+    case IB_SMINFO_STATE_MASTER:
+      /* This means the master is alive */
+      /* Signal that to the SM state mgr */
+      osm_sm_state_mgr_signal_master_is_alive( p_rcv->p_sm_state_mgr );
+      break;
+    case IB_SMINFO_STATE_STANDBY:
+      /* This should be the response from the sm we are polling. */
+      /* If it is - then signal master is alive */
+      if (p_rcv->p_sm_state_mgr->master_guid == p_sm->p_port->guid) 
+      {
+        /* Make sure that it is an SM with higher priority than us.
+           If we started polling it when it was master, and it moved
+           to standby - then it might be with a lower priority than
+           us - and then we don't want to continue polling it. */
+        if ( __osm_sminfo_rcv_remote_sm_is_higher(p_rcv, p_smi) == TRUE )
+          osm_sm_state_mgr_signal_master_is_alive( p_rcv->p_sm_state_mgr );
+      }
+      break;
+    default:
+      /* any other state - do nothing */
+      break;
+    }
+    break;
+
+  case IB_SMINFO_STATE_MASTER:
+    switch( ib_sminfo_get_state( p_smi ) )
+    {
+    case IB_SMINFO_STATE_MASTER:
+      /* If this is a response due to our polling, this means that we are
+         waiting for a handover from this SM, and it is still alive - 
+         signal that. */
+      if ( p_rcv->p_sm_state_mgr->p_polling_sm != NULL )
+      {
+        osm_sm_state_mgr_signal_master_is_alive( p_rcv->p_sm_state_mgr );
+      }
+      else
+      {
+        /* This is a response we got while sweeping the subnet. 
+           We will handle a case of handover needed later on, when the sweep
+           is done and all SMs are recongnized. */
+      }
+      break; 
+    default:
+      /* any other state - do nothing */
+      break;
+    }
+    break;
+
+  default:
+    break;
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return ret_val;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sminfo_rcv_process_get_response(
+  IN const osm_sminfo_rcv_t*  const p_rcv,
+  IN const osm_madw_t*     const p_madw )
+{
+  const ib_smp_t*          p_smp;
+  const ib_sm_info_t*      p_smi;
+  cl_qmap_t*               p_sm_tbl;
+  cl_qmap_t*               p_port_tbl;
+  osm_port_t*              p_port;
+  ib_net64_t               port_guid;
+  osm_remote_sm_t*         p_sm;
+  osm_signal_t             process_get_sm_ret_val = OSM_SIGNAL_NONE;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sminfo_rcv_process_get_response );
+
+  CL_ASSERT( p_madw );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+
+  if( p_smp->method != IB_MAD_METHOD_GET_RESP )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sminfo_rcv_process_get_response: ERR 2F11: "
+             "Unsupported method 0x%X\n",
+             p_smp->method );
+    goto Exit;
+  }
+
+  p_smi = ib_smp_get_payload_ptr( p_smp );
+  p_sm_tbl = &p_rcv->p_subn->sm_guid_tbl;
+  p_port_tbl = &p_rcv->p_subn->port_guid_tbl;
+  port_guid = p_smi->guid;
+
+  osm_dump_sm_info( p_rcv->p_log, p_smi, OSM_LOG_DEBUG );
+
+  /* 
+     Check that the sm_key of the found SM is the same as ours,
+     or is zero. If not - OpenSM cannot continue with configuration!. */
+  if ( p_smi->sm_key != 0 && 
+       p_smi->sm_key != p_rcv->p_subn->opt.sm_key )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sminfo_rcv_process_get_response: ERR 2F18: "
+             "Got SM with sm_key that doesn't match our "
+             "local key. Exiting\n" );
+    osm_log( p_rcv->p_log, OSM_LOG_SYS,
+             "Found remote SM with non-matching sm_key. Exiting\n" );
+    osm_exit_flag = TRUE;
+    goto Exit;
+  }
+
+  /*
+    Determine if we already have another SM object for this SM.
+  */
+  CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
+
+  p_port = (osm_port_t*)cl_qmap_get( p_port_tbl, port_guid );
+  if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sminfo_rcv_process_get_response: ERR 2F12: "
+             "No port object for this SM\n" );
+    goto Exit;
+  }
+
+  if( osm_port_get_guid( p_port ) != p_smi->guid )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sminfo_rcv_process_get_response: ERR 2F13: "
+             "Bogus SM port GUID"
+             "\n\t\t\t\tExpected 0x%016" PRIx64
+             ", Received 0x%016" PRIx64 "\n",
+             cl_ntoh64( osm_port_get_guid( p_port ) ),
+             cl_ntoh64( p_smi->guid ) );
+    goto Exit;
+  }
+
+  p_sm = (osm_remote_sm_t*)cl_qmap_get( p_sm_tbl, port_guid );
+  if( p_sm == (osm_remote_sm_t*)cl_qmap_end( p_sm_tbl ) )
+  {
+    p_sm = malloc( sizeof(*p_sm) );
+    if( p_sm == NULL )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_sminfo_rcv_process_get_response: ERR 2F14: "
+               "Unable to allocate SM object\n" );
+      goto Exit;
+    }
+
+    osm_remote_sm_init( p_sm, p_port, p_smi );
+
+    cl_qmap_insert( p_sm_tbl, port_guid, &p_sm->map_item );
+  }
+  else
+  {
+    /*
+      We already know this SM.
+      Update the SMInfo attribute.
+    */
+    p_sm->smi = *p_smi;
+  }
+
+  process_get_sm_ret_val = __osm_sminfo_rcv_process_get_sm( p_rcv, p_sm );
+
+ Exit:
+  CL_PLOCK_RELEASE( p_rcv->p_lock );
+  
+  /* If process_get_sm_ret_val != OSM_SIGNAL_NONE then we have to signal
+   * to the state_mgr with that signal. */
+  if (process_get_sm_ret_val != OSM_SIGNAL_NONE)
+    osm_state_mgr_process( p_rcv->p_state_mgr,
+                           process_get_sm_ret_val );
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sminfo_rcv_process_set_response(
+  IN const osm_sminfo_rcv_t*  const p_rcv,
+  IN const osm_madw_t*     const p_madw )
+{
+  const ib_smp_t*          p_smp;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sminfo_rcv_process_set_response );
+
+  CL_ASSERT( p_madw );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+
+  if( p_smp->method != IB_MAD_METHOD_GET_RESP )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sminfo_rcv_process_set_response: ERR 2F16: "
+             "Unsupported method 0x%X\n",
+             p_smp->method );
+    goto Exit;
+  }
+
+  /* Check the AttributeModifier */
+  if ( p_smp->attr_mod != IB_SMINFO_ATTR_MOD_HANDOVER )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_sminfo_rcv_process_set_response: ERR 2F17: "
+             "Unsupported attribute modifier 0x%X\n",
+             p_smp->attr_mod );
+    goto Exit;
+  }
+
+  /*
+    This is a response on a HANDOVER request -
+    Nothing to do.
+  */
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sminfo_rcv_process(
+  IN const osm_sminfo_rcv_t* const p_rcv,
+  IN osm_madw_t* const p_madw )
+{
+  ib_smp_t *p_smp;
+  osm_smi_context_t *p_smi_context;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_sminfo_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+
+  /*
+    Determine if this is a request for our own SMInfo
+    or if this is a response to our request for another
+    SM's SMInfo.
+  */
+  if( ib_smp_is_response( p_smp ) )
+  {
+    /* Get the context - to see if this is a response to a Get or Set method */
+    p_smi_context = osm_madw_get_smi_context_ptr( p_madw );
+    if ( p_smi_context->set_method == FALSE )
+    {
+      /* this is a response to a Get method */
+      __osm_sminfo_rcv_process_get_response( p_rcv, p_madw );
+    }
+    else
+    {
+      /* this is a response to a Set method */
+      __osm_sminfo_rcv_process_set_response( p_rcv, p_madw );
+    }
+  }
+  else
+  {
+    /* This is a request */
+    if ( p_smp->method == IB_MAD_METHOD_GET )
+    {
+      /* This is a SubnGet request */
+      __osm_sminfo_rcv_process_get_request( p_rcv, p_madw );
+    }
+    else
+    {
+      /* This is a SubnSet request */
+      __osm_sminfo_rcv_process_set_request( p_rcv, p_madw );
+    }
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sminfo_rcv_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sminfo_rcv_ctrl.c
new file mode 100644 (file)
index 0000000..8ad3d11
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sminfo_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_sminfo_rcv_ctrl_t.
+ * This object represents the SMInfo request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sminfo_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sminfo_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_sminfo_rcv_process( ((osm_sminfo_rcv_ctrl_t*)context)->p_rcv,
+                          (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sminfo_rcv_ctrl_construct(
+  IN osm_sminfo_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sminfo_rcv_ctrl_destroy(
+  IN osm_sminfo_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sminfo_rcv_ctrl_init(
+  IN osm_sminfo_rcv_ctrl_t* const p_ctrl,
+  IN osm_sminfo_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_sminfo_rcv_ctrl_init );
+
+  osm_sminfo_rcv_ctrl_construct( p_ctrl );
+
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_SM_INFO,
+    __osm_sminfo_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_sminfo_rcv_ctrl_init: ERR 3001: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_state_mgr.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_state_mgr.c
new file mode 100644 (file)
index 0000000..ef41870
--- /dev/null
@@ -0,0 +1,2986 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_state_mgr.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_state_mgr_t.
+ * This file implements the State Manager object.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.13 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_state_mgr.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_pkey_mgr.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_sm_state_mgr.h>
+#include <opensm/osm_opensm.h>
+
+#define SUBNET_LIST_FILENAME "/osm-subnet.lst"
+
+osm_signal_t osm_qos_setup(IN osm_opensm_t * p_osm);
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_state_mgr_construct(
+   IN osm_state_mgr_t * const p_mgr )
+{
+   memset( p_mgr, 0, sizeof( *p_mgr ) );
+   cl_spinlock_construct( &p_mgr->state_lock );
+   cl_spinlock_construct( &p_mgr->idle_lock );
+   p_mgr->state = OSM_SM_STATE_INIT;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_state_mgr_destroy(
+   IN osm_state_mgr_t * const p_mgr )
+{
+   CL_ASSERT( p_mgr );
+
+   OSM_LOG_ENTER( p_mgr->p_log, osm_state_mgr_destroy );
+
+   /*  destroy the locks */
+   cl_spinlock_destroy( &p_mgr->state_lock );
+   cl_spinlock_destroy( &p_mgr->idle_lock );
+
+   OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_state_mgr_init(
+   IN osm_state_mgr_t * const p_mgr,
+   IN osm_subn_t * const p_subn,
+   IN osm_lid_mgr_t * const p_lid_mgr,
+   IN osm_ucast_mgr_t * const p_ucast_mgr,
+   IN osm_mcast_mgr_t * const p_mcast_mgr,
+   IN osm_link_mgr_t * const p_link_mgr,
+   IN osm_drop_mgr_t * const p_drop_mgr,
+   IN osm_req_t * const p_req,
+   IN osm_stats_t * const p_stats,
+   IN osm_sm_state_mgr_t * const p_sm_state_mgr,
+   IN const osm_sm_mad_ctrl_t * const p_mad_ctrl,
+   IN cl_plock_t * const p_lock,
+   IN cl_event_t * const p_subnet_up_event,
+   IN osm_log_t * const p_log )
+{
+   cl_status_t status;
+
+   OSM_LOG_ENTER( p_log, osm_state_mgr_init );
+
+   CL_ASSERT( p_subn );
+   CL_ASSERT( p_lid_mgr );
+   CL_ASSERT( p_ucast_mgr );
+   CL_ASSERT( p_mcast_mgr );
+   CL_ASSERT( p_link_mgr );
+   CL_ASSERT( p_drop_mgr );
+   CL_ASSERT( p_req );
+   CL_ASSERT( p_stats );
+   CL_ASSERT( p_sm_state_mgr );
+   CL_ASSERT( p_mad_ctrl );
+   CL_ASSERT( p_lock );
+
+   osm_state_mgr_construct( p_mgr );
+
+   p_mgr->p_log = p_log;
+   p_mgr->p_subn = p_subn;
+   p_mgr->p_lid_mgr = p_lid_mgr;
+   p_mgr->p_ucast_mgr = p_ucast_mgr;
+   p_mgr->p_mcast_mgr = p_mcast_mgr;
+   p_mgr->p_link_mgr = p_link_mgr;
+   p_mgr->p_drop_mgr = p_drop_mgr;
+   p_mgr->p_mad_ctrl = p_mad_ctrl;
+   p_mgr->p_req = p_req;
+   p_mgr->p_stats = p_stats;
+   p_mgr->p_sm_state_mgr = p_sm_state_mgr;
+   p_mgr->state = OSM_SM_STATE_IDLE;
+   p_mgr->p_lock = p_lock;
+   p_mgr->p_subnet_up_event = p_subnet_up_event;
+   p_mgr->state_step_mode = OSM_STATE_STEP_CONTINUOUS;
+   p_mgr->next_stage_signal = OSM_SIGNAL_NONE;
+
+   status = cl_spinlock_init( &p_mgr->state_lock );
+   if( status != CL_SUCCESS )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "osm_state_mgr_init: ERR 3301: "
+               "Spinlock init failed (%s)\n", CL_STATUS_MSG( status ) );
+   }
+
+   cl_qlist_init( &p_mgr->idle_time_list );
+
+   status = cl_spinlock_init( &p_mgr->idle_lock );
+   if( status != CL_SUCCESS )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "osm_state_mgr_init: ERR 3302: "
+               "Spinlock init failed (%s)\n", CL_STATUS_MSG( status ) );
+   }
+
+   OSM_LOG_EXIT( p_mgr->p_log );
+   return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_up_msg(
+   IN const osm_state_mgr_t * p_mgr )
+{
+   /* 
+    * This message should be written only once - when the 
+    * SM moves to Master state and the subnet is up for
+    * the first time. The change of state is marked with 
+    * the subnet flag moved_to_master_state
+    */
+   if( p_mgr->p_subn->moved_to_master_state == TRUE )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_SYS, "SUBNET UP\n" ); /* Format Waived */
+      /* clear the signal */
+      p_mgr->p_subn->moved_to_master_state = FALSE;
+   }
+   else
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_INFO, "SUBNET UP\n" ); /* Format Waived */
+   }
+
+   if( p_mgr->p_subn->opt.sweep_interval )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+               "__osm_state_mgr_up_msg: "
+               "\n\n\n********************************"
+               "**********************************\n"
+               "**************************** SUBNET UP "
+               "***************************\n"
+               "**************************************"
+               "****************************\n\n\n" );
+   }
+   else
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+               "__osm_state_mgr_up_msg: "
+               "\n\n\n********************************"
+               "**********************************\n"
+               "******************* SUBNET UP "
+               "(sweep disabled) *******************\n"
+               "**************************************"
+               "****************************\n\n\n" );
+   }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_init_errors_msg(
+   IN const osm_state_mgr_t * p_mgr )
+{
+   osm_log( p_mgr->p_log, OSM_LOG_SYS, "Errors during initialization\n" );   /* Format Waived */
+
+   osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+            "__osm_state_mgr_init_errors_msg: "
+            "\n\n\n********************************"
+            "**********************************\n"
+            "****************** ERRORS DURING INITI"
+            "ALIZATION ******************\n"
+            "**************************************"
+            "****************************\n\n\n" );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_light_sweep_done_msg(
+   IN const osm_state_mgr_t * p_mgr )
+{
+   if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+               "__osm_state_mgr_light_sweep_done_msg: "
+               "\n\n\n********************************"
+               "**********************************\n"
+               "********************** LIGHT SWEEP "
+               "COMPLETE **********************\n"
+               "**************************************"
+               "****************************\n\n\n" );
+   }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_standby_msg(
+   IN const osm_state_mgr_t * p_mgr )
+{
+   if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+               "__osm_state_mgr_standby_msg: "
+               "\n\n\n********************************"
+               "**********************************\n"
+               "******************** ENTERING STANDBY"
+               " STATE **********************\n"
+               "**************************************"
+               "****************************\n\n\n" );
+   }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_sm_port_down_msg(
+   IN const osm_state_mgr_t * p_mgr )
+{
+   osm_log( p_mgr->p_log, OSM_LOG_SYS, "SM port is down\n" );   /* Format Waived */
+
+   if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+               "__osm_state_mgr_sm_port_down_msg: "
+               "\n\n\n********************************"
+               "**********************************\n"
+               "************************** SM PORT DOWN "
+               "**************************\n"
+               "**************************************"
+               "****************************\n\n\n" );
+   }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_lid_assign_msg(
+   IN const osm_state_mgr_t * p_mgr )
+{
+   if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+               "__osm_state_mgr_lid_assign_msg: "
+               "\n\n\n**************************************"
+               "****************************\n"
+               "***** LID ASSIGNMENT COMPLETE - STARTING SWITC"
+               "H TABLE CONFIG *****\n"
+               "*********************************************"
+               "*********************\n\n\n" );
+   }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_set_sm_lid_done_msg(
+   IN const osm_state_mgr_t * p_mgr )
+{
+   if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+               "__osm_state_mgr_set_sm_lid_done_msg: "
+               "\n\n\n**************************************"
+               "****************************\n"
+               "**** SM LID ASSIGNMENT COMPLETE - STARTING SUBN"
+               "ET LID CONFIG *****\n"
+               "*********************************************"
+               "*********************\n\n\n" );
+   }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_switch_config_msg(
+   IN const osm_state_mgr_t * p_mgr )
+{
+   if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+               "__osm_state_mgr_switch_config_msg: "
+               "\n\n\n**************************************"
+               "****************************\n"
+               "***************** SWITCHES CONFIGURED FOR UNICAST "
+               "****************\n"
+               "*********************************************"
+               "*********************\n\n\n" );
+   }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_multicast_config_msg(
+   IN const osm_state_mgr_t * p_mgr )
+{
+   if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+               "__osm_state_mgr_multicast_config_msg: "
+               "\n\n\n**************************************"
+               "****************************\n"
+               "**************** SWITCHES CONFIGURED FOR MULTICAST "
+               "***************\n"
+               "*********************************************"
+               "*********************\n\n\n" );
+   }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_links_ports_msg(
+   IN const osm_state_mgr_t * p_mgr )
+{
+   if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+               "__osm_state_mgr_links_ports_msg: "
+               "\n\n\n**************************************"
+               "****************************\n"
+               "******* LINKS PORTS CONFIGURED - SET LINKS TO ARMED "
+               "STATE ********\n"
+               "*********************************************"
+               "*********************\n\n\n" );
+   }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_links_armed_msg(
+   IN const osm_state_mgr_t * p_mgr )
+{
+   if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+               "__osm_state_mgr_links_armed_msg: "
+               "\n\n\n**************************************"
+               "****************************\n"
+               "************* LINKS ARMED - SET LINKS TO ACTIVE "
+               "STATE ************\n"
+               "*********************************************"
+               "*********************\n\n\n" );
+   }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_sweep_heavy_msg(
+   IN const osm_state_mgr_t * p_mgr )
+{
+   if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+               "__osm_state_mgr_sweep_heavy_msg: "
+               "\n\n\n**************************************"
+               "****************************\n"
+               "******************** INITIATING HEAVY SWEEP "
+               "**********************\n"
+               "*********************************************"
+               "*********************\n\n\n" );
+   }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_sweep_heavy_done_msg(
+   IN const osm_state_mgr_t * p_mgr )
+{
+   if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+               "__osm_state_mgr_sweep_heavy_done_msg: "
+               "\n\n\n**************************************"
+               "****************************\n"
+               "********************* HEAVY SWEEP COMPLETE "
+               "***********************\n"
+               "*********************************************"
+               "*********************\n\n\n" );
+   }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_sweep_light_msg(
+   IN const osm_state_mgr_t * p_mgr )
+{
+   if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+               "__osm_state_mgr_sweep_light_msg: "
+               "\n\n\n**************************************"
+               "****************************\n"
+               "******************** INITIATING LIGHT SWEEP "
+               "**********************\n"
+               "*********************************************"
+               "*********************\n\n\n" );
+   }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_signal_warning(
+   IN const osm_state_mgr_t * const p_mgr,
+   IN const osm_signal_t signal )
+{
+   osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+            "__osm_state_mgr_signal_warning: "
+            "Invalid signal %s(%lu) in state %s\n",
+            osm_get_sm_signal_str( signal ),
+            signal, osm_get_sm_state_str( p_mgr->state ) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_signal_error(
+   IN const osm_state_mgr_t * const p_mgr,
+   IN const osm_signal_t signal )
+{
+   /* the Request for IDLE processing can come async to the state so it
+    * really is just verbose ... */
+   if( signal == OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST )
+      __osm_state_mgr_signal_warning( p_mgr, signal );
+   else
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_state_mgr_signal_error: ERR 3303: "
+               "Invalid signal %s(%lu) in state %s\n",
+               osm_get_sm_signal_str( signal ),
+               signal, osm_get_sm_state_str( p_mgr->state ) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_reset_node_count(
+   IN cl_map_item_t * const p_map_item,
+   IN void *context )
+{
+   osm_node_t *p_node = ( osm_node_t * ) p_map_item;
+   osm_state_mgr_t *const p_mgr = ( osm_state_mgr_t * ) context;
+
+   if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "__osm_state_mgr_reset_node_count: "
+               "Resetting discovery count for node 0x%" PRIx64 "\n",
+               cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+   }
+
+   osm_node_discovery_count_reset( p_node );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_reset_port_count(
+   IN cl_map_item_t * const p_map_item,
+   IN void *context )
+{
+   osm_port_t *p_port = ( osm_port_t * ) p_map_item;
+   osm_state_mgr_t *const p_mgr = ( osm_state_mgr_t * ) context;
+
+   if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "__osm_state_mgr_reset_port_count: "
+               "Resetting discovery count for port 0x%" PRIx64 "\n",
+               cl_ntoh64( osm_port_get_guid( p_port ) ) );
+   }
+
+   osm_port_discovery_count_reset( p_port );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_reset_switch_count(
+   IN cl_map_item_t * const p_map_item,
+   IN void *context )
+{
+   osm_switch_t *p_sw = ( osm_switch_t * ) p_map_item;
+   osm_state_mgr_t *const p_mgr = ( osm_state_mgr_t * ) context;
+
+   if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "__osm_state_mgr_reset_switch_count: "
+               "Resetting discovery count for switch 0x%" PRIx64 "\n",
+               cl_ntoh64( osm_node_get_node_guid( p_sw->p_node ) ) );
+   }
+
+   osm_switch_discovery_count_reset( p_sw );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_get_sw_info(
+   IN cl_map_item_t * const p_object,
+   IN void *context )
+{
+   osm_node_t *p_node;
+   osm_dr_path_t *p_dr_path;
+   osm_madw_context_t mad_context;
+   osm_switch_t *const p_sw = ( osm_switch_t * ) p_object;
+   osm_state_mgr_t *const p_mgr = ( osm_state_mgr_t * ) context;
+   ib_api_status_t status;
+
+   OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_get_sw_info );
+
+   p_node = osm_switch_get_node_ptr( p_sw );
+   p_dr_path = osm_node_get_any_dr_path_ptr( p_node );
+
+   memset( &context, 0, sizeof( context ) );
+
+   mad_context.si_context.node_guid = osm_node_get_node_guid( p_node );
+   mad_context.si_context.set_method = FALSE;
+   mad_context.si_context.light_sweep = TRUE;
+
+   status = osm_req_get( p_mgr->p_req,
+                         p_dr_path,
+                         IB_MAD_ATTR_SWITCH_INFO,
+                         0, OSM_MSG_LIGHT_SWEEP_FAIL, &mad_context );
+
+   if( status != IB_SUCCESS )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_state_mgr_get_sw_info: ERR 3304: "
+               "Request SwitchInfo failed\n" );
+   }
+
+   OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ Initiate a remote port info request for the given physical port
+ **********************************************************************/
+static void
+__osm_state_mgr_get_remote_port_info(
+   IN osm_state_mgr_t * const p_mgr,
+   IN osm_physp_t * const p_physp )
+{
+   osm_dr_path_t *p_dr_path;
+   osm_dr_path_t rem_node_dr_path;
+   osm_madw_context_t mad_context;
+   ib_api_status_t status;
+
+   OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_get_remote_port_info );
+
+   /* generate a dr path leaving on the physp to the remote node */
+   p_dr_path = osm_physp_get_dr_path_ptr( p_physp );
+   memcpy( &rem_node_dr_path, p_dr_path, sizeof( osm_dr_path_t ) );
+   osm_dr_path_extend( &rem_node_dr_path, osm_physp_get_port_num( p_physp ) );
+
+   memset( &mad_context, 0, sizeof( mad_context ) );
+
+   mad_context.pi_context.node_guid =
+      osm_node_get_node_guid( osm_physp_get_node_ptr( p_physp ) );
+   mad_context.pi_context.port_guid =
+      cl_hton64( osm_physp_get_port_num( p_physp ) );
+   mad_context.pi_context.set_method = FALSE;
+   mad_context.pi_context.light_sweep = TRUE;
+   mad_context.pi_context.ignore_errors = FALSE;
+   mad_context.pi_context.update_master_sm_base_lid = FALSE;
+   mad_context.pi_context.active_transition = FALSE;
+
+   /* note that with some negative logic - if the query failed it means that
+    * there is no point in going to heavy sweep */
+   status = osm_req_get( p_mgr->p_req,
+                         &rem_node_dr_path,
+                         IB_MAD_ATTR_PORT_INFO,
+                         0, CL_DISP_MSGID_NONE, &mad_context );
+
+   if( status != IB_SUCCESS )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_state_mgr_get_remote_port_info: ERR 332E: "
+               "Request for PortInfo failed\n" );
+   }
+
+   OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ Initiates a thorough sweep of the subnet.
+ Used when there is suspicion that something on the subnet has changed.
+**********************************************************************/
+static ib_api_status_t
+__osm_state_mgr_sweep_hop_0(
+   IN osm_state_mgr_t * const p_mgr )
+{
+   ib_api_status_t status;
+   osm_dr_path_t dr_path;
+   osm_bind_handle_t h_bind;
+   osm_ni_context_t ni_context;
+   uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX];
+
+   OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_sweep_hop_0 );
+
+   memset( path_array, 0, sizeof( path_array ) );
+
+   /*
+    * First, get the bind handle.
+    */
+   h_bind = osm_sm_mad_ctrl_get_bind_handle( p_mgr->p_mad_ctrl );
+   if( h_bind != OSM_BIND_INVALID_HANDLE )
+   {
+      __osm_state_mgr_sweep_heavy_msg( p_mgr );
+
+      /*
+       * Start the sweep by clearing the port counts, then
+       * get our own NodeInfo at 0 hops.
+       */
+      CL_PLOCK_ACQUIRE( p_mgr->p_lock );
+
+      cl_qmap_apply_func( &p_mgr->p_subn->node_guid_tbl,
+                          __osm_state_mgr_reset_node_count, p_mgr );
+
+      cl_qmap_apply_func( &p_mgr->p_subn->port_guid_tbl,
+                          __osm_state_mgr_reset_port_count, p_mgr );
+
+      cl_qmap_apply_func( &p_mgr->p_subn->sw_guid_tbl,
+                          __osm_state_mgr_reset_switch_count, p_mgr );
+
+      /* Set the in_sweep_hop_0 flag in subn to be TRUE. 
+       * This will indicate the sweeping not to continue beyond the 
+       * the current node. 
+       * This is relevant for the case of SM on switch, since in the
+       * switch info we need to signal somehow not to continue 
+       * the sweeping. */
+      p_mgr->p_subn->in_sweep_hop_0 = TRUE;
+
+      CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+      memset( &ni_context, 0, sizeof( ni_context ) );
+      osm_dr_path_init( &dr_path, h_bind, 0, path_array );
+      status = osm_req_get( p_mgr->p_req,
+                            &dr_path,
+                            IB_MAD_ATTR_NODE_INFO,
+                            0, CL_DISP_MSGID_NONE, NULL );
+
+      if( status != IB_SUCCESS )
+      {
+         osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+                  "__osm_state_mgr_sweep_hop_0: ERR 3305: "
+                  "Request NodeInfo failed\n" );
+      }
+   }
+   else
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "__osm_state_mgr_sweep_hop_0: "
+               "No bound ports. Deferring sweep...\n" );
+      status = IB_INVALID_STATE;
+   }
+
+   OSM_LOG_EXIT( p_mgr->p_log );
+   return ( status );
+}
+
+/**********************************************************************
+ Clear out all existing port lid assignments
+**********************************************************************/
+static ib_api_status_t
+__osm_state_mgr_clean_known_lids(
+   IN osm_state_mgr_t * const p_mgr )
+{
+   ib_api_status_t status = IB_SUCCESS;
+   cl_ptr_vector_t *p_vec = &( p_mgr->p_subn->port_lid_tbl );
+   uint32_t i;
+
+   OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_clean_known_lids );
+
+   /* we need a lock here! */
+   CL_PLOCK_ACQUIRE( p_mgr->p_lock );
+
+   for( i = 0; i < cl_ptr_vector_get_size( p_vec ); i++ )
+      cl_ptr_vector_set( p_vec, i, NULL );
+
+   CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+   OSM_LOG_EXIT( p_mgr->p_log );
+   return ( status );
+}
+
+/**********************************************************************
+ Notifies the transport layer that the local LID has changed,
+ which give it a chance to update address vectors, etc..
+**********************************************************************/
+static ib_api_status_t
+__osm_state_mgr_notify_lid_change(
+   IN osm_state_mgr_t * const p_mgr )
+{
+   ib_api_status_t status;
+   osm_bind_handle_t h_bind;
+
+   OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_notify_lid_change );
+
+   /*
+    * First, get the bind handle.
+    */
+   h_bind = osm_sm_mad_ctrl_get_bind_handle( p_mgr->p_mad_ctrl );
+   if( h_bind == OSM_BIND_INVALID_HANDLE )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_state_mgr_notify_lid_change: ERR 3306: "
+               "No bound ports\n" );
+      status = IB_ERROR;
+      goto Exit;
+   }
+
+   /*
+    * Notify the transport layer that we changed the local LID.
+    */
+   status = osm_vendor_local_lid_change( h_bind );
+   if( status != IB_SUCCESS )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_state_mgr_notify_lid_change: ERR 3307: "
+               "Vendor LID update failed (%s)\n", ib_get_err_str( status ) );
+   }
+
+ Exit:
+   OSM_LOG_EXIT( p_mgr->p_log );
+   return ( status );
+}
+
+/**********************************************************************
+ Returns true if the SM port is down.
+ The SM's port object must exist in the port_guid table.
+**********************************************************************/
+static boolean_t
+__osm_state_mgr_is_sm_port_down(
+   IN osm_state_mgr_t * const p_mgr )
+{
+   ib_net64_t port_guid;
+   osm_port_t *p_port;
+   osm_physp_t *p_physp;
+   cl_qmap_t *p_tbl;
+   uint8_t state;
+
+   OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_is_sm_port_down );
+
+   port_guid = p_mgr->p_subn->sm_port_guid;
+
+   /*
+    * If we don't know our own port guid yet, assume the port is down.
+    */
+   if( port_guid == 0 )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_state_mgr_is_sm_port_down: ERR 3308: "
+               "SM port GUID unknown\n" );
+      state = IB_LINK_DOWN;
+      goto Exit;
+   }
+
+   p_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+   CL_ASSERT( port_guid );
+
+   CL_PLOCK_ACQUIRE( p_mgr->p_lock );
+   p_port = ( osm_port_t * ) cl_qmap_get( p_tbl, port_guid );
+   if( p_port == ( osm_port_t * ) cl_qmap_end( p_tbl ) )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_state_mgr_is_sm_port_down: ERR 3309: "
+               "SM port with GUID:%016" PRIx64 " is unknown\n",
+               cl_ntoh64( port_guid ) );
+      state = IB_LINK_DOWN;
+      CL_PLOCK_RELEASE( p_mgr->p_lock );
+      goto Exit;
+   }
+
+   p_physp = osm_port_get_default_phys_ptr( p_port );
+
+   CL_ASSERT( p_physp );
+   CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+   state = osm_physp_get_port_state( p_physp );
+   CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+ Exit:
+   OSM_LOG_EXIT( p_mgr->p_log );
+   return ( state == IB_LINK_DOWN );
+}
+
+/**********************************************************************
+ Sweeps the node 1 hop away.
+ This sets off a "chain reaction" that causes discovery of the subnet.
+ Used when there is suspicion that something on the subnet has changed.
+**********************************************************************/
+static ib_api_status_t
+__osm_state_mgr_sweep_hop_1(
+   IN osm_state_mgr_t * const p_mgr )
+{
+   ib_api_status_t status = IB_SUCCESS;
+   osm_bind_handle_t h_bind;
+   osm_madw_context_t context;
+   osm_node_t *p_node;
+   osm_port_t *p_port;
+   osm_physp_t *p_physp;
+   osm_dr_path_t *p_dr_path;
+   osm_dr_path_t hop_1_path;
+   ib_net64_t port_guid;
+   uint8_t port_num;
+   cl_qmap_t *p_port_tbl;
+   uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX];
+   uint8_t num_ports;
+   osm_physp_t *p_ext_physp;
+
+   OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_sweep_hop_1 );
+
+   /*
+    * First, get our own port and node objects.
+    */
+   p_port_tbl = &p_mgr->p_subn->port_guid_tbl;
+   port_guid = p_mgr->p_subn->sm_port_guid;
+
+   CL_ASSERT( port_guid );
+
+   /* Set the in_sweep_hop_0 flag in subn to be FALSE.
+    * This will indicate the sweeping to continue beyond the 
+    * the current node. 
+    * This is relevant for the case of SM on switch, since in the
+    * switch info we need to signal that the sweeping should 
+    * continue through the switch. */
+   p_mgr->p_subn->in_sweep_hop_0 = FALSE;
+
+   p_port = ( osm_port_t * ) cl_qmap_get( p_port_tbl, port_guid );
+   if( p_port == ( osm_port_t * ) cl_qmap_end( p_port_tbl ) )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_state_mgr_sweep_hop_1: ERR 3310: "
+               "No SM port object\n" );
+      status = IB_ERROR;
+      goto Exit;
+   }
+
+   p_node = osm_port_get_parent_node( p_port );
+   CL_ASSERT( p_node );
+
+   port_num = ib_node_info_get_local_port_num( &p_node->node_info );
+
+   osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+            "__osm_state_mgr_sweep_hop_1: "
+            "Probing hop 1 on local port %u\n", port_num );
+
+   p_physp = osm_node_get_physp_ptr( p_node, port_num );
+
+   CL_ASSERT( p_physp );
+   CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+   p_dr_path = osm_physp_get_dr_path_ptr( p_physp );
+   h_bind = osm_dr_path_get_bind_handle( p_dr_path );
+
+   CL_ASSERT( h_bind != OSM_BIND_INVALID_HANDLE );
+
+   memset( path_array, 0, sizeof( path_array ) );
+   /* the hop_1 operations depend on the type of our node.
+    * Currently - legal nodes that can host SM are SW and CA */
+   switch ( osm_node_get_type( p_node ) )
+   {
+   case IB_NODE_TYPE_CA:
+   case IB_NODE_TYPE_ROUTER:
+      context.ni_context.node_guid = osm_node_get_node_guid( p_node );
+      context.ni_context.port_num = port_num;
+
+      path_array[1] = port_num;
+
+      osm_dr_path_init( &hop_1_path, h_bind, 1, path_array );
+      status = osm_req_get( p_mgr->p_req,
+                            &hop_1_path,
+                            IB_MAD_ATTR_NODE_INFO,
+                            0, CL_DISP_MSGID_NONE, &context );
+
+      if( status != IB_SUCCESS )
+      {
+         osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+                  "__osm_state_mgr_sweep_hop_1: ERR 3311: "
+                  "Request NodeInfo failed\n" );
+      }
+      break;
+
+   case IB_NODE_TYPE_SWITCH:
+      /* Need to go over all the ports of the switch, and send a node_info
+       * from them. This doesn't include the port 0 of the switch, which 
+       * hosts the SM. 
+       * Note: We'll send another switchInfo on port 0, since if no ports
+       * are connected, we still want to get some response, and have the
+       * subnet come up.
+       */
+      num_ports = osm_node_get_num_physp( p_node );
+      for( port_num = 0; port_num < num_ports; port_num++ )
+      {
+         /* go through the port only if the port is not DOWN */
+         p_ext_physp = osm_node_get_physp_ptr( p_node, port_num );
+         /* Make sure the physp object exists */
+         if( !p_ext_physp )
+            continue;
+         if( ib_port_info_get_port_state( &( p_ext_physp->port_info ) ) >
+             IB_LINK_DOWN )
+         {
+            context.ni_context.node_guid = osm_node_get_node_guid( p_node );
+            context.ni_context.port_num = port_num;
+
+            path_array[1] = port_num;
+
+            osm_dr_path_init( &hop_1_path, h_bind, 1, path_array );
+            status = osm_req_get( p_mgr->p_req,
+                                  &hop_1_path,
+                                  IB_MAD_ATTR_NODE_INFO,
+                                  0, CL_DISP_MSGID_NONE, &context );
+
+            if( status != IB_SUCCESS )
+            {
+               osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+                        "__osm_state_mgr_sweep_hop_1: ERR 3312: "
+                        "Request NodeInfo failed\n" );
+            }
+         }
+      }
+      break;
+
+   default:
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_state_mgr_sweep_hop_1: ERR 3313: Unknown node type %d\n",
+               osm_node_get_type( p_node ) );
+   }
+
+ Exit:
+   OSM_LOG_EXIT( p_mgr->p_log );
+   return ( status );
+}
+
+/**********************************************************************
+ Initiates a lightweight sweep of the subnet.
+ Used during normal sweeps after the subnet is up.
+**********************************************************************/
+static ib_api_status_t
+__osm_state_mgr_light_sweep_start(
+   IN osm_state_mgr_t * const p_mgr )
+{
+   ib_api_status_t status = IB_SUCCESS;
+   osm_bind_handle_t h_bind;
+   cl_qmap_t *p_sw_tbl;
+   cl_list_t *p_no_rem_port_list;
+   cl_list_iterator_t list_iter;
+   uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX];
+
+   OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_light_sweep_start );
+
+   p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+   memset( path_array, 0, sizeof( path_array ) );
+
+   /*
+    * First, get the bind handle.
+    */
+   h_bind = osm_sm_mad_ctrl_get_bind_handle( p_mgr->p_mad_ctrl );
+   if( h_bind != OSM_BIND_INVALID_HANDLE )
+   {
+      __osm_state_mgr_sweep_light_msg( p_mgr );
+      CL_PLOCK_ACQUIRE( p_mgr->p_lock );
+      cl_qmap_apply_func( p_sw_tbl, __osm_state_mgr_get_sw_info, p_mgr );
+      CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+      /* now scan the list of physical ports that were not down but have no remote port */
+      CL_PLOCK_ACQUIRE( p_mgr->p_lock );
+      p_no_rem_port_list = &p_mgr->p_subn->light_sweep_physp_list;
+      list_iter = cl_list_head( p_no_rem_port_list );
+      while( list_iter != cl_list_end( p_no_rem_port_list ) )
+      {
+         __osm_state_mgr_get_remote_port_info( p_mgr,
+                                               ( osm_physp_t * )
+                                               cl_list_obj( list_iter ) );
+         list_iter = cl_list_next( list_iter );
+      }
+      CL_PLOCK_RELEASE( p_mgr->p_lock );
+   }
+   else
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "__osm_state_mgr_light_sweep_start: "
+               "No bound ports. Deferring sweep...\n" );
+      status = IB_INVALID_STATE;
+   }
+
+   OSM_LOG_EXIT( p_mgr->p_log );
+   return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_topology_file_create(
+   IN osm_state_mgr_t * const p_mgr )
+{
+   const osm_node_t *p_node;
+   char *file_name;
+   FILE *rc;
+   char desc[IB_NODE_DESCRIPTION_SIZE + 1];
+
+   OSM_LOG_ENTER( p_mgr->p_log, __osm_topology_file_create );
+
+   CL_PLOCK_ACQUIRE( p_mgr->p_lock );
+
+   file_name =
+      ( char * )malloc( strlen( p_mgr->p_subn->opt.dump_files_dir )
+                        + strlen(SUBNET_LIST_FILENAME) + 1 );
+
+   CL_ASSERT( file_name );
+
+   strcpy( file_name, p_mgr->p_subn->opt.dump_files_dir );
+   strcat( file_name, SUBNET_LIST_FILENAME );
+
+   if( ( rc = fopen( file_name, "w" ) ) == NULL )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "__osm_topology_file_create: "
+               "fopen failed for file:%s\n", file_name );
+
+      CL_PLOCK_RELEASE( p_mgr->p_lock );
+      goto Exit;
+   }
+
+   p_node = ( osm_node_t * ) cl_qmap_head( &p_mgr->p_subn->node_guid_tbl );
+   while( p_node !=
+          ( osm_node_t * ) cl_qmap_end( &p_mgr->p_subn->node_guid_tbl ) )
+   {
+      if( p_node->node_info.num_ports )
+      {
+         uint32_t cPort;
+         osm_node_t *p_nbnode;
+         osm_physp_t *p_physp;
+         osm_physp_t *p_default_physp;
+         osm_physp_t *p_rphysp;
+         uint8_t link_speed_act;
+
+         for( cPort = 1; cPort < osm_node_get_num_physp( p_node ); cPort++ )
+         {
+            uint8_t port_state;
+
+            p_physp = osm_node_get_physp_ptr( p_node, cPort );
+
+            if( ( p_physp == NULL ) || ( !osm_physp_is_valid( p_physp ) ) )
+               continue;
+
+            p_rphysp = p_physp->p_remote_physp;
+
+            if( ( p_rphysp == NULL ) || ( !osm_physp_is_valid( p_rphysp ) ) )
+               continue;
+
+            CL_ASSERT( cPort == p_physp->port_num );
+
+            if( p_node->node_info.node_type == IB_NODE_TYPE_SWITCH )
+            {
+               p_default_physp = osm_node_get_physp_ptr( p_node, 0 );
+            }
+            else
+            {
+               p_default_physp = p_physp;
+            }
+
+            memcpy(desc, p_node->node_desc.description,
+                   IB_NODE_DESCRIPTION_SIZE);
+            desc[IB_NODE_DESCRIPTION_SIZE] = '\0';
+
+            fprintf( rc, "{ %s%s Ports:%02X"
+                     " SystemGUID:%016" PRIx64
+                     " NodeGUID:%016" PRIx64
+                     " PortGUID:%016" PRIx64
+                     " VenID:%06X DevID:%04X Rev:%08X {%s} LID:%04X PN:%02X } ",
+                     ( p_node->node_info.node_type ==
+                       IB_NODE_TYPE_SWITCH ) ? "SW" : ( p_node->node_info.
+                                                        node_type ==
+                                                        IB_NODE_TYPE_CA ) ?
+                     "CA" : ( p_node->node_info.node_type ==
+                              IB_NODE_TYPE_ROUTER ) ? "Rt" : "**",
+                     ( p_default_physp->port_info.base_lid ==
+                       p_default_physp->port_info.
+                       master_sm_base_lid ) ? "-SM" : "",
+                     p_node->node_info.num_ports,
+                     cl_ntoh64( p_node->node_info.sys_guid ),
+                     cl_ntoh64( p_node->node_info.node_guid ),
+                     cl_ntoh64( p_physp->port_guid ),
+                     cl_ntoh32( ib_node_info_get_vendor_id
+                                ( &p_node->node_info ) ),
+                     cl_ntoh16( p_node->node_info.device_id ),
+                     cl_ntoh32( p_node->node_info.revision ),
+                     desc,
+                     cl_ntoh16( p_default_physp->port_info.base_lid ),
+                     cPort );
+
+            p_nbnode = p_rphysp->p_node;
+
+            if( p_nbnode->node_info.node_type == IB_NODE_TYPE_SWITCH )
+            {
+               p_default_physp = osm_node_get_physp_ptr( p_nbnode, 0 );
+            }
+            else
+            {
+               p_default_physp = p_rphysp;
+            }
+
+            memcpy(desc, p_nbnode->node_desc.description,
+                   IB_NODE_DESCRIPTION_SIZE);
+            desc[IB_NODE_DESCRIPTION_SIZE] = '\0';
+
+            fprintf( rc, "{ %s%s Ports:%02X"
+                     " SystemGUID:%016" PRIx64
+                     " NodeGUID:%016" PRIx64
+                     " PortGUID:%016" PRIx64
+                     " VenID:%08X DevID:%04X Rev:%08X {%s} LID:%04X PN:%02X } ",
+                     ( p_nbnode->node_info.node_type ==
+                       IB_NODE_TYPE_SWITCH ) ? "SW" : ( p_nbnode->node_info.
+                                                        node_type ==
+                                                        IB_NODE_TYPE_CA ) ?
+                     "CA" : ( p_nbnode->node_info.node_type ==
+                              IB_NODE_TYPE_ROUTER ) ? "Rt" : "**",
+                     ( p_default_physp->port_info.base_lid ==
+                       p_default_physp->port_info.
+                       master_sm_base_lid ) ? "-SM" : "",
+                     p_nbnode->node_info.num_ports,
+                     cl_ntoh64( p_nbnode->node_info.sys_guid ),
+                     cl_ntoh64( p_nbnode->node_info.node_guid ),
+                     cl_ntoh64( p_rphysp->port_guid ),
+                     cl_ntoh32( ib_node_info_get_vendor_id
+                                ( &p_nbnode->node_info ) ),
+                     cl_ntoh32( p_nbnode->node_info.device_id ),
+                     cl_ntoh32( p_nbnode->node_info.revision ),
+                     desc,
+                     cl_ntoh16( p_default_physp->port_info.base_lid ),
+                     p_rphysp->port_num );
+
+            port_state = ib_port_info_get_port_state( &p_physp->port_info );
+            link_speed_act =
+               ib_port_info_get_link_speed_active( &p_physp->port_info );
+
+            fprintf( rc, "PHY=%s LOG=%s SPD=%s\n",
+                     ( p_physp->port_info.link_width_active == 1 ) ? "1x" :
+                     ( p_physp->port_info.link_width_active == 2 ) ? "4x" :
+                     ( p_physp->port_info.link_width_active == 8 ) ? "12x" :
+                     "??",
+                     ( ( port_state == IB_LINK_ACTIVE ) ? "ACT" :
+                       ( port_state == IB_LINK_ARMED ) ? "ARM" :
+                       ( port_state == IB_LINK_INIT ) ? "INI" : "DWN" ),
+                     ( link_speed_act == 1 ) ? "2.5" :
+                     ( link_speed_act == 2 ) ? "5" :
+                     ( link_speed_act == 4 ) ? "10" : "??" );
+         }
+      }
+      p_node = ( osm_node_t * ) cl_qmap_next( &p_node->map_item );
+   }
+
+   CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+   fclose( rc );
+
+ Exit:
+   free( file_name );
+   OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_report(
+   IN osm_state_mgr_t * const p_mgr )
+{
+   const cl_qmap_t *p_tbl;
+   const osm_port_t *p_port;
+   const osm_node_t *p_node;
+   const osm_physp_t *p_physp;
+   const osm_physp_t *p_remote_physp;
+   const ib_port_info_t *p_pi;
+   uint8_t port_num;
+   uint8_t start_port;
+   uint32_t num_ports;
+   uint8_t node_type;
+
+   if( !osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+      return;
+
+   OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_report );
+
+   osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE,
+                   "\n==================================================="
+                   "===================================================="
+                   "\nVendor      : Ty "
+                   ": #  : Sta : LID  : LMC : MTU  : LWA : LSA : Port GUID    "
+                   "    : Neighbor Port (Port #)\n" );
+
+   p_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+   /*
+    * Hold lock non-exclusively while we perform these read-only operations.
+    */
+
+   CL_PLOCK_ACQUIRE( p_mgr->p_lock );
+   p_port = ( osm_port_t * ) cl_qmap_head( p_tbl );
+   while( p_port != ( osm_port_t * ) cl_qmap_end( p_tbl ) )
+   {
+      if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+      {
+         osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+                  "__osm_state_mgr_report: "
+                  "Processing port 0x%016" PRIx64 "\n",
+                  cl_ntoh64( osm_port_get_guid( p_port ) ) );
+      }
+
+      p_node = osm_port_get_parent_node( p_port );
+      node_type = osm_node_get_type( p_node );
+      if( node_type == IB_NODE_TYPE_SWITCH )
+         start_port = 0;
+      else
+         start_port = 1;
+
+      num_ports = osm_port_get_num_physp( p_port );
+      for( port_num = start_port; port_num < num_ports; port_num++ )
+      {
+         p_physp = osm_port_get_phys_ptr( p_port, port_num );
+         if( ( p_physp == NULL ) || ( !osm_physp_is_valid( p_physp ) ) )
+            continue;
+
+         osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, "%s : %s : %02X :",
+                         osm_get_manufacturer_str( cl_ntoh64
+                                                   ( osm_node_get_node_guid
+                                                   ( p_node ) ) ),
+                         osm_get_node_type_str_fixed_width( node_type ),
+                         port_num );
+
+         p_pi = osm_physp_get_port_info_ptr( p_physp );
+
+         /*
+          * Port state is not defined for switch port 0
+          */
+         if( port_num == 0 )
+            osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, "     :" );
+         else
+            osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, " %s :",
+                            osm_get_port_state_str_fixed_width
+                            ( ib_port_info_get_port_state( p_pi ) ) );
+
+         /*
+          * LID values are only meaningful in select cases.
+          */
+         if( ib_port_info_get_port_state( p_pi ) != IB_LINK_DOWN
+             && ( ( node_type == IB_NODE_TYPE_SWITCH && port_num == 0 )
+                  || node_type != IB_NODE_TYPE_SWITCH ) )
+            osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, " %04X :  %01X  :",
+                            cl_ntoh16( p_pi->base_lid ),
+                            ib_port_info_get_lmc( p_pi ) );
+         else
+            osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, "      :     :" );
+
+         if( port_num != 0 )
+            osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, " %s : %s : %s ",
+                            osm_get_mtu_str( ib_port_info_get_neighbor_mtu( p_pi ) ),
+                            osm_get_lwa_str( p_pi->link_width_active ),
+                            osm_get_lsa_str( ib_port_info_get_link_speed_active
+                                             ( p_pi ) ) );
+         else
+            osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, "      :     :     " );
+
+         if( osm_physp_get_port_guid( p_physp ) ==
+             p_mgr->p_subn->sm_port_guid )
+            osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, "* %016" PRIx64 " *",
+                            cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) );
+         else
+            osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, ": %016" PRIx64 " :",
+                            cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) );
+
+         if( port_num &&
+             ( ib_port_info_get_port_state( p_pi ) != IB_LINK_DOWN ) )
+         {
+            p_remote_physp = osm_physp_get_remote( p_physp );
+            if( p_remote_physp && osm_physp_is_valid( p_remote_physp ) )
+            {
+               osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE,
+                               " %016" PRIx64 " (%02X)",
+                               cl_ntoh64( osm_physp_get_port_guid
+                                          ( p_remote_physp ) ),
+                               osm_physp_get_port_num( p_remote_physp ) );
+            }
+            else
+               osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, " UNKNOWN" );
+         }
+
+         osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, "\n" );
+      }
+
+      osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE,
+                      "------------------------------------------------------"
+                      "------------------------------------------------\n" );
+      p_port = ( osm_port_t * ) cl_qmap_next( &p_port->map_item );
+   }
+
+   CL_PLOCK_RELEASE( p_mgr->p_lock );
+   OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__process_idle_time_queue_done(
+   IN osm_state_mgr_t * const p_mgr )
+{
+   cl_qlist_t *p_list = &p_mgr->idle_time_list;
+   cl_list_item_t *p_list_item;
+   osm_idle_item_t *p_process_item;
+
+   OSM_LOG_ENTER( p_mgr->p_log, __process_idle_time_queue_done );
+
+   cl_spinlock_acquire( &p_mgr->idle_lock );
+   p_list_item = cl_qlist_remove_head( p_list );
+
+   if( p_list_item == cl_qlist_end( p_list ) )
+   {
+      cl_spinlock_release( &p_mgr->idle_lock );
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "__process_idle_time_queue_done: ERR 3314: "
+               "Idle time queue is empty\n" );
+      return;
+   }
+   cl_spinlock_release( &p_mgr->idle_lock );
+
+   p_process_item = ( osm_idle_item_t * ) p_list_item;
+
+   if( p_process_item->pfn_done )
+   {
+
+      p_process_item->pfn_done( p_process_item->context1,
+                                p_process_item->context2 );
+   }
+
+   free( p_process_item );
+
+   OSM_LOG_EXIT( p_mgr->p_log );
+   return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static osm_signal_t
+__process_idle_time_queue_start(
+   IN osm_state_mgr_t * const p_mgr )
+{
+   cl_qlist_t *p_list = &p_mgr->idle_time_list;
+   cl_list_item_t *p_list_item;
+   osm_idle_item_t *p_process_item;
+   osm_signal_t signal;
+
+   OSM_LOG_ENTER( p_mgr->p_log, __process_idle_time_queue_start );
+
+   cl_spinlock_acquire( &p_mgr->idle_lock );
+
+   p_list_item = cl_qlist_head( p_list );
+   if( p_list_item == cl_qlist_end( p_list ) )
+   {
+      cl_spinlock_release( &p_mgr->idle_lock );
+      OSM_LOG_EXIT( p_mgr->p_log );
+      return OSM_SIGNAL_NONE;
+   }
+
+   cl_spinlock_release( &p_mgr->idle_lock );
+
+   p_process_item = ( osm_idle_item_t * ) p_list_item;
+
+   CL_ASSERT( p_process_item->pfn_start );
+
+   signal = p_process_item->pfn_start( p_process_item->context1,
+                                       p_process_item->context2 );
+
+   CL_ASSERT( signal != OSM_SIGNAL_NONE );
+
+   OSM_LOG_EXIT( p_mgr->p_log );
+   return signal;
+}
+
+/**********************************************************************
+ * Go over all the remote SMs (as updated in the sm_guid_tbl).
+ * Find if there is a remote sm that is a master SM.
+ * If there is a remote master SM - return TRUE, else - return FALSE.
+ **********************************************************************/
+static osm_remote_sm_t *
+__osm_state_mgr_exists_other_master_sm(
+   IN osm_state_mgr_t * const p_mgr )
+{
+   cl_qmap_t *p_sm_tbl;
+   osm_remote_sm_t *p_sm;
+   osm_remote_sm_t *p_sm_res = NULL;
+
+   OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_exists_other_master_sm );
+
+   p_sm_tbl = &p_mgr->p_subn->sm_guid_tbl;
+
+   /*  go over all the remote SMs */
+   for( p_sm = ( osm_remote_sm_t * ) cl_qmap_head( p_sm_tbl );
+        p_sm != ( osm_remote_sm_t * ) cl_qmap_end( p_sm_tbl );
+        p_sm = ( osm_remote_sm_t * ) cl_qmap_next( &p_sm->map_item ) )
+   {
+      /* If the sm is in MASTER state - return TRUE */
+      if( ib_sminfo_get_state( &p_sm->smi ) == IB_SMINFO_STATE_MASTER )
+      {
+         osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+                  "__osm_state_mgr_exists_other_master_sm: "
+                  "Found remote master SM with guid:0x%016" PRIx64 "\n",
+                  cl_ntoh64(p_sm->smi.guid) );
+         p_sm_res = p_sm;
+         goto Exit;
+      }
+   }
+
+ Exit:
+   OSM_LOG_EXIT( p_mgr->p_log );
+   return ( p_sm_res );
+}
+
+/**********************************************************************
+ * Go over all remote SMs (as updated in the sm_guid_tbl).
+ * Find the one with the highest priority and lowest guid.
+ * Compare this SM to the local SM. If the local SM is higher -
+ * return NULL, if the remote SM is higher - return a pointer to it.
+ **********************************************************************/
+static osm_remote_sm_t *
+__osm_state_mgr_get_highest_sm(
+   IN osm_state_mgr_t * const p_mgr )
+{
+   cl_qmap_t *p_sm_tbl;
+   osm_remote_sm_t *p_sm = NULL;
+   osm_remote_sm_t *p_highest_sm;
+   uint8_t highest_sm_priority;
+   ib_net64_t highest_sm_guid;
+
+   OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_get_highest_sm );
+
+   p_sm_tbl = &p_mgr->p_subn->sm_guid_tbl;
+
+   /* Start with the local sm as the standard */
+   p_highest_sm = NULL;
+   highest_sm_priority = p_mgr->p_subn->opt.sm_priority;
+   highest_sm_guid = p_mgr->p_subn->sm_port_guid;
+
+   /* go over all the remote SMs */
+   for( p_sm = ( osm_remote_sm_t * ) cl_qmap_head( p_sm_tbl );
+        p_sm != ( osm_remote_sm_t * ) cl_qmap_end( p_sm_tbl );
+        p_sm = ( osm_remote_sm_t * ) cl_qmap_next( &p_sm->map_item ) )
+   {
+
+      /* If the sm is in NOTACTIVE state - continue */
+      if( ib_sminfo_get_state( &p_sm->smi ) == IB_SMINFO_STATE_NOTACTIVE )
+         continue;
+
+      if( osm_sm_is_greater_than( ib_sminfo_get_priority( &p_sm->smi ),
+                                  p_sm->smi.guid, highest_sm_priority,
+                                  highest_sm_guid ) )
+      {
+         /* the new p_sm is with higher priority - update the highest_sm */
+         /* to this sm */
+         p_highest_sm = p_sm;
+         highest_sm_priority = ib_sminfo_get_priority( &p_sm->smi );
+         highest_sm_guid = p_sm->smi.guid;
+      }
+   }
+
+   if( p_highest_sm != NULL )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "__osm_state_mgr_get_highest_sm: "
+               "Found higher SM with guid: %016" PRIx64 "\n",
+               cl_ntoh64( p_highest_sm->smi.guid ) );
+   }
+
+   OSM_LOG_EXIT( p_mgr->p_log );
+   return ( p_highest_sm );
+}
+
+/**********************************************************************
+ * Send SubnSet(SMInfo) SMP with HANDOVER attribute to the
+ * remote_sm indicated.
+ **********************************************************************/
+static void
+__osm_state_mgr_send_handover(
+   IN osm_state_mgr_t * const p_mgr,
+   IN osm_remote_sm_t * const p_sm )
+{
+   uint8_t payload[IB_SMP_DATA_SIZE];
+   ib_sm_info_t *p_smi = ( ib_sm_info_t * ) payload;
+   osm_madw_context_t context;
+   const osm_port_t *p_port;
+   ib_api_status_t status;
+
+   OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_send_handover );
+
+   if( p_mgr->p_subn->opt.testability_mode ==
+       OSM_TEST_MODE_EXIT_BEFORE_SEND_HANDOVER )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_state_mgr_send_handover: ERR 3315: "
+               "Exit on testability mode OSM_TEST_MODE_EXIT_BEFORE_SEND_HANDOVER\n" );
+      osm_exit_flag = TRUE;
+      sleep( 3 );
+      exit( 1 );
+   }
+
+   /*
+    * Send a query of SubnSet(SMInfo) HANDOVER to the remote sm given.
+    */
+
+   memset( &context, 0, sizeof( context ) );
+   p_port = p_sm->p_port;
+   if( p_port == NULL )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_state_mgr_send_handover: ERR 3316: "
+               "No port object on given remote_sm object\n" );
+      goto Exit;
+   }
+
+   /* update the master_guid in the p_sm_state_mgr object according to */
+   /* the guid of the port where the new Master SM should reside. */
+   osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+            "__osm_state_mgr_send_handover: "
+            "Handing over mastership. Updating sm_state_mgr master_guid: %016"
+            PRIx64 "\n", cl_ntoh64( p_port->guid ) );
+   p_mgr->p_sm_state_mgr->master_guid = p_port->guid;
+
+   context.smi_context.port_guid = p_port->guid;
+   context.smi_context.set_method = TRUE;
+
+   p_smi->guid = p_mgr->p_subn->sm_port_guid;
+   p_smi->act_count = cl_hton32( p_mgr->p_stats->qp0_mads_sent );
+   p_smi->pri_state = ( uint8_t ) ( p_mgr->p_subn->sm_state |
+                                    p_mgr->p_subn->opt.sm_priority << 4 );
+   /*
+    * Return 0 for the SM key unless we authenticate the requester
+    * as the master SM.
+    */
+   if( ib_sminfo_get_state( &p_sm->smi ) == IB_SMINFO_STATE_MASTER )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "__osm_state_mgr_send_handover: "
+               "Responding to master SM with real sm_key\n" );
+      p_smi->sm_key = p_mgr->p_subn->opt.sm_key;
+   }
+   else
+   {
+      /* The requester is not authenticated as master - set sm_key to zero */
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "__osm_state_mgr_send_handover: "
+               "Responding to SM not master with zero sm_key\n" );
+      p_smi->sm_key = 0;
+   }
+
+   status = osm_req_set( p_mgr->p_req,
+                         osm_physp_get_dr_path_ptr
+                         ( osm_port_get_default_phys_ptr( p_port ) ), payload,
+                         sizeof(payload),
+                         IB_MAD_ATTR_SM_INFO, IB_SMINFO_ATTR_MOD_HANDOVER,
+                         CL_DISP_MSGID_NONE, &context );
+
+   if( status != IB_SUCCESS )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_state_mgr_send_handover: ERR 3317: "
+               "Failure requesting SMInfo (%s)\n", ib_get_err_str( status ) );
+   }
+
+ Exit:
+   OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ * Send Trap 64 on all ports in new_ports_list.
+ **********************************************************************/
+static void
+__osm_state_mgr_report_new_ports(
+   IN osm_state_mgr_t * const p_mgr )
+{
+   osm_port_t *p_port;
+   ib_gid_t port_gid;
+   ib_mad_notice_attr_t notice;
+   ib_api_status_t status;
+   ib_net64_t port_guid;
+   uint16_t min_lid_ho;
+   uint16_t max_lid_ho;
+   char desc[IB_NODE_DESCRIPTION_SIZE + 1];
+
+   OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_report_new_ports );
+
+   CL_PLOCK_ACQUIRE( p_mgr->p_lock );
+   p_port =
+      ( osm_port_t
+        * ) ( cl_list_remove_head( &p_mgr->p_subn->new_ports_list ) );
+   while( p_port != NULL )
+   {
+      port_guid = osm_port_get_guid( p_port );
+      /* issue a notice - trap 64 */
+
+      /* details of the notice */
+      notice.generic_type = 0x83;   /* is generic subn mgt type */
+      ib_notice_set_prod_type_ho( &notice, 4 ); /* A Class Manager generator */
+      /* endport becomes to be reachable */
+      notice.g_or_v.generic.trap_num = CL_HTON16( 64 );
+      /* The sm_base_lid is saved in network order already. */
+      notice.issuer_lid = p_mgr->p_subn->sm_base_lid;
+      /* following C14-72.1.1 and table 119 p725 */
+      /* we need to provide the GID */
+      port_gid.unicast.prefix = p_mgr->p_subn->opt.subnet_prefix;
+      port_gid.unicast.interface_id = port_guid;
+      memcpy( &( notice.data_details.ntc_64_67.gid ),
+              &( port_gid ), sizeof( ib_gid_t ) );
+
+      /* According to page 653 - the issuer gid in this case of trap
+       * is the SM gid, since the SM is the initiator of this trap. */
+      notice.issuer_gid.unicast.prefix = p_mgr->p_subn->opt.subnet_prefix;
+      notice.issuer_gid.unicast.interface_id = p_mgr->p_subn->sm_port_guid;
+
+      status = osm_report_notice( p_mgr->p_log, p_mgr->p_subn, &notice );
+      if( status != IB_SUCCESS )
+      {
+         osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+                  "__osm_state_mgr_report_new_ports: ERR 3318: "
+                  "Error sending trap reports on GUID:0x%016" PRIx64
+                  " (%s)\n", port_gid.unicast.interface_id,
+                  ib_get_err_str( status ) );
+      }
+      osm_port_get_lid_range_ho( p_port, &min_lid_ho, &max_lid_ho );
+      if (p_port->p_node)
+      {
+         memcpy(desc, p_port->p_node->node_desc.description,
+                IB_NODE_DESCRIPTION_SIZE);
+         desc[IB_NODE_DESCRIPTION_SIZE] = '\0';
+      }
+      osm_log( p_mgr->p_log, OSM_LOG_INFO,
+               "Discovered new port with GUID:0x%016" PRIx64
+               " LID range [0x%X,0x%X] of node:%s\n",
+               cl_ntoh64( port_gid.unicast.interface_id ),
+               min_lid_ho, max_lid_ho,
+               p_port->p_node ? desc : "UNKNOWN" );
+
+      p_port =
+         ( osm_port_t
+           * ) ( cl_list_remove_head( &p_mgr->p_subn->new_ports_list ) );
+   }
+   CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+   OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ * Make sure that the lid_port_tbl of the subnet has only the ports 
+ * that are recognized, and in the correct lid place. There could be
+ * errors if we wanted to assign a certain port with lid X, but that 
+ * request didn't reach the port. In this case port_lid_tbl will have
+ * the port under lid X, though the port isn't updated with this lid.
+ * We will run a new heavy sweep (since there were errors in the 
+ * initialization), but here we'll clean the database from incorrect 
+ * information.
+ **********************************************************************/
+static void
+__osm_state_mgr_check_tbl_consistency(
+   IN osm_state_mgr_t * const p_mgr )
+{
+   cl_qmap_t *p_port_guid_tbl;
+   osm_port_t *p_port;
+   osm_port_t *p_next_port;
+   cl_ptr_vector_t *p_port_lid_tbl;
+   size_t max_lid, ref_size, curr_size, lid;
+   osm_port_t *p_port_ref, *p_port_stored;
+   cl_ptr_vector_t ref_port_lid_tbl;
+   uint16_t min_lid_ho;
+   uint16_t max_lid_ho;
+   uint16_t lid_ho;
+
+   OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_check_tbl_consistency );
+
+   cl_ptr_vector_construct( &ref_port_lid_tbl );
+   cl_ptr_vector_init( &ref_port_lid_tbl,
+                       cl_ptr_vector_get_size( &p_mgr->p_subn->port_lid_tbl ),
+                       OSM_SUBNET_VECTOR_GROW_SIZE );
+
+   p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+   /* Let's go over all the ports according to port_guid_tbl,
+    * and add the port to a reference port_lid_tbl. */
+   p_next_port = ( osm_port_t * ) cl_qmap_head( p_port_guid_tbl );
+   while( p_next_port != ( osm_port_t * ) cl_qmap_end( p_port_guid_tbl ) )
+   {
+      p_port = p_next_port;
+      p_next_port = ( osm_port_t * ) cl_qmap_next( &p_next_port->map_item );
+
+      osm_port_get_lid_range_ho( p_port, &min_lid_ho, &max_lid_ho );
+      for( lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++ )
+         cl_ptr_vector_set( &ref_port_lid_tbl, lid_ho, p_port );
+   }
+
+   p_port_lid_tbl = &p_mgr->p_subn->port_lid_tbl;
+
+   ref_size = cl_ptr_vector_get_size( &ref_port_lid_tbl );
+   curr_size = cl_ptr_vector_get_size( p_port_lid_tbl );
+   /* They should be the same, but compare it anyway */
+   max_lid = ( ref_size > curr_size ) ? ref_size : curr_size;
+
+   for( lid = 1; lid <= max_lid; lid++ )
+   {
+      p_port_ref = NULL;
+      p_port_stored = NULL;
+      cl_ptr_vector_at( p_port_lid_tbl, lid, ( void * )&p_port_stored );
+      cl_ptr_vector_at( &ref_port_lid_tbl, lid, ( void * )&p_port_ref );
+
+      if( p_port_stored == p_port_ref )
+         /* This is the "good" case - both entries are the same for this lid. 
+          * Nothing to do. */
+         continue;
+
+      if( p_port_ref == NULL )
+      {
+         /* There is an object in the subnet database for this lid,
+          * but no such object exists in the reference port_list_tbl. 
+          * This can occur if we wanted to assign a certain port with some
+          * lid (different than the one pre-assigned to it), and the port 
+          * didn't get the PortInfo Set request. Due to this, the port 
+          * is updated with its original lid in our database, but with the
+          * new lid we wanted to give it in our port_lid_tbl. */
+         osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+                  "__osm_state_mgr_check_tbl_consistency: ERR 3322: "
+                  "lid 0x%zX is wrongly assigned to port 0x%016" PRIx64
+                  " in port_lid_tbl\n",
+                  lid, cl_ntoh64( osm_port_get_guid( p_port_stored ) ) );
+      }
+      else
+      {
+         if( p_port_stored == NULL )
+         {
+            /* There is an object in the new database, but no object in our subnet
+             * database. This is the matching case of the prior check - the port
+             * still has its original lid. */
+            osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+                     "__osm_state_mgr_check_tbl_consistency: ERR 3323: "
+                     "port 0x%016" PRIx64 " exists in new port_lid_tbl under "
+                     "lid 0x%zX, but missing in subnet port_lid_tbl db\n",
+                     cl_ntoh64( osm_port_get_guid( p_port_ref ) ), lid );
+         }
+         else
+         {
+
+            /* if we reached here then p_port_stored != p_port_ref. 
+             * We were trying to set a lid to p_port_stored, but it didn't reach it,
+             * and p_port_ref also didn't get the lid update. */
+            osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+                     "__osm_state_mgr_check_tbl_consistency: ERR 3324: "
+                     "lid 0x%zX has port 0x%016" PRIx64
+                     " in new port_lid_tbl db, " "and port 0x%016" PRIx64
+                     " in subnet port_lid_tbl db\n", lid,
+                     cl_ntoh64( osm_port_get_guid( p_port_ref ) ),
+                     cl_ntoh64( osm_port_get_guid( p_port_stored ) ) );
+         }
+      }
+      /* In any of these cases we want to set NULL in the port_lid_tbl, since this
+       * entry is invalid. Also, make sure we'll do another heavy sweep. */
+      cl_ptr_vector_set( p_port_lid_tbl, lid, NULL );
+      p_mgr->p_subn->subnet_initialization_error = TRUE;
+   }
+
+   cl_ptr_vector_destroy( &ref_port_lid_tbl );
+   OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_state_mgr_process(
+   IN osm_state_mgr_t * const p_mgr,
+   IN osm_signal_t signal )
+{
+   ib_api_status_t status;
+   osm_remote_sm_t *p_remote_sm;
+   osm_signal_t tmp_signal;
+
+   CL_ASSERT( p_mgr );
+
+   OSM_LOG_ENTER( p_mgr->p_log, osm_state_mgr_process );
+
+   /* if we are exiting do nothing */
+   if( osm_exit_flag )
+      signal = OSM_SIGNAL_NONE;
+
+   /*
+    * The state lock prevents many race conditions from screwing
+    * up the state transition process.  For example, if an function
+    * puts transactions on the wire, the state lock guarantees this
+    * loop will see the return code ("DONE PENDING") of the function
+    * before the "NO OUTSTANDING TRANSACTIONS" signal is asynchronously
+    * received.
+    */
+   cl_spinlock_acquire( &p_mgr->state_lock );
+
+   while( signal != OSM_SIGNAL_NONE )
+   {
+      if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+      {
+         osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+                  "osm_state_mgr_process: "
+                  "Received signal %s in state %s\n",
+                  osm_get_sm_signal_str( signal ),
+                  osm_get_sm_state_str( p_mgr->state ) );
+      }
+
+      /*
+       * If we're already sweeping and we get the signal to sweep,
+       * just ignore it harmlessly.
+       */
+      if( ( p_mgr->state != OSM_SM_STATE_IDLE ) &&
+          ( p_mgr->state != OSM_SM_STATE_STANDBY ) &&
+          ( signal == OSM_SIGNAL_SWEEP ) )
+      {
+         break;
+      }
+
+      switch ( p_mgr->state )
+      {
+      case OSM_SM_STATE_IDLE:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_SWEEP:
+            /*
+             * If the osm_sm_state_mgr is in INIT state - signal
+             * it with a INIT signal to move it to DISCOVERY state.
+             */
+            if( p_mgr->p_subn->sm_state == IB_SMINFO_STATE_INIT )
+               osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr,
+                                         OSM_SM_SIGNAL_INIT );
+
+            /*
+             * If we already have switches, then try a light sweep.
+             * Otherwise, this is probably our first discovery pass
+             * or we are connected in loopback. In both cases do a 
+             * heavy sweep.
+             * Note: If we are connected in loopback we want a heavy 
+             * sweep, since we will not be getting any traps if there is
+             * a lost connection.
+             */
+            /*  if we are in DISCOVERING state - this means it is either in 
+             *  initializing or wake up from STANDBY - run the heavy sweep */
+            if( cl_qmap_count( &p_mgr->p_subn->sw_guid_tbl ) &&
+                p_mgr->p_subn->sm_state != IB_SMINFO_STATE_DISCOVERING &&
+                p_mgr->p_subn->opt.force_heavy_sweep == FALSE &&
+                p_mgr->p_subn->force_immediate_heavy_sweep == FALSE &&
+                p_mgr->p_subn->force_delayed_heavy_sweep == FALSE &&
+                p_mgr->p_subn->subnet_initialization_error == FALSE )
+            {
+               if( __osm_state_mgr_light_sweep_start( p_mgr ) == IB_SUCCESS )
+               {
+                  p_mgr->state = OSM_SM_STATE_SWEEP_LIGHT;
+               }
+            }
+            else
+            {
+               /* First of all - if force_immediate_heavy_sweep is TRUE then
+                * need to unset it */
+               p_mgr->p_subn->force_immediate_heavy_sweep = FALSE;
+               /* If force_delayed_heavy_sweep is TRUE then
+                * need to unset it */
+               p_mgr->p_subn->force_delayed_heavy_sweep = FALSE;
+               /* If subnet_initialization_error is TRUE then
+                * need to unset it. */
+               p_mgr->p_subn->subnet_initialization_error = FALSE;
+
+               /* rescan configuration updates */
+               osm_subn_rescan_conf_file(&p_mgr->p_subn->opt);
+
+               status = __osm_state_mgr_sweep_hop_0( p_mgr );
+               if( status == IB_SUCCESS )
+               {
+                  p_mgr->state = OSM_SM_STATE_SWEEP_HEAVY_SELF;
+               }
+            }
+            signal = OSM_SIGNAL_NONE;
+            break;
+
+         case OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST:
+            p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST;
+            signal = OSM_SIGNAL_IDLE_TIME_PROCESS;
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_PROCESS_REQUEST:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_IDLE_TIME_PROCESS:
+            signal = __process_idle_time_queue_start( p_mgr );
+            switch ( signal )
+            {
+            case OSM_SIGNAL_NONE:
+               p_mgr->state = OSM_SM_STATE_IDLE;
+               break;
+
+            case OSM_SIGNAL_DONE_PENDING:
+               p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST_WAIT;
+               signal = OSM_SIGNAL_NONE;
+               break;
+
+            case OSM_SIGNAL_DONE:
+               p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST_DONE;
+               break;
+
+            default:
+               __osm_state_mgr_signal_error( p_mgr, signal );
+               signal = OSM_SIGNAL_NONE;
+               break;
+            }
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_PROCESS_REQUEST_WAIT:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+            p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST_DONE;
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_PROCESS_REQUEST_DONE:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+         case OSM_SIGNAL_DONE:
+            /* CALL the done function */
+            __process_idle_time_queue_done( p_mgr );
+
+            /*
+             * Set the signal to OSM_SIGNAL_IDLE_TIME_PROCESS
+             * so that the next element in the queue gets processed
+             */
+
+            signal = OSM_SIGNAL_IDLE_TIME_PROCESS;
+            p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST;
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_SWEEP_LIGHT:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_LIGHT_SWEEP_FAIL:
+         case OSM_SIGNAL_CHANGE_DETECTED:
+            /*
+             * Nothing else to do yet except change state.
+             */
+            p_mgr->state = OSM_SM_STATE_SWEEP_LIGHT_WAIT;
+            signal = OSM_SIGNAL_NONE;
+            break;
+
+         case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+            /*
+             * No change was detected on the subnet.
+             * We can return to the idle state.
+             */
+            __osm_state_mgr_light_sweep_done_msg( p_mgr );
+            p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST;
+            signal = OSM_SIGNAL_IDLE_TIME_PROCESS;
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_SWEEP_LIGHT_WAIT:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_LIGHT_SWEEP_FAIL:
+         case OSM_SIGNAL_CHANGE_DETECTED:
+            /*
+             * Nothing to do here. One subnet change typcially
+             * begets another.... But needs to wait for all transactions to
+             * complete
+             */
+            break;
+
+         case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+            /*
+             * A change was detected on the subnet.
+             * Initiate a heavy sweep.
+             */
+            if( __osm_state_mgr_sweep_hop_0( p_mgr ) == IB_SUCCESS )
+            {
+               p_mgr->state = OSM_SM_STATE_SWEEP_HEAVY_SELF;
+            }
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            break;
+         }
+         signal = OSM_SIGNAL_NONE;
+         break;
+
+      case OSM_SM_STATE_SWEEP_HEAVY_SELF:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_CHANGE_DETECTED:
+            /*
+             * Nothing to do here. One subnet change typcially
+             * begets another.... But needs to wait for all transactions
+             */
+            signal = OSM_SIGNAL_NONE;
+            break;
+
+         case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+            if( __osm_state_mgr_is_sm_port_down( p_mgr ) == TRUE )
+            {
+               __osm_state_mgr_sm_port_down_msg( p_mgr );
+
+               /* Run the drop manager - we want to clear all records */
+               osm_drop_mgr_process( p_mgr->p_drop_mgr );
+
+               /* Move to DISCOVERING state */
+               osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr,
+                                         OSM_SM_SIGNAL_DISCOVER );
+
+               p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST;
+               signal = OSM_SIGNAL_IDLE_TIME_PROCESS;
+            }
+            else
+            {
+               if( __osm_state_mgr_sweep_hop_1( p_mgr ) == IB_SUCCESS )
+               {
+                  p_mgr->state = OSM_SM_STATE_SWEEP_HEAVY_SUBNET;
+               }
+               signal = OSM_SIGNAL_NONE;
+            }
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+         /*
+          * There is no 'OSM_SM_STATE_SWEEP_HEAVY_WAIT' state since we
+          * know that there are outstanding transactions on the wire already...
+          */
+      case OSM_SM_STATE_SWEEP_HEAVY_SUBNET:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_CHANGE_DETECTED:
+            /*
+             * Nothing to do here. One subnet change typically
+             * begets another....
+             */
+            signal = OSM_SIGNAL_NONE;
+            break;
+
+         case OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED:
+            p_mgr->state = OSM_SM_STATE_MASTER_OR_HIGHER_SM_DETECTED;
+            break;
+
+         case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+            __osm_state_mgr_sweep_heavy_done_msg( p_mgr );
+
+            /* If we are MASTER - get the highest remote_sm, and
+             * see if it is higher than our local sm. If
+             */
+            if( p_mgr->p_subn->sm_state == IB_SMINFO_STATE_MASTER )
+            {
+               p_remote_sm = __osm_state_mgr_get_highest_sm( p_mgr );
+               if( p_remote_sm != NULL )
+               {
+                  /*  need to handover the mastership 
+                   * to the remote sm, and move to standby */
+                  __osm_state_mgr_send_handover( p_mgr, p_remote_sm );
+                  osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr,
+                                            OSM_SM_SIGNAL_HANDOVER_SENT );
+                  p_mgr->state = OSM_SM_STATE_STANDBY;
+                  signal = OSM_SIGNAL_NONE;
+                  break;
+               }
+               else
+               {
+                  /* We are the highest sm - check to see if there is
+                   * a remote SM that is in master state. */
+                  p_remote_sm = __osm_state_mgr_exists_other_master_sm( p_mgr );
+                  if( p_remote_sm != NULL )
+                  {
+                     /* There is a remote SM that is master. 
+                      * need to wait for that SM to relinquish control 
+                      * of its portion of the subnet. C14-60.
+                      * Also - need to start polling on that SM. */
+                     p_mgr->p_sm_state_mgr->p_polling_sm = p_remote_sm;
+                     osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr,
+                                               OSM_SM_SIGNAL_WAIT_FOR_HANDOVER );
+                     p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST;
+                     signal = OSM_SIGNAL_IDLE_TIME_PROCESS;
+                     break;
+                  }
+               }
+            }
+            
+            /*  Need to continue with lid assignment */
+            osm_drop_mgr_process( p_mgr->p_drop_mgr );
+            
+            p_mgr->state = OSM_SM_STATE_SET_PKEY;
+
+            /*
+             * If we are not MASTER already - this means that we are
+             * in discovery state. call osm_sm_state_mgr with signal
+             * DISCOVERY_COMPLETED
+             */
+            if( p_mgr->p_subn->sm_state == IB_SMINFO_STATE_DISCOVERING )
+               osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr,
+                                         OSM_SM_SIGNAL_DISCOVERY_COMPLETED );
+
+            /* the returned signal might be DONE or DONE_PENDING */
+            signal = osm_pkey_mgr_process( p_mgr->p_subn->p_osm );
+
+            /* the returned signal is always DONE */
+            tmp_signal = osm_qos_setup(p_mgr->p_subn->p_osm);
+
+            if (tmp_signal == OSM_SIGNAL_DONE_PENDING)
+               signal = OSM_SIGNAL_DONE_PENDING;
+
+            /* try to restore SA DB (this should be before lid_mgr
+               because we may want to disable clients reregistration
+               when SA DB is restored) */
+            osm_sa_db_file_load(p_mgr->p_subn->p_osm);
+
+            break;
+
+         default:
+           __osm_state_mgr_signal_error( p_mgr, signal );
+           signal = OSM_SIGNAL_NONE;
+           break;
+         }
+         break;
+
+      case OSM_SM_STATE_SET_PKEY:
+        switch ( signal )
+        {
+        case OSM_SIGNAL_DONE:
+          p_mgr->state = OSM_SM_STATE_SET_PKEY_DONE;
+          break;
+
+        case OSM_SIGNAL_DONE_PENDING:
+          /*
+           * There are outstanding transactions, so we
+           * must wait for the wire to clear.
+           */
+          p_mgr->state = OSM_SM_STATE_SET_PKEY_WAIT;
+          signal = OSM_SIGNAL_NONE;
+          break;
+          
+        default:
+          __osm_state_mgr_signal_error( p_mgr, signal );
+          signal = OSM_SIGNAL_NONE;
+          break;
+        }
+        break;
+        
+      case OSM_SM_STATE_SET_PKEY_WAIT:
+        switch ( signal )
+        {
+        case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+          p_mgr->state = OSM_SM_STATE_SET_PKEY_DONE;
+          break;
+          
+        default:
+          __osm_state_mgr_signal_error( p_mgr, signal );
+          signal = OSM_SIGNAL_NONE;
+          break;
+        }
+        break;
+        
+      case OSM_SM_STATE_SET_PKEY_DONE:
+        switch ( signal )
+        {
+        case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+        case OSM_SIGNAL_DONE:
+          p_mgr->state = OSM_SM_STATE_SET_SM_UCAST_LID;
+            signal = osm_lid_mgr_process_sm( p_mgr->p_lid_mgr );
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_SET_SM_UCAST_LID:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_DONE:
+            p_mgr->state = OSM_SM_STATE_SET_SM_UCAST_LID_DONE;
+            break;
+
+         case OSM_SIGNAL_DONE_PENDING:
+            /*
+             * There are outstanding transactions, so we
+             * must wait for the wire to clear.
+             */
+            p_mgr->state = OSM_SM_STATE_SET_SM_UCAST_LID_WAIT;
+            signal = OSM_SIGNAL_NONE;
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_SET_SM_UCAST_LID_WAIT:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+            p_mgr->state = OSM_SM_STATE_SET_SM_UCAST_LID_DONE;
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_SET_SM_UCAST_LID_DONE:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+         case OSM_SIGNAL_DONE:
+            /* If we run single step we have already done this */
+            if( p_mgr->state_step_mode != OSM_STATE_STEP_TAKE_ONE )
+            {
+               __osm_state_mgr_set_sm_lid_done_msg( p_mgr );
+               __osm_state_mgr_notify_lid_change( p_mgr );
+            }
+
+            /* Break on single step mode - if not continuous */
+            if( p_mgr->state_step_mode == OSM_STATE_STEP_BREAK )
+            {
+               p_mgr->next_stage_signal = signal;
+               signal = OSM_SIGNAL_NONE;
+               break;
+            }
+
+            p_mgr->state = OSM_SM_STATE_SET_SUBNET_UCAST_LIDS;
+            signal = osm_lid_mgr_process_subnet( p_mgr->p_lid_mgr );
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+
+      case OSM_SM_STATE_SET_SUBNET_UCAST_LIDS:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_DONE:
+            /*
+             * The LID Manager is done processing.
+             * There are no outstanding transactions, so we
+             * can move on to configuring the forwarding tables.
+             */
+            p_mgr->state = OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_DONE;
+            break;
+
+         case OSM_SIGNAL_DONE_PENDING:
+            /*
+             * The LID Manager is done processing.
+             * There are outstanding transactions, so we
+             * must wait for the wire to clear.
+             */
+            p_mgr->state = OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_WAIT;
+            signal = OSM_SIGNAL_NONE;
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+         /*
+          * In this state, the Unicast Manager has completed processing,
+          * but there are still transactions on the wire.  Therefore,
+          * wait here until the wire clears.
+          */
+      case OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_WAIT:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+            /*
+             * The LID Manager is done processing.
+             * There are no outstanding transactions, so we
+             * can move on to configuring the forwarding tables.
+             */
+            p_mgr->state = OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_DONE;
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_DONE:
+
+         switch ( signal )
+         {
+         case OSM_SIGNAL_DONE:
+         case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+            /* At this point we need to check the consistency of 
+             * the port_lid_tbl under the subnet. There might be
+             * errors in it if PortInfo Set reqeusts didn't reach 
+             * their destination. */
+            __osm_state_mgr_check_tbl_consistency( p_mgr );
+
+            /* If we run single step we have already done this */
+            if( p_mgr->state_step_mode != OSM_STATE_STEP_TAKE_ONE )
+               __osm_state_mgr_lid_assign_msg( p_mgr );
+
+            /* Break on single step mode - just before taking next step */
+            if( p_mgr->state_step_mode == OSM_STATE_STEP_BREAK )
+            {
+               p_mgr->next_stage_signal = signal;
+               signal = OSM_SIGNAL_NONE;
+               break;
+            }
+
+            /*
+             * OK, the wire is clear, so proceed with
+             * unicast forwarding table configuration.
+             * First - send trap 64 on newly discovered endports
+             */
+            __osm_state_mgr_report_new_ports( p_mgr );
+
+            p_mgr->state = OSM_SM_STATE_SET_UCAST_TABLES;
+            signal = osm_ucast_mgr_process( p_mgr->p_ucast_mgr );
+
+            /* Break on single step mode */
+            if( p_mgr->state_step_mode != OSM_STATE_STEP_CONTINUOUS )
+            {
+               p_mgr->next_stage_signal = signal;
+               signal = OSM_SIGNAL_NONE;
+            }
+
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_SET_UCAST_TABLES:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_DONE:
+            p_mgr->state = OSM_SM_STATE_SET_UCAST_TABLES_DONE;
+            break;
+
+         case OSM_SIGNAL_DONE_PENDING:
+            /*
+             * The Unicast Manager is done processing.
+             * There are outstanding transactions, so we
+             * must wait for the wire to clear.
+             */
+            p_mgr->state = OSM_SM_STATE_SET_UCAST_TABLES_WAIT;
+            signal = OSM_SIGNAL_NONE;
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_SET_UCAST_TABLES_WAIT:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+            p_mgr->state = OSM_SM_STATE_SET_UCAST_TABLES_DONE;
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_SET_UCAST_TABLES_DONE:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+         case OSM_SIGNAL_DONE:
+            /* we are done setting all LFTs so clear the ignore existing.
+             * From now on, as long as we are still master, we want to 
+             * take into account these lfts. */
+            p_mgr->p_subn->ignore_existing_lfts = FALSE;
+
+            /* If we run single step we have already done this */
+            if( p_mgr->state_step_mode != OSM_STATE_STEP_TAKE_ONE )
+               __osm_state_mgr_switch_config_msg( p_mgr );
+
+            /* Break on single step mode - just before taking next step */
+            if( p_mgr->state_step_mode == OSM_STATE_STEP_BREAK )
+            {
+               p_mgr->next_stage_signal = signal;
+               signal = OSM_SIGNAL_NONE;
+               break;
+            }
+
+            if( !p_mgr->p_subn->opt.disable_multicast )
+            {
+               p_mgr->state = OSM_SM_STATE_SET_MCAST_TABLES;
+               signal = osm_mcast_mgr_process( p_mgr->p_mcast_mgr );
+            }
+            else
+            {
+               p_mgr->state = OSM_SM_STATE_SET_LINK_PORTS;
+               signal = osm_link_mgr_process( p_mgr->p_link_mgr,
+                                              IB_LINK_NO_CHANGE );
+            }
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_SET_MCAST_TABLES:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_DONE:
+            p_mgr->state = OSM_SM_STATE_SET_MCAST_TABLES_DONE;
+            break;
+
+         case OSM_SIGNAL_DONE_PENDING:
+            /*
+             * The Multicast Manager is done processing.
+             * There are outstanding transactions, so we
+             * must wait for the wire to clear.
+             */
+            p_mgr->state = OSM_SM_STATE_SET_MCAST_TABLES_WAIT;
+            signal = OSM_SIGNAL_NONE;
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_SET_MCAST_TABLES_WAIT:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+            p_mgr->state = OSM_SM_STATE_SET_MCAST_TABLES_DONE;
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_SET_MCAST_TABLES_DONE:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+         case OSM_SIGNAL_DONE:
+            /* If we run single step we have already done this */
+            if( p_mgr->state_step_mode != OSM_STATE_STEP_TAKE_ONE )
+               __osm_state_mgr_multicast_config_msg( p_mgr );
+
+            /* Break on single step mode - just before taking next step */
+            if( p_mgr->state_step_mode == OSM_STATE_STEP_BREAK )
+            {
+               p_mgr->next_stage_signal = signal;
+               signal = OSM_SIGNAL_NONE;
+               break;
+            }
+
+            p_mgr->state = OSM_SM_STATE_SET_LINK_PORTS;
+            signal = osm_link_mgr_process( p_mgr->p_link_mgr,
+                                           IB_LINK_NO_CHANGE );
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+         /*
+          * The LINK_PORTS state is required since we can not count on
+          * the port state change MADs to succeed. This is an artifact
+          * of the spec defining state change from state X to state X
+          * as an error. The hardware then is not required to process
+          * other parameters provided by the Set(PortInfo) Packet.
+          */
+      case OSM_SM_STATE_SET_LINK_PORTS:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_DONE:
+            p_mgr->state = OSM_SM_STATE_SET_LINK_PORTS_DONE;
+            break;
+
+         case OSM_SIGNAL_DONE_PENDING:
+            /*
+             * The Link Manager is done processing.
+             * There are outstanding transactions, so we
+             * must wait for the wire to clear.
+             */
+            p_mgr->state = OSM_SM_STATE_SET_LINK_PORTS_WAIT;
+            signal = OSM_SIGNAL_NONE;
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_SET_LINK_PORTS_WAIT:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+            p_mgr->state = OSM_SM_STATE_SET_LINK_PORTS_DONE;
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_SET_LINK_PORTS_DONE:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+         case OSM_SIGNAL_DONE:
+
+            __osm_state_mgr_links_ports_msg( p_mgr );
+
+            p_mgr->state = OSM_SM_STATE_SET_ARMED;
+            signal = osm_link_mgr_process( p_mgr->p_link_mgr, IB_LINK_ARMED );
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_SET_ARMED:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_DONE:
+            p_mgr->state = OSM_SM_STATE_SET_ARMED_DONE;
+            break;
+
+         case OSM_SIGNAL_DONE_PENDING:
+            /*
+             * The Link Manager is done processing.
+             * There are outstanding transactions, so we
+             * must wait for the wire to clear.
+             */
+            p_mgr->state = OSM_SM_STATE_SET_ARMED_WAIT;
+            signal = OSM_SIGNAL_NONE;
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_SET_ARMED_WAIT:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+            p_mgr->state = OSM_SM_STATE_SET_ARMED_DONE;
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_SET_ARMED_DONE:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+         case OSM_SIGNAL_DONE:
+
+            /* If we run single step we have already done this */
+            if( p_mgr->state_step_mode != OSM_STATE_STEP_TAKE_ONE )
+               __osm_state_mgr_links_armed_msg( p_mgr );
+
+            /* Break on single step mode - just before taking next step */
+            if( p_mgr->state_step_mode == OSM_STATE_STEP_BREAK )
+            {
+               p_mgr->next_stage_signal = signal;
+               signal = OSM_SIGNAL_NONE;
+               break;
+            }
+
+            p_mgr->state = OSM_SM_STATE_SET_ACTIVE;
+            signal = osm_link_mgr_process( p_mgr->p_link_mgr,
+                                           IB_LINK_ACTIVE );
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_SET_ACTIVE:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_DONE:
+            /*
+             * Don't change the signal, just the state.
+             */
+            p_mgr->state = OSM_SM_STATE_SUBNET_UP;
+            break;
+
+         case OSM_SIGNAL_DONE_PENDING:
+            /*
+             * The Link Manager is done processing.
+             * There are outstanding transactions, so we
+             * must wait for the wire to clear.
+             */
+            p_mgr->state = OSM_SM_STATE_SET_ACTIVE_WAIT;
+            signal = OSM_SIGNAL_NONE;
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_SET_ACTIVE_WAIT:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+            /*
+             * Don't change the signal, just the state.
+             */
+            p_mgr->state = OSM_SM_STATE_SUBNET_UP;
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_SUBNET_UP:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+         case OSM_SIGNAL_DONE:
+            /*
+             * The sweep completed!
+             */
+
+            /* in any case we zero this flag */
+            p_mgr->p_subn->coming_out_of_standby = FALSE;
+
+            /* If there were errors - then the subnet is not really up */
+            if( p_mgr->p_subn->subnet_initialization_error == TRUE )
+            {
+               __osm_state_mgr_init_errors_msg( p_mgr );
+            }
+            else
+            {
+               /* The subnet is up correctly - set the first_time_master_sweep flag 
+                * (if it is on) to FALSE. */
+               if( p_mgr->p_subn->first_time_master_sweep == TRUE )
+               {
+                  p_mgr->p_subn->first_time_master_sweep = FALSE;
+               }
+
+               __osm_topology_file_create( p_mgr );
+               __osm_state_mgr_report( p_mgr );
+               __osm_state_mgr_up_msg( p_mgr );
+
+              if( osm_log_is_active(p_mgr->p_log, OSM_LOG_VERBOSE) )
+                  osm_sa_db_file_dump(p_mgr->p_subn->p_osm);
+            }
+            p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST;
+            signal = OSM_SIGNAL_IDLE_TIME_PROCESS;
+
+            /*
+             * Finally signal the subnet up event
+             */
+            status = cl_event_signal( p_mgr->p_subnet_up_event );
+            if( status != IB_SUCCESS )
+            {
+               osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+                        "osm_state_mgr_process: ERR 3319: "
+                        "Invalid SM state %u\n", p_mgr->state );
+            }
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         break;
+
+      case OSM_SM_STATE_MASTER_OR_HIGHER_SM_DETECTED:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_CHANGE_DETECTED:
+            /*
+             * Nothing to do here. One subnet change typically
+             * begets another....
+             */
+            break;
+
+         case OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED:
+            /*
+             * If we lost once, we might lose again. Nothing to do.
+             */
+            break;
+
+         case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+            p_mgr->state = OSM_SM_STATE_STANDBY;
+            /*
+             * Call the sm_state_mgr with signal
+             * MASTER_OR_HIGHER_SM_DETECTED_DONE
+             */
+            osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr,
+                                      OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED_DONE );
+            __osm_state_mgr_standby_msg( p_mgr );
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            break;
+         }
+         signal = OSM_SIGNAL_NONE;
+         break;
+
+      case OSM_SM_STATE_STANDBY:
+         switch ( signal )
+         {
+         case OSM_SIGNAL_EXIT_STBY:
+            /*
+             * Need to force re-write of sm_base_lid to all ports
+             * to do that we want all the ports to be considered
+             * foriegn
+             */
+            signal = OSM_SIGNAL_SWEEP;
+            __osm_state_mgr_clean_known_lids( p_mgr );
+            p_mgr->state = OSM_SM_STATE_IDLE;
+            break;
+
+         case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+            /*
+             * Nothing to do here - need to stay at this state
+             */
+            signal = OSM_SIGNAL_NONE;
+            break;
+
+         default:
+            __osm_state_mgr_signal_error( p_mgr, signal );
+            signal = OSM_SIGNAL_NONE;
+            break;
+         }
+         /* stay with the same signal - so we can start the sweep */
+         break;
+
+      default:
+         CL_ASSERT( FALSE );
+         osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+                  "osm_state_mgr_process: ERR 3320: "
+                  "Invalid SM state %u\n", p_mgr->state );
+         p_mgr->state = OSM_SM_STATE_IDLE;
+         signal = OSM_SIGNAL_NONE;
+         break;
+      }
+
+      /* if we got a signal to force immediate heavy sweep in the middle of the sweep -
+       * try another sweep. */
+      if( ( p_mgr->p_subn->force_immediate_heavy_sweep ) &&
+          ( p_mgr->state == OSM_SM_STATE_IDLE ) )
+      {
+         signal = OSM_SIGNAL_SWEEP;
+      }
+      /* if we got errors during the initialization in the middle of the sweep -
+       * try another sweep. */
+      if( ( p_mgr->p_subn->subnet_initialization_error ) &&
+          ( p_mgr->state == OSM_SM_STATE_IDLE ) )
+      {
+         signal = OSM_SIGNAL_SWEEP;
+      }
+
+      /*
+       * for single step mode - some stages need to break only
+       * after evaluating a single step.
+       * For those we track the fact we have already performed
+       * a single loop
+       */
+      if( p_mgr->state_step_mode == OSM_STATE_STEP_TAKE_ONE )
+         p_mgr->state_step_mode = OSM_STATE_STEP_BREAK;
+   }
+
+   cl_spinlock_release( &p_mgr->state_lock );
+
+   OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_state_mgr_process_idle(
+   IN osm_state_mgr_t * const p_mgr,
+   IN osm_pfn_start_t pfn_start,
+   IN osm_pfn_done_t pfn_done,
+   void *context1,
+   void *context2 )
+{
+   osm_idle_item_t *p_idle_item;
+
+   OSM_LOG_ENTER( p_mgr->p_log, osm_state_mgr_process_idle );
+
+   p_idle_item = malloc( sizeof( osm_idle_item_t ) );
+   if( p_idle_item == NULL )
+   {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "osm_state_mgr_process_idle: ERR 3321: "
+               "insufficient memory\n" );
+      return IB_ERROR;
+   }
+
+   memset( p_idle_item, 0, sizeof( osm_idle_item_t ) );
+   p_idle_item->pfn_start = pfn_start;
+   p_idle_item->pfn_done = pfn_done;
+   p_idle_item->context1 = context1;
+   p_idle_item->context2 = context2;
+
+   cl_spinlock_acquire( &p_mgr->idle_lock );
+   cl_qlist_insert_tail( &p_mgr->idle_time_list, &p_idle_item->list_item );
+   cl_spinlock_release( &p_mgr->idle_lock );
+
+   osm_state_mgr_process( p_mgr, OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST );
+
+   OSM_LOG_EXIT( p_mgr->p_log );
+
+   return IB_SUCCESS;
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_state_mgr_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_state_mgr_ctrl.c
new file mode 100644 (file)
index 0000000..36fd3c6
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_state_mgr_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_state_mgr_ctrl_t.
+ * This object represents the State Manager Controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_state_mgr_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_state_mgr_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+    osm_state_mgr_process( ((osm_state_mgr_ctrl_t*)context)->p_mgr,
+               (osm_signal_t)(p_data) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_state_mgr_ctrl_construct(
+  IN osm_state_mgr_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_state_mgr_ctrl_destroy(
+  IN osm_state_mgr_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_state_mgr_ctrl_init(
+  IN osm_state_mgr_ctrl_t* const p_ctrl,
+  IN osm_state_mgr_t* const p_mgr,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_state_mgr_ctrl_init );
+
+  osm_state_mgr_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+
+  p_ctrl->p_mgr = p_mgr;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_NO_SMPS_OUTSTANDING,
+    __osm_state_mgr_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_state_mgr_ctrl_init: ERR 3401: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_subnet.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_subnet.c
new file mode 100644 (file)
index 0000000..71c5b3d
--- /dev/null
@@ -0,0 +1,1272 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_subnet.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_subn_t.
+ * This object represents an IBA subnet.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.9 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <stdio.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_remote_sm.h>
+#include <opensm/osm_partition.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_multicast.h>
+#include <opensm/osm_inform.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_subn_construct(
+  IN osm_subn_t* const p_subn )
+{
+  memset( p_subn, 0, sizeof(*p_subn) );
+  cl_ptr_vector_construct( &p_subn->node_lid_tbl );
+  cl_ptr_vector_construct( &p_subn->port_lid_tbl );
+  cl_qmap_init( &p_subn->sw_guid_tbl );
+  cl_qmap_init( &p_subn->node_guid_tbl );
+  cl_qmap_init( &p_subn->port_guid_tbl );
+  cl_qmap_init( &p_subn->sm_guid_tbl );
+  cl_qlist_init( &p_subn->sa_sr_list );
+  cl_qlist_init( &p_subn->sa_infr_list );
+  cl_qmap_init( &p_subn->rtr_guid_tbl );
+  cl_qmap_init( &p_subn->prtn_pkey_tbl );
+  cl_qmap_init( &p_subn->mgrp_mlid_tbl );
+  cl_list_construct( &p_subn->new_ports_list );
+  cl_list_init( &p_subn->new_ports_list, 10 );
+  cl_list_construct( &p_subn->light_sweep_physp_list );
+  cl_list_init( &p_subn->light_sweep_physp_list, 5 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_subn_destroy(
+  IN osm_subn_t* const p_subn )
+{
+  osm_node_t      *p_node, *p_next_node;
+  osm_port_t      *p_port, *p_next_port;
+  osm_switch_t    *p_sw,   *p_next_sw;
+  osm_remote_sm_t *p_rsm,  *p_next_rsm;  
+  osm_prtn_t      *p_prtn, *p_next_prtn;
+  osm_mgrp_t      *p_mgrp, *p_next_mgrp;
+  osm_infr_t      *p_infr, *p_next_infr;
+
+  /* it might be a good idea to de-allocate all known objects */
+  p_next_node = (osm_node_t*)cl_qmap_head( &p_subn->node_guid_tbl );
+  while( p_next_node != (osm_node_t*)cl_qmap_end( &p_subn->node_guid_tbl ) )
+  {
+    p_node = p_next_node;
+    p_next_node = (osm_node_t*)cl_qmap_next( &p_node->map_item );
+    osm_node_delete( &p_node );
+  }
+
+  cl_ptr_vector_destroy( &p_subn->node_lid_tbl );
+
+  p_next_port = (osm_port_t*)cl_qmap_head( &p_subn->port_guid_tbl );
+  while( p_next_port != (osm_port_t*)cl_qmap_end( &p_subn->port_guid_tbl ) )
+  {
+    p_port = p_next_port;
+    p_next_port = (osm_port_t*)cl_qmap_next( &p_port->map_item );
+    osm_port_delete( &p_port );
+  }
+
+  p_next_sw = (osm_switch_t*)cl_qmap_head( &p_subn->sw_guid_tbl );
+  while( p_next_sw != (osm_switch_t*)cl_qmap_end( &p_subn->sw_guid_tbl ) )
+  {
+    p_sw = p_next_sw;
+    p_next_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item );
+    osm_switch_delete( &p_sw );
+  }
+
+  p_next_rsm = (osm_remote_sm_t*)cl_qmap_head( &p_subn->sm_guid_tbl );
+  while( p_next_rsm != (osm_remote_sm_t*)cl_qmap_end( &p_subn->sm_guid_tbl ) )
+  {
+    p_rsm = p_next_rsm;
+    p_next_rsm = (osm_remote_sm_t*)cl_qmap_next( &p_rsm->map_item );
+    free( p_rsm );
+  }
+
+  p_next_prtn = (osm_prtn_t*)cl_qmap_head( &p_subn->prtn_pkey_tbl );
+  while( p_next_prtn != (osm_prtn_t*)cl_qmap_end( &p_subn->prtn_pkey_tbl ) )
+  {
+    p_prtn = p_next_prtn;
+    p_next_prtn = (osm_prtn_t*)cl_qmap_next( &p_prtn->map_item );
+    osm_prtn_delete( &p_prtn );
+  }
+
+  p_next_mgrp = (osm_mgrp_t*)cl_qmap_head( &p_subn->mgrp_mlid_tbl );
+  while( p_next_mgrp != (osm_mgrp_t*)cl_qmap_end( &p_subn->mgrp_mlid_tbl ) )
+  {
+    p_mgrp = p_next_mgrp;
+    p_next_mgrp = (osm_mgrp_t*)cl_qmap_next( &p_mgrp->map_item );
+    osm_mgrp_destroy( p_mgrp );
+  }
+
+  p_next_infr = (osm_infr_t*)cl_qlist_head( &p_subn->sa_infr_list );
+  while (p_next_infr != (osm_infr_t*)cl_qlist_end( &p_subn->sa_infr_list ) )
+  {
+    p_infr = p_next_infr;
+    p_next_infr = (osm_infr_t*)cl_qlist_next( &p_infr->list_item );
+    osm_infr_destroy( p_infr );
+  }
+
+  cl_list_remove_all( &p_subn->new_ports_list );
+  cl_list_destroy( &p_subn->new_ports_list );
+
+  cl_list_remove_all( &p_subn->light_sweep_physp_list );
+  cl_list_destroy( &p_subn->light_sweep_physp_list );
+
+  cl_ptr_vector_destroy( &p_subn->port_lid_tbl );
+  cl_map_remove_all(&(p_subn->opt.port_prof_ignore_guids));
+  cl_map_destroy(&(p_subn->opt.port_prof_ignore_guids));
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_subn_init(
+  IN osm_subn_t* const p_subn,
+  IN osm_opensm_t * const p_osm,
+  IN const osm_subn_opt_t* const p_opt )
+{
+  cl_status_t status;
+
+  p_subn->p_osm = p_osm;
+
+  status = cl_ptr_vector_init( &p_subn->node_lid_tbl,
+                               OSM_SUBNET_VECTOR_MIN_SIZE,
+                               OSM_SUBNET_VECTOR_GROW_SIZE );
+  if( status != CL_SUCCESS )
+    return( status );
+
+  status = cl_ptr_vector_init( &p_subn->port_lid_tbl,
+                               OSM_SUBNET_VECTOR_MIN_SIZE,
+                               OSM_SUBNET_VECTOR_GROW_SIZE );
+  if( status != CL_SUCCESS )
+    return( status );
+
+  status = cl_ptr_vector_set_capacity( &p_subn->node_lid_tbl,
+                                       OSM_SUBNET_VECTOR_CAPACITY );
+  if( status != CL_SUCCESS )
+    return( status );
+
+  status = cl_ptr_vector_set_capacity( &p_subn->port_lid_tbl,
+                                       OSM_SUBNET_VECTOR_CAPACITY );
+  if( status != CL_SUCCESS )
+    return( status );
+
+  /*
+    LID zero is not valid.  NULL out this entry for the
+    convenience of other code.
+  */
+  cl_ptr_vector_set( &p_subn->node_lid_tbl, 0, NULL );
+  cl_ptr_vector_set( &p_subn->port_lid_tbl, 0, NULL );
+
+  p_subn->opt = *p_opt;
+  p_subn->max_unicast_lid_ho = IB_LID_UCAST_END_HO;
+  p_subn->max_multicast_lid_ho = IB_LID_MCAST_END_HO;
+  p_subn->min_ca_mtu = IB_MAX_MTU;
+  p_subn->min_ca_rate = IB_MAX_RATE;
+
+  /* note that insert and remove are part of the port_profile thing */
+  cl_map_init(&(p_subn->opt.port_prof_ignore_guids), 10);
+
+  /* ignore_existing_lfts follows reassign_lfts on first sweep */
+  p_subn->ignore_existing_lfts = p_subn->opt.reassign_lfts;
+
+  /* we assume master by default - so we only need to set it true if STANDBY */
+  p_subn->coming_out_of_standby = FALSE;
+
+  return( IB_SUCCESS );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_get_gid_by_mad_addr(
+  IN osm_log_t*            p_log,
+  IN const osm_subn_t     *p_subn,
+  IN const osm_mad_addr_t *p_mad_addr,
+  OUT ib_gid_t            *p_gid)
+{
+  const cl_ptr_vector_t*  p_tbl;
+  const osm_port_t*       p_port = NULL;
+  const osm_physp_t*      p_physp = NULL;
+
+  if ( p_gid == NULL ) 
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_get_gid_by_mad_addr: ERR 7505: "
+             "Provided output GID is NULL\n");
+    return(IB_INVALID_PARAMETER);
+  }
+
+  /* Find the port gid of the request in the subnet */
+  p_tbl = &p_subn->port_lid_tbl;
+
+  CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 );
+
+  if ((uint16_t)cl_ptr_vector_get_size(p_tbl) > 
+      cl_ntoh16(p_mad_addr->dest_lid))
+  {
+    p_port = cl_ptr_vector_get( p_tbl, cl_ntoh16(p_mad_addr->dest_lid) );
+    if ( p_port == NULL )
+    {
+      osm_log( p_log, OSM_LOG_DEBUG,
+               "osm_get_gid_by_mad_addr: "
+               "Did not find any port with LID: 0x%X\n",
+               cl_ntoh16(p_mad_addr->dest_lid)
+               );
+      return(IB_INVALID_PARAMETER);
+    }
+    p_physp = osm_port_get_phys_ptr( p_port, p_port->default_port_num);
+    p_gid->unicast.interface_id = p_physp->port_guid;
+    p_gid->unicast.prefix = p_subn->opt.subnet_prefix;
+  }
+  else
+  {
+    /* The dest_lid is not in the subnet table - this is an error */
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_get_gid_by_mad_addr: ERR 7501: "
+             "LID is out of range: 0x%X\n",
+             cl_ntoh16(p_mad_addr->dest_lid)
+             );
+    return(IB_INVALID_PARAMETER);
+  }
+
+  return( IB_SUCCESS );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_physp_t*
+osm_get_physp_by_mad_addr(
+  IN osm_log_t*            p_log,
+  IN const osm_subn_t     *p_subn,
+  IN osm_mad_addr_t       *p_mad_addr )
+{
+  const cl_ptr_vector_t*  p_port_lid_tbl;
+  osm_port_t*             p_port = NULL;
+  osm_physp_t*            p_physp = NULL;
+
+  /* Find the port gid of the request in the subnet */
+  p_port_lid_tbl = &p_subn->port_lid_tbl;
+
+  CL_ASSERT( cl_ptr_vector_get_size(p_port_lid_tbl) < 0x10000 );
+
+  if ((uint16_t)cl_ptr_vector_get_size(p_port_lid_tbl) >
+      cl_ntoh16(p_mad_addr->dest_lid))
+  {
+    p_port = cl_ptr_vector_get( p_port_lid_tbl, cl_ntoh16(p_mad_addr->dest_lid) );
+    if (p_port == NULL)
+    {
+      /* The port is not in the port_lid table - this is an error */
+      osm_log( p_log, OSM_LOG_ERROR,
+               "osm_get_physp_by_mad_addr: ERR 7502: "
+               "Cannot locate port object by lid: 0x%X\n",
+               cl_ntoh16(p_mad_addr->dest_lid)
+               );
+    
+      goto Exit;
+    }
+    p_physp = osm_port_get_phys_ptr( p_port, p_port->default_port_num);
+  }
+  else
+  {
+    /* The dest_lid is not in the subnet table - this is an error */
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_get_physp_by_mad_addr: ERR 7503: "
+             "Lid is out of range: 0x%X\n",
+             cl_ntoh16(p_mad_addr->dest_lid)
+             );
+  }
+
+ Exit:
+  return p_physp;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_port_t*
+osm_get_port_by_mad_addr(
+  IN osm_log_t*            p_log,
+  IN const osm_subn_t     *p_subn,
+  IN osm_mad_addr_t       *p_mad_addr )
+{
+  const cl_ptr_vector_t*  p_port_lid_tbl;
+  osm_port_t*             p_port = NULL;
+
+  /* Find the port gid of the request in the subnet */
+  p_port_lid_tbl = &p_subn->port_lid_tbl;
+
+  CL_ASSERT( cl_ptr_vector_get_size(p_port_lid_tbl) < 0x10000 );
+
+  if ((uint16_t)cl_ptr_vector_get_size(p_port_lid_tbl) > 
+      cl_ntoh16(p_mad_addr->dest_lid))
+  {
+    p_port = 
+      cl_ptr_vector_get( p_port_lid_tbl, cl_ntoh16(p_mad_addr->dest_lid) );
+  }
+  else
+  {
+    /* The dest_lid is not in the subnet table - this is an error */
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_get_port_by_mad_addr: ERR 7504: "
+             "Lid is out of range: 0x%X\n",
+             cl_ntoh16(p_mad_addr->dest_lid)
+             );
+  }
+
+  return p_port;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_switch_t *
+osm_get_switch_by_guid(
+  IN const osm_subn_t *p_subn,
+  IN uint64_t          guid)
+{
+  osm_switch_t *p_switch;
+
+  p_switch = (osm_switch_t*)cl_qmap_get( &(p_subn->sw_guid_tbl), guid );
+  if( p_switch == (osm_switch_t*)cl_qmap_end( &(p_subn->sw_guid_tbl)) )
+    p_switch = NULL;
+  return p_switch;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_node_t *
+osm_get_node_by_guid(
+  IN osm_subn_t const *p_subn,
+  IN uint64_t          guid)
+{
+  osm_node_t *p_node;
+
+  p_node = (osm_node_t*)cl_qmap_get( &(p_subn->node_guid_tbl), guid );
+  if( p_node == (osm_node_t*)cl_qmap_end( &(p_subn->node_guid_tbl)) )
+    p_node = NULL;
+  return p_node;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_port_t *
+osm_get_port_by_guid(
+       IN osm_subn_t const *p_subn,
+   IN uint64_t          guid)
+{
+  osm_port_t *p_port;
+
+  p_port = (osm_port_t*)cl_qmap_get( &(p_subn->port_guid_tbl), guid );
+  if( p_port == (osm_port_t*)cl_qmap_end( &(p_subn->port_guid_tbl)) )
+    p_port = NULL;
+  return p_port;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+subn_set_default_qos_options(
+  IN osm_qos_options_t *opt)
+{
+  opt->max_vls = 15;
+  opt->high_limit = 0;
+  opt->vlarb_high = "0:4,1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0,10:0,11:0,12:0,13:0,14:0";
+  opt->vlarb_low = "0:0,1:4,2:4,3:4,4:4,5:4,6:4,7:4,8:4,9:4,10:4,11:4,12:4,13:4,14:4";
+  opt->sl2vl = "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,7";
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_subn_set_default_opt(
+  IN osm_subn_opt_t* const p_opt )
+{
+  memset(p_opt, 0, sizeof(osm_subn_opt_t));
+  p_opt->guid = 0;
+  p_opt->m_key = OSM_DEFAULT_M_KEY;
+  p_opt->sm_key = OSM_DEFAULT_SM_KEY;
+  p_opt->subnet_prefix = IB_DEFAULT_SUBNET_PREFIX;
+  p_opt->m_key_lease_period = 0;
+  p_opt->sweep_interval = OSM_DEFAULT_SWEEP_INTERVAL_SECS;
+  p_opt->max_wire_smps = OSM_DEFAULT_SMP_MAX_ON_WIRE;
+  p_opt->console = FALSE;
+  p_opt->transaction_timeout = OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC;
+  /* by default we will consider waiting for 50x transaction timeout normal */
+  p_opt->max_msg_fifo_timeout = 50*OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC;
+  p_opt->sm_priority = OSM_DEFAULT_SM_PRIORITY;
+  p_opt->lmc = OSM_DEFAULT_LMC;
+  p_opt->lmc_esp0 = FALSE;
+  p_opt->max_op_vls = OSM_DEFAULT_MAX_OP_VLS;
+  p_opt->force_link_speed = 0;
+  p_opt->reassign_lids = FALSE;
+  p_opt->reassign_lfts = TRUE;
+  p_opt->ignore_other_sm = FALSE;
+  p_opt->single_thread = FALSE;
+  p_opt->no_multicast_option = FALSE;
+  p_opt->disable_multicast = FALSE;
+  p_opt->force_log_flush = FALSE;
+  p_opt->subnet_timeout = OSM_DEFAULT_SUBNET_TIMEOUT;
+  p_opt->packet_life_time = OSM_DEFAULT_SWITCH_PACKET_LIFE;
+  p_opt->vl_stall_count = OSM_DEFAULT_VL_STALL_COUNT;
+  p_opt->leaf_vl_stall_count = OSM_DEFAULT_LEAF_VL_STALL_COUNT;
+  p_opt->head_of_queue_lifetime = OSM_DEFAULT_HEAD_OF_QUEUE_LIFE;
+  p_opt->leaf_head_of_queue_lifetime = OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE;
+  p_opt->local_phy_errors_threshold = OSM_DEFAULT_ERROR_THRESHOLD;
+  p_opt->overrun_errors_threshold = OSM_DEFAULT_ERROR_THRESHOLD;
+  p_opt->sminfo_polling_timeout = OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS;
+  p_opt->polling_retry_number = OSM_SM_DEFAULT_POLLING_RETRY_NUMBER;
+  p_opt->force_heavy_sweep = FALSE;
+  p_opt->log_flags = 0;
+  p_opt->honor_guid2lid_file = FALSE;
+
+  p_opt->dump_files_dir = getenv("OSM_TMP_DIR");
+  if (!p_opt->dump_files_dir || !(*p_opt->dump_files_dir))
+    p_opt->dump_files_dir = OSM_DEFAULT_TMP_DIR;
+
+  p_opt->log_file = OSM_DEFAULT_LOG_FILE;
+  p_opt->log_max_size = 0;
+  p_opt->partition_config_file = OSM_DEFAULT_PARTITION_CONFIG_FILE;
+  p_opt->no_partition_enforcement = FALSE;
+  p_opt->no_qos = TRUE;
+  p_opt->accum_log_file = TRUE;
+  p_opt->port_profile_switch_nodes = FALSE;
+  p_opt->pfn_ui_pre_lid_assign = NULL;
+  p_opt->ui_pre_lid_assign_ctx = NULL;
+  p_opt->pfn_ui_mcast_fdb_assign = NULL;
+  p_opt->ui_mcast_fdb_assign_ctx = NULL;
+  p_opt->sweep_on_trap = TRUE;
+  p_opt->testability_mode = OSM_TEST_MODE_NONE;
+  p_opt->routing_engine_name = NULL;
+  p_opt->lid_matrix_dump_file = NULL;
+  p_opt->ucast_dump_file = NULL;
+  p_opt->updn_guid_file = NULL;
+  p_opt->sa_db_file = NULL;
+  p_opt->exit_on_fatal = TRUE;
+  p_opt->enable_quirks = FALSE;
+  p_opt->no_clients_rereg = FALSE;
+  subn_set_default_qos_options(&p_opt->qos_options);
+  subn_set_default_qos_options(&p_opt->qos_ca_options);
+  subn_set_default_qos_options(&p_opt->qos_sw0_options);
+  subn_set_default_qos_options(&p_opt->qos_swe_options);
+  subn_set_default_qos_options(&p_opt->qos_rtr_options);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline void
+__osm_subn_opts_unpack_net64(
+  IN char *p_req_key,
+  IN char *p_key,
+  IN char *p_val_str,
+  IN uint64_t *p_val)
+{
+  uint64_t val;
+  if (!strcmp(p_req_key, p_key))
+  {
+#if __WORDSIZE == 64
+    val = strtoul(p_val_str, NULL, 0);
+#else
+    val = strtoull(p_val_str, NULL, 0);
+#endif
+    if (cl_hton64(val) != *p_val)
+    {
+      char buff[128];
+      sprintf(buff, " Using Cached Option:%s = 0x%016" PRIx64 "\n",
+              p_key, val);
+      printf(buff);
+      cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
+      *p_val = cl_ntoh64(val);
+    }
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline void
+__osm_subn_opts_unpack_uint32(
+  IN char *p_req_key,
+  IN char *p_key,
+  IN char *p_val_str,
+  IN uint32_t *p_val)
+{
+  uint32_t val;
+  if (!strcmp(p_req_key, p_key))
+  {
+    val = strtoul(p_val_str, NULL, 0);
+    if (val != *p_val)
+    {
+      char buff[128];
+      sprintf(buff, " Using Cached Option:%s = %u\n",
+              p_key, val);
+      printf(buff);
+      cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
+      *p_val = val;
+    }
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline void
+__osm_subn_opts_unpack_net16(
+  IN char *p_req_key,
+  IN char *p_key,
+  IN char *p_val_str,
+  IN uint16_t *p_val)
+{
+  if (!strcmp(p_req_key, p_key))
+  {
+    uint32_t val;
+    val = strtoul(p_val_str, NULL, 0);
+    CL_ASSERT( val < 0x10000 );
+    if (cl_hton32(val) != *p_val) 
+    {
+      char buff[128];
+      sprintf(buff, " Using Cached Option:%s = 0x%04x\n",
+              p_key, val);
+      printf(buff);
+      cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
+      *p_val = cl_hton16((uint16_t)val);
+    }
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline void
+__osm_subn_opts_unpack_uint8(
+  IN char *p_req_key,
+  IN char *p_key,
+  IN char *p_val_str,
+  IN uint8_t *p_val)
+{
+  if (!strcmp(p_req_key, p_key))
+  {
+    uint32_t val;
+    val = strtoul(p_val_str, NULL, 0);
+    CL_ASSERT( val < 0x100 );
+    if (val != *p_val) 
+    {
+      char buff[128];
+      sprintf(buff, " Using Cached Option:%s = %u\n",
+              p_key, val);
+      printf(buff);
+      cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
+      *p_val = (uint8_t)val;
+    }
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline void
+__osm_subn_opts_unpack_boolean(
+  IN char *p_req_key,
+  IN char *p_key,
+  IN char *p_val_str,
+  IN boolean_t *p_val)
+{
+  if (!strcmp(p_req_key, p_key) && p_val_str)
+  {
+    boolean_t val;
+    if (strcmp("TRUE", p_val_str))
+      val = FALSE;
+    else
+      val = TRUE;
+    
+    if (val != *p_val) {
+      char buff[128];
+      sprintf(buff, " Using Cached Option:%s = %s\n",
+              p_key, p_val_str);
+      printf(buff);
+      cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
+      *p_val = val;
+    }
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline void
+__osm_subn_opts_unpack_charp(
+  IN char *p_req_key,
+  IN char *p_key,
+  IN char *p_val_str,  
+  IN char **p_val)
+{
+  if (!strcmp(p_req_key, p_key) && p_val_str)
+  {
+    if ((*p_val == NULL) || strcmp(p_val_str, *p_val))
+    {
+      char buff[128];
+      sprintf(buff, " Using Cached Option:%s = %s\n",
+              p_key, p_val_str);
+      printf(buff);
+      cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
+
+      /*
+        Ignore the possible memory leak here;
+        the pointer may be to a static default.
+      */
+      *p_val = (char *)malloc( strlen(p_val_str) +1 );
+      strcpy( *p_val, p_val_str);
+    }
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+subn_parse_qos_options(
+  IN const char *prefix,
+  IN char *p_key,
+  IN char *p_val_str,
+  IN osm_qos_options_t *opt)
+{
+  char name[256];
+
+  snprintf(name, sizeof(name), "%s_max_vls", prefix);
+  __osm_subn_opts_unpack_uint32(name, p_key, p_val_str, &opt->max_vls);
+  snprintf(name, sizeof(name), "%s_high_limit", prefix);
+  __osm_subn_opts_unpack_uint32(name, p_key, p_val_str, &opt->high_limit);
+  snprintf(name, sizeof(name), "%s_vlarb_high", prefix);
+  __osm_subn_opts_unpack_charp(name, p_key, p_val_str, &opt->vlarb_high);
+  snprintf(name, sizeof(name), "%s_vlarb_low", prefix);
+  __osm_subn_opts_unpack_charp(name, p_key, p_val_str, &opt->vlarb_low);
+  snprintf(name, sizeof(name), "%s_sl2vl", prefix);
+  __osm_subn_opts_unpack_charp(name, p_key, p_val_str, &opt->sl2vl);
+}
+
+static int
+subn_dump_qos_options(
+  FILE *file,
+  const char *set_name,
+  const char *prefix,
+  osm_qos_options_t *opt)
+{
+       return fprintf(file, "# %s\n"
+               "%s_max_vls %u\n"
+               "%s_high_limit %u\n"
+               "%s_vlarb_high %s\n"
+               "%s_vlarb_low %s\n"
+               "%s_sl2vl %s\n",
+               set_name,
+               prefix, opt->max_vls,
+               prefix, opt->high_limit,
+               prefix, opt->vlarb_high,
+               prefix, opt->vlarb_low,
+               prefix, opt->sl2vl);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_subn_rescan_conf_file(
+  IN osm_subn_opt_t* const p_opts )
+{
+  char *p_cache_dir = getenv("OSM_CACHE_DIR");
+  char file_name[256];
+  FILE *opts_file;
+  char line[1024];
+  char *p_key, *p_val ,*p_last;
+  
+  /* try to open the options file from the cache dir */
+  if (!p_cache_dir || !(*p_cache_dir))
+    p_cache_dir = OSM_DEFAULT_CACHE_DIR;
+
+  strcpy(file_name, p_cache_dir);
+  strcat(file_name, "opensm.opts");
+  
+  opts_file = fopen(file_name, "r");
+  if (!opts_file)
+    return;
+
+  while (fgets(line, 1023, opts_file) != NULL)
+  {
+    /* get the first token */
+    p_key = strtok_r(line, " \t\n", &p_last);
+    if (p_key)
+    {
+      p_val = strtok_r(NULL, " \t\n", &p_last);
+
+      subn_parse_qos_options("qos",
+        p_key, p_val, &p_opts->qos_options);
+
+      subn_parse_qos_options("qos_ca",
+        p_key, p_val, &p_opts->qos_ca_options);
+
+      subn_parse_qos_options("qos_sw0",
+        p_key, p_val, &p_opts->qos_sw0_options);
+
+      subn_parse_qos_options("qos_swe",
+        p_key, p_val, &p_opts->qos_swe_options);
+
+      subn_parse_qos_options("qos_rtr",
+        p_key, p_val, &p_opts->qos_rtr_options);
+
+    }
+  }
+  fclose(opts_file);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_subn_parse_conf_file(
+  IN osm_subn_opt_t* const p_opts )
+{
+  char *p_cache_dir = getenv("OSM_CACHE_DIR");
+  char file_name[256];
+  FILE *opts_file;
+  char line[1024];
+  char *p_key, *p_val ,*p_last;
+  
+  /* try to open the options file from the cache dir */
+  if (!p_cache_dir || !(*p_cache_dir))
+    p_cache_dir = OSM_DEFAULT_CACHE_DIR;
+
+  strcpy(file_name, p_cache_dir);
+  strcat(file_name, "opensm.opts");
+  
+  opts_file = fopen(file_name, "r");
+  if (!opts_file) return;
+
+  while (fgets(line, 1023, opts_file) != NULL)
+  {
+    /* get the first token */
+    p_key = strtok_r(line, " \t\n", &p_last);
+    if (p_key)
+    {
+      p_val = strtok_r(NULL, " \t\n", &p_last);
+      
+      __osm_subn_opts_unpack_net64(
+        "guid", p_key, p_val, &p_opts->guid);
+
+      __osm_subn_opts_unpack_net64(
+        "m_key", p_key, p_val, &p_opts->m_key);
+  
+      __osm_subn_opts_unpack_net64(
+        "sm_key", p_key, p_val, &p_opts->sm_key);
+
+      __osm_subn_opts_unpack_net64(
+        "subnet_prefix",
+        p_key, p_val, &p_opts->subnet_prefix);
+
+      __osm_subn_opts_unpack_net16(
+        "m_key_lease_period",
+        p_key, p_val, &p_opts->m_key_lease_period);
+  
+      __osm_subn_opts_unpack_uint32(
+        "sweep_interval",
+        p_key, p_val, &p_opts->sweep_interval);
+      
+      __osm_subn_opts_unpack_uint32( 
+        "max_wire_smps",
+        p_key, p_val, &p_opts->max_wire_smps);
+      
+      __osm_subn_opts_unpack_uint32(
+        "transaction_timeout",
+        p_key, p_val, &p_opts->transaction_timeout);
+      
+      __osm_subn_opts_unpack_uint32(
+        "max_msg_fifo_timeout",
+        p_key, p_val, &p_opts->max_msg_fifo_timeout);
+
+      __osm_subn_opts_unpack_uint8( 
+        "sm_priority",
+        p_key, p_val, &p_opts->sm_priority);
+
+      __osm_subn_opts_unpack_uint8(
+        "lmc",
+        p_key, p_val, &p_opts->lmc);
+
+      __osm_subn_opts_unpack_boolean(
+        "lmc_esp0",
+        p_key, p_val, &p_opts->lmc_esp0);
+
+      __osm_subn_opts_unpack_uint8(
+        "max_op_vls",
+        p_key, p_val, &p_opts->max_op_vls);
+
+      __osm_subn_opts_unpack_uint8(
+        "force_link_speed",
+        p_key, p_val, &p_opts->force_link_speed);
+
+      __osm_subn_opts_unpack_boolean(
+        "reassign_lids",
+        p_key, p_val, &p_opts->reassign_lids);
+
+      __osm_subn_opts_unpack_boolean(
+        "reassign_lfts",
+        p_key, p_val, &p_opts->reassign_lfts);
+      
+      __osm_subn_opts_unpack_boolean( 
+        "ignore_other_sm",
+        p_key, p_val, &p_opts->ignore_other_sm);
+      
+      __osm_subn_opts_unpack_boolean( 
+        "single_thread",
+        p_key, p_val, &p_opts->single_thread);
+
+      __osm_subn_opts_unpack_boolean( 
+        "no_multicast_option",
+        p_key, p_val, &p_opts->no_multicast_option);
+      
+      __osm_subn_opts_unpack_boolean( 
+        "disable_multicast",
+        p_key, p_val, &p_opts->disable_multicast);
+      
+      __osm_subn_opts_unpack_boolean( 
+        "force_log_flush",
+        p_key, p_val, &p_opts->force_log_flush);
+
+      __osm_subn_opts_unpack_uint8( 
+        "subnet_timeout",
+        p_key, p_val, &p_opts->subnet_timeout);
+      
+      __osm_subn_opts_unpack_uint8(
+        "packet_life_time",
+        p_key, p_val, &p_opts->packet_life_time);
+      
+      __osm_subn_opts_unpack_uint8(
+        "vl_stall_count",
+        p_key, p_val, &p_opts->vl_stall_count);
+      
+      __osm_subn_opts_unpack_uint8(
+        "leaf_vl_stall_count",
+        p_key, p_val, &p_opts->leaf_vl_stall_count);
+      
+      __osm_subn_opts_unpack_uint8(
+        "head_of_queue_lifetime",
+        p_key, p_val, &p_opts->head_of_queue_lifetime);
+      
+      __osm_subn_opts_unpack_uint8(
+        "leaf_head_of_queue_lifetime",
+        p_key, p_val, &p_opts->leaf_head_of_queue_lifetime);
+
+      __osm_subn_opts_unpack_uint8(
+        "local_phy_errors_threshold",
+        p_key, p_val, &p_opts->local_phy_errors_threshold);
+
+      __osm_subn_opts_unpack_uint8(
+        "overrun_errors_threshold",
+        p_key, p_val, &p_opts->overrun_errors_threshold);
+      
+      __osm_subn_opts_unpack_uint32(
+        "sminfo_polling_timeout",
+        p_key, p_val, &p_opts->sminfo_polling_timeout);
+      
+      __osm_subn_opts_unpack_uint32( 
+        "polling_retry_number",
+        p_key, p_val, &p_opts->polling_retry_number);
+      
+      __osm_subn_opts_unpack_boolean(
+        "force_heavy_sweep",
+        p_key, p_val, &p_opts->force_heavy_sweep);
+
+      __osm_subn_opts_unpack_uint8( 
+        "log_flags",
+        p_key, p_val, &p_opts->log_flags);
+
+      __osm_subn_opts_unpack_boolean(
+        "port_profile_switch_nodes",
+        p_key, p_val, &p_opts->port_profile_switch_nodes);
+      
+      __osm_subn_opts_unpack_boolean(
+        "sweep_on_trap",
+        p_key, p_val, &p_opts->sweep_on_trap);
+
+      __osm_subn_opts_unpack_charp(
+        "routing_engine",
+        p_key, p_val, &p_opts->routing_engine_name);
+
+      __osm_subn_opts_unpack_charp(
+        "log_file", p_key, p_val, &p_opts->log_file);
+
+      __osm_subn_opts_unpack_uint32(
+        "log_max_size",
+        p_key, p_val, (uint32_t *)&p_opts->log_max_size);
+      
+      __osm_subn_opts_unpack_charp(
+        "partition_config_file",
+       p_key, p_val, &p_opts->partition_config_file);
+
+      __osm_subn_opts_unpack_boolean(
+        "no_partition_enforcement",
+        p_key, p_val, &p_opts->no_partition_enforcement);
+
+      __osm_subn_opts_unpack_boolean(
+        "no_qos",
+        p_key, p_val, &p_opts->no_qos);
+
+      __osm_subn_opts_unpack_boolean(
+        "accum_log_file",
+        p_key, p_val, &p_opts->accum_log_file);
+
+      __osm_subn_opts_unpack_charp(
+        "dump_files_dir",
+        p_key, p_val, &p_opts->dump_files_dir);
+
+      __osm_subn_opts_unpack_charp(
+        "lid_matrix_dump_file",
+        p_key, p_val, &p_opts->lid_matrix_dump_file);
+
+      __osm_subn_opts_unpack_charp( 
+        "ucast_dump_file",
+        p_key, p_val, &p_opts->ucast_dump_file);
+
+      __osm_subn_opts_unpack_charp( 
+        "updn_guid_file",
+        p_key, p_val, &p_opts->updn_guid_file);
+
+      __osm_subn_opts_unpack_charp(
+        "sa_db_file",
+        p_key, p_val, &p_opts->sa_db_file);
+
+      __osm_subn_opts_unpack_boolean(
+        "exit_on_fatal",
+        p_key, p_val, &p_opts->exit_on_fatal);
+
+      __osm_subn_opts_unpack_boolean( 
+        "honor_guid2lid_file",
+        p_key, p_val, &p_opts->honor_guid2lid_file);
+
+      subn_parse_qos_options("qos",
+        p_key, p_val, &p_opts->qos_options);
+
+      subn_parse_qos_options("qos_ca",
+        p_key, p_val, &p_opts->qos_ca_options);
+
+      subn_parse_qos_options("qos_sw0",
+        p_key, p_val, &p_opts->qos_sw0_options);
+
+      subn_parse_qos_options("qos_swe",
+        p_key, p_val, &p_opts->qos_swe_options);
+
+      subn_parse_qos_options("qos_rtr",
+        p_key, p_val, &p_opts->qos_rtr_options);
+
+      __osm_subn_opts_unpack_boolean(
+        "enable_quirks",
+        p_key, p_val, &p_opts->enable_quirks);
+
+    }
+  }
+  fclose(opts_file);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_subn_write_conf_file(
+  IN osm_subn_opt_t* const p_opts )
+{
+  char *p_cache_dir = getenv("OSM_CACHE_DIR");
+  char file_name[256];
+  FILE *opts_file;
+  
+  /* try to open the options file from the cache dir */
+  if (!p_cache_dir || !(*p_cache_dir))
+    p_cache_dir = OSM_DEFAULT_CACHE_DIR;
+
+  strcpy(file_name, p_cache_dir);
+  strcat(file_name, "opensm.opts");
+  
+  opts_file = fopen(file_name, "w");
+  if (!opts_file) return;
+
+  fprintf( 
+    opts_file,
+    "#\n# DEVICE ATTRIBUTES OPTIONS\n#\n"
+    "# The port GUID on which the OpenSM is running\n"
+    "guid 0x%016" PRIx64 "\n\n"
+    "# M_Key value sent to all ports qualifying all Set(PortInfo)\n"
+    "m_key 0x%016" PRIx64 "\n\n"
+    "# The lease period used for the M_Key on this subnet in [msec]\n"
+    "m_key_lease_period %u\n\n"
+    "# SM_Key value of the SM to qualify rcv SA queries as 'trusted'\n"
+    "sm_key 0x%016" PRIx64 "\n\n"
+    "# Subnet prefix used on this subnet\n"
+    "subnet_prefix 0x%016" PRIx64 "\n\n"
+    "# The LMC value used on this subnet\n"
+    "lmc %u\n\n"
+    "# lmc_esp0 determines whether LMC value used on subnet is used for\n"
+    "#enhanced switch port 0. If TRUE, LMC value for subnet is used for\n"
+    "#ESP0. Otherwise, LMC value for ESP0s is 0.\n"
+    "lmc_esp0 %s\n\n"
+    "# The code of maximal time a packet can live in a switch\n"
+    "# The actual time is 4.096usec * 2^<packet_life_time>\n"
+    "# The value 0x14 disables this mechanism\n"
+    "packet_life_time 0x%02x\n\n"
+    "# The number of sequential packets dropped that cause the port\n"
+    "# to enter the VLStalled state. The result of setting this value to\n"
+    "# zero is undefined.\n"
+    "vl_stall_count 0x%02x\n\n"
+    "# The number of sequential packets dropped that cause the port\n"
+    "# to enter the VLStalled state. This value is for switch ports\n"
+    "# driving a CA or router port. The result of setting this value\n"
+    "# to zero is undefined.\n"
+    "leaf_vl_stall_count 0x%02x\n\n"
+    "# The code of maximal time a packet can wait at the head of\n"
+    "# transmission queue. \n"
+    "# The actual time is 4.096usec * 2^<head_of_queue_lifetime>\n"
+    "# The value 0x14 disables this mechanism\n"          
+    "head_of_queue_lifetime 0x%02x\n\n"
+    "# The maximal time a packet can wait at the head of queue on \n"
+    "# switch port connected to a CA or router port\n"
+    "leaf_head_of_queue_lifetime 0x%02x\n\n"
+    "# Limit the maximal operational VLs\n"
+    "max_op_vls %u\n\n"
+    "# Force switch links which are more than SDR capable to \n"
+    "# operate at SDR speed\n\n"
+    "force_link_speed %u\n\n"
+    "# The subnet_timeout code that will be set for all the ports\n"
+    "# The actual timeout is 4.096usec * 2^<subnet_timeout>\n"
+    "subnet_timeout %u\n\n"
+    "# Threshold of local phy errors for sending Trap 129\n"
+    "local_phy_errors_threshold 0x%02x\n\n"
+    "# Threshold of credits over-run errors for sending Trap 129\n"
+    "overrun_errors_threshold 0x%02x\n\n",
+    cl_ntoh64(p_opts->guid),
+    cl_ntoh64(p_opts->m_key),
+    cl_ntoh16(p_opts->m_key_lease_period),
+    cl_ntoh64(p_opts->sm_key),
+    cl_ntoh64(p_opts->subnet_prefix),
+    p_opts->lmc,
+    p_opts->lmc_esp0 ? "TRUE" : "FALSE",
+    p_opts->packet_life_time,
+    p_opts->vl_stall_count,
+    p_opts->leaf_vl_stall_count,
+    p_opts->head_of_queue_lifetime,
+    p_opts->leaf_head_of_queue_lifetime,
+    p_opts->max_op_vls,
+    p_opts->force_link_speed,
+    p_opts->subnet_timeout,
+    p_opts->local_phy_errors_threshold,
+    p_opts->overrun_errors_threshold
+    );
+
+  fprintf( 
+    opts_file,
+    "#\n# PARTITIONING OPTIONS\n#\n"
+    "# Partition configuration file to be used\n"
+    "partition_config_file %s\n\n" 
+    "# Disable partition enforcement by switches\n"
+    "no_partition_enforcement %s\n\n",
+    p_opts->partition_config_file,
+    p_opts->no_partition_enforcement ? "TRUE" : "FALSE");
+
+  fprintf( 
+    opts_file,
+    "#\n# SWEEP OPTIONS\n#\n"
+    "# The number of seconds between subnet sweeps (0 disables it)\n"
+    "sweep_interval %u\n\n"
+    "# If TRUE cause all lids to be reassigned\n"
+    "reassign_lids %s\n\n"
+    "# If TRUE ignore existing LFT entries on first sweep (default).\n"
+    "# Otherwise only non minimal hop cases are modified.\n"
+    "# NOTE: A standby SM clears its first sweep flag - since the\n"
+    "# master SM already sweeps...\n"
+    "reassign_lfts %s\n\n"
+    "# If TRUE forces every sweep to be a heavy sweep\n"
+    "force_heavy_sweep %s\n\n"
+    "# If TRUE every trap will cause a heavy sweep.\n"
+    "# NOTE: successive identical traps (>10) are suppressed\n"
+    "sweep_on_trap %s\n\n",
+    p_opts->sweep_interval,
+    p_opts->reassign_lids ? "TRUE" : "FALSE",
+    p_opts->reassign_lfts ? "TRUE" : "FALSE",
+    p_opts->force_heavy_sweep ? "TRUE" : "FALSE",
+    p_opts->sweep_on_trap ? "TRUE" : "FALSE"    
+    );
+  
+  fprintf( 
+    opts_file,
+    "#\n# ROUTING OPTIONS\n#\n"
+    "# If TRUE count switches as link subscriptions\n"
+    "port_profile_switch_nodes %s\n\n",
+    p_opts->port_profile_switch_nodes ? "TRUE" : "FALSE");
+
+  if (p_opts->routing_engine_name)
+    fprintf( opts_file,
+             "# Routing engine\n"
+             "routing_engine %s\n\n",
+             p_opts->routing_engine_name);
+  if (p_opts->lid_matrix_dump_file)
+    fprintf( opts_file,
+             "# Lid matrix dump file name\n"
+             "lid_matrix_dump_file %s\n\n",
+             p_opts->lid_matrix_dump_file);
+  if (p_opts->ucast_dump_file)
+    fprintf( opts_file,
+             "# Ucast dump file name\n"
+             "ucast_dump_file %s\n\n",
+             p_opts->ucast_dump_file);
+  if (p_opts->updn_guid_file)
+    fprintf( opts_file,
+             "# The file holding the Up/Down root node guids\n"
+             "# One guid in each line\n"
+             "updn_guid_file %s\n\n",
+             p_opts->updn_guid_file);
+  if (p_opts->sa_db_file)
+    fprintf( opts_file,
+             "# SA database file name\n"
+             "sa_db_file %s\n\n",
+             p_opts->sa_db_file);
+  
+  fprintf( 
+    opts_file,    
+    "#\n# HANDOVER - MULTIPLE SMs OPTIONS\n#\n"
+    "# SM priority used for deciding who is the master\n"
+    "sm_priority %u\n\n"
+    "# If TRUE other SMs on the subnet should be ignored\n"
+    "ignore_other_sm %s\n\n"
+    "# Timeout in [msec] between two polls of active master SM\n"
+    "sminfo_polling_timeout %u\n\n"
+    "# Number of failing polls of remote SM that declares it dead\n"
+    "polling_retry_number %u\n\n"
+    "# If TRUE honor the guid2lid file when coming out of standby\n"
+    "# state, if such file exists and is valid\n"
+    "honor_guid2lid_file %s\n\n",
+    p_opts->sm_priority,
+    p_opts->ignore_other_sm ? "TRUE" : "FALSE",
+    p_opts->sminfo_polling_timeout,
+    p_opts->polling_retry_number,
+    p_opts->honor_guid2lid_file ? "TRUE" : "FALSE"
+    );
+    
+  fprintf(
+    opts_file,
+    "#\n# TIMING AND THREADING OPTIONS\n#\n"
+    "# Number of MADs sent in parallel\n"
+    "max_wire_smps %u\n\n"
+    "# The time taken to a transaction to finish in [msec]\n"
+    "transaction_timeout %u\n\n"
+    "# Maximal time in [msec] a message can stay in the incoming message queue.\n"
+    "# If there is more than one message in the queue and the last message\n"
+    "# stayed in the queue more than this value any SA request will be \n"
+    "# immediately returned with a BUSY status.\n"
+    "max_msg_fifo_timeout %u\n\n"
+    "# Use a single thread for handling SA queries\n"
+    "single_thread %s\n\n",
+    p_opts->max_wire_smps,
+    p_opts->transaction_timeout,
+    p_opts->max_msg_fifo_timeout,
+    p_opts->single_thread ? "TRUE" : "FALSE"
+    );
+  
+  fprintf( 
+    opts_file,
+    "#\n# DEBUG FEATURES\n#\n"
+    "# The log flags used\n"
+    "log_flags 0x%02x\n\n"
+    "# Force flush of the log file after each log message\n"
+    "force_log_flush %s\n\n"
+    "# Log file to be used\n"
+    "log_file %s\n\n"
+    "# Limit the size of the log file. If overrun, log is restarted\n"
+    "log_max_size %lu\n\n"
+    "# If TRUE will accumulate the log over multiple OpenSM sessions\n"
+    "accum_log_file %s\n\n"
+    "# The directory to hold the file OpenSM dumps\n"
+    "dump_files_dir %s\n\n"
+    "# If TRUE enables new high risk options and hardware specific quirks\n"
+    "enable_quirks %s\n\n"
+    "# If TRUE OpenSM should disable multicast support\n"  
+    "no_multicast_option %s\n\n"
+    "# No multicast routing is performed if TRUE\n"
+    "disable_multicast %s\n\n"
+    "# If TRUE opensm will exit on fatal initialization issues\n"
+    "exit_on_fatal %s\n\n",
+    p_opts->log_flags,
+    p_opts->force_log_flush ? "TRUE" : "FALSE",
+    p_opts->log_file,
+    p_opts->log_max_size,
+    p_opts->accum_log_file ? "TRUE" : "FALSE",
+    p_opts->dump_files_dir,
+    p_opts->enable_quirks ? "TRUE" : "FALSE",
+    p_opts->no_multicast_option ? "TRUE" : "FALSE",
+    p_opts->disable_multicast ? "TRUE" : "FALSE",
+    p_opts->exit_on_fatal ? "TRUE" : "FALSE"
+    );
+  
+  fprintf(
+    opts_file,
+    "#\n# QoS OPTIONS\n#\n"
+    "# Disable QoS setup\n"
+    "no_qos %s\n\n",
+    p_opts->no_qos ? "TRUE" : "FALSE");
+
+  subn_dump_qos_options(opts_file,
+    "QoS default options", "qos", &p_opts->qos_options);
+  fprintf(opts_file, "\n");
+  subn_dump_qos_options(opts_file,
+    "QoS CA options", "qos_ca", &p_opts->qos_ca_options);
+  fprintf(opts_file, "\n");
+  subn_dump_qos_options(opts_file,
+    "QoS Switch Port 0 options", "qos_sw0", &p_opts->qos_sw0_options);
+  fprintf(opts_file, "\n");
+  subn_dump_qos_options(opts_file,
+    "QoS Switch external ports options", "qos_swe", &p_opts->qos_swe_options);
+  fprintf(opts_file, "\n");
+  subn_dump_qos_options(opts_file,
+    "QoS Router ports options", "qos_rtr", &p_opts->qos_rtr_options);
+
+  /* optional string attributes ... */
+  
+  fclose(opts_file);
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sw_info_rcv.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sw_info_rcv.c
new file mode 100644 (file)
index 0000000..5edbf0b
--- /dev/null
@@ -0,0 +1,681 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sw_info_rcv.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_si_rcv_t.
+ * This object represents the SwitchInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_sw_info_rcv.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_helper.h>
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_si_rcv_get_port_info(
+  IN const osm_si_rcv_t* const p_rcv,
+  IN osm_switch_t* const p_sw,
+  IN const osm_madw_t* const p_madw )
+{
+  osm_madw_context_t context;
+  uint8_t port_num;
+  osm_physp_t *p_physp;
+  osm_node_t *p_node;
+  uint8_t num_ports;
+  osm_dr_path_t dr_path;
+  const ib_smp_t* p_smp;
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_get_port_info );
+
+  CL_ASSERT( p_sw );
+
+  p_node = osm_switch_get_node_ptr( p_sw );
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+
+  CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
+
+  /*
+    Request PortInfo attribute for each port on the switch.
+    Don't trust the port's own DR Path, since it may no longer
+    be a legitimate path through the subnet.
+    Build a path from the mad instead, since we know that path works.
+    The port's DR Path info gets updated when the PortInfo
+    attribute is received.
+  */
+  p_physp = osm_node_get_any_physp_ptr( p_node );
+
+  CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+  context.pi_context.node_guid = osm_node_get_node_guid( p_node );
+  context.pi_context.port_guid = osm_physp_get_port_guid( p_physp );
+  context.pi_context.set_method = FALSE;
+  context.pi_context.update_master_sm_base_lid = FALSE;
+  context.pi_context.ignore_errors = FALSE;
+  context.pi_context.light_sweep = FALSE;
+  context.pi_context.active_transition = FALSE;
+
+  num_ports = osm_node_get_num_physp( p_node );
+  osm_dr_path_init( &dr_path,
+                    osm_madw_get_bind_handle( p_madw ),
+                    p_smp->hop_count, p_smp->initial_path );
+
+  for( port_num = 0; port_num < num_ports; port_num++)
+  {
+    status = osm_req_get(
+      p_rcv->p_req,
+      &dr_path,
+      IB_MAD_ATTR_PORT_INFO,
+      cl_hton32( port_num ),
+      CL_DISP_MSGID_NONE,
+      &context );
+    if( status != IB_SUCCESS )
+    {
+      /* continue the loop despite the error */
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_si_rcv_get_port_info: ERR 3602: "
+               "Failure initiating PortInfo request (%s)\n",
+               ib_get_err_str(status));
+    }
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_si_rcv_get_fwd_tbl(
+  IN const osm_si_rcv_t* const p_rcv,
+  IN osm_switch_t* const p_sw )
+{
+  osm_madw_context_t context;
+  osm_dr_path_t *p_dr_path;
+  osm_physp_t *p_physp;
+  osm_node_t *p_node;
+  uint32_t block_id_ho;
+  uint32_t max_block_id_ho;
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_get_fwd_tbl );
+
+  CL_ASSERT( p_sw );
+
+  p_node = osm_switch_get_node_ptr( p_sw );
+
+  CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
+
+  p_physp = osm_node_get_any_physp_ptr( p_node );
+
+  CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+  context.lft_context.node_guid = osm_node_get_node_guid( p_node );
+  context.lft_context.set_method = FALSE;
+
+  max_block_id_ho = osm_switch_get_max_block_id_in_use( p_sw );
+
+  p_dr_path = osm_physp_get_dr_path_ptr( p_physp );
+
+  for( block_id_ho = 0; block_id_ho <= max_block_id_ho; block_id_ho++)
+  {
+    if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+               "__osm_si_rcv_get_fwd_tbl: "
+               "Retrieving FT block %u\n", block_id_ho );
+    }
+
+    status = osm_req_get(
+      p_rcv->p_req,
+      p_dr_path,
+      IB_MAD_ATTR_LIN_FWD_TBL,
+      cl_hton32( block_id_ho ),
+      CL_DISP_MSGID_NONE,
+      &context );
+    if( status != IB_SUCCESS )
+    {
+      /* continue the loop despite the error */
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_si_rcv_get_fwd_tbl: ERR 3603: "
+               "Failure initiating PortInfo request (%s)\n",
+               ib_get_err_str(status));
+    }
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+#if 0
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_si_rcv_get_mcast_fwd_tbl(
+  IN const osm_si_rcv_t* const p_rcv,
+  IN osm_switch_t* const p_sw )
+{
+  osm_madw_context_t context;
+  osm_dr_path_t *p_dr_path;
+  osm_physp_t *p_physp;
+  osm_node_t *p_node;
+  osm_mcast_tbl_t* p_tbl;
+  uint32_t block_id_ho;
+  uint32_t max_block_id_ho;
+  uint32_t position;
+  uint32_t max_position;
+  uint32_t attr_mod_ho;
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_get_mcast_fwd_tbl );
+
+  CL_ASSERT( p_sw );
+
+  p_node = osm_switch_get_node_ptr( p_sw );
+
+  CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
+
+  if( osm_switch_get_mcast_fwd_tbl_size( p_sw ) == 0 )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "__osm_si_rcv_get_mcast_fwd_tbl: "
+             "Multicast not supported by switch 0x%016" PRIx64 "\n",
+             cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+    goto Exit;
+  }
+
+  p_physp = osm_node_get_any_physp_ptr( p_node );
+  p_tbl = osm_switch_get_mcast_tbl_ptr( p_sw );
+
+  CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+  context.mft_context.node_guid = osm_node_get_node_guid( p_node );
+  context.mft_context.set_method = FALSE;
+
+  max_block_id_ho = osm_mcast_tbl_get_max_block( p_tbl );
+
+  if( max_block_id_ho > IB_MCAST_MAX_BLOCK_ID )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_si_rcv_get_mcast_fwd_tbl: ERR 3609: "
+             "Out-of-range mcast block size = %u on switch 0x%016" PRIx64
+             "\n", max_block_id_ho,
+             cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+    goto Exit;
+  }
+
+  max_position = osm_mcast_tbl_get_max_position( p_tbl );
+
+  CL_ASSERT( max_position <= IB_MCAST_POSITION_MAX );
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+           "__osm_si_rcv_get_mcast_fwd_tbl: "
+           "Max MFT block = %u, Max position = %u\n", max_block_id_ho,
+           max_position );
+
+  p_dr_path = osm_physp_get_dr_path_ptr( p_physp );
+
+  for( block_id_ho = 0; block_id_ho <= max_block_id_ho; block_id_ho++)
+  {
+    if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+               "__osm_si_rcv_get_mcast_fwd_tbl: "
+               "Retrieving MFT block %u\n", block_id_ho );
+    }
+
+    for( position = 0; position <= max_position; position++ )
+    {
+      if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+                 "__osm_si_rcv_get_mcast_fwd_tbl: "
+                 "Retrieving MFT position %u\n", position );
+      }
+
+      attr_mod_ho = block_id_ho | position << IB_MCAST_POSITION_SHIFT;
+      status = osm_req_get(
+        p_rcv->p_req,
+        p_dr_path,
+        IB_MAD_ATTR_MCAST_FWD_TBL,
+        cl_hton32( attr_mod_ho ),
+        CL_DISP_MSGID_NONE,
+        &context );
+      if( status != IB_SUCCESS )
+      {
+        /* continue the loop despite the error */
+        osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                 "__osm_si_rcv_get_mcast_fwd_tbl: ERR 3607: "
+                 "Failure initiating PortInfo request (%s)\n",
+                 ib_get_err_str(status));
+      }
+    }
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+#endif
+
+/**********************************************************************
+   Lock must be held on entry to this function.
+**********************************************************************/
+static void
+__osm_si_rcv_process_new(
+  IN const osm_si_rcv_t* const p_rcv,
+  IN osm_node_t* const p_node,
+  IN const osm_madw_t* const p_madw )
+{
+  osm_switch_t *p_sw;
+  osm_switch_t *p_check;
+  ib_switch_info_t *p_si;
+  ib_smp_t *p_smp;
+  cl_qmap_t *p_sw_guid_tbl;
+
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_process_new );
+
+  CL_ASSERT( p_madw );
+
+  p_sw_guid_tbl = &p_rcv->p_subn->sw_guid_tbl;
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+  p_si = (ib_switch_info_t*)ib_smp_get_payload_ptr( p_smp );
+
+  osm_dump_switch_info( p_rcv->p_log, p_si, OSM_LOG_DEBUG );
+
+  /*
+    Allocate a new switch object for this switch,
+    and place it in the switch table.
+  */
+  p_sw = osm_switch_new( p_node, p_madw );
+  if( p_sw == NULL )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_si_rcv_process_new: ERR 3608: "
+             "Unable to allocate new switch object\n" );
+    goto Exit;
+  }
+
+  /* set subnet max mlid to the minimum MulticastFDBCap of all switches */
+  if ( p_sw->mcast_tbl.max_mlid_ho < p_rcv->p_subn->max_multicast_lid_ho )
+  {
+    p_rcv->p_subn->max_multicast_lid_ho = p_sw->mcast_tbl.max_mlid_ho;
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "__osm_si_rcv_process_new: "
+             "Subnet max multicast lid is 0x%X\n",
+             p_rcv->p_subn->max_multicast_lid_ho );
+  }
+
+  /* set subnet max unicast lid to the minimum LinearFDBCap of all switches */
+  if ( p_sw->fwd_tbl.p_lin_tbl->size < p_rcv->p_subn->max_unicast_lid_ho )
+  {
+    p_rcv->p_subn->max_unicast_lid_ho = p_sw->fwd_tbl.p_lin_tbl->size;
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "__osm_si_rcv_process_new: "
+             "Subnet max unicast lid is 0x%X\n",
+             p_rcv->p_subn->max_unicast_lid_ho );
+  }
+
+  p_check = (osm_switch_t*)cl_qmap_insert( p_sw_guid_tbl,
+                                           osm_node_get_node_guid( p_node ),
+                                           &p_sw->map_item );
+
+  if( p_check != p_sw )
+  {
+    /*
+      This shouldn't happen since we hold the lock!
+    */
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_si_rcv_process_new: ERR 3605: "
+             "Unable to add new switch object to database\n" );
+    osm_switch_delete( &p_sw );
+    goto Exit;
+  }
+
+  p_node->sw = p_sw;
+
+  /*
+    Update the switch info according to the
+    info we just received.
+  */
+  osm_switch_set_switch_info( p_sw, p_si );
+  osm_switch_discovery_count_inc( p_sw );
+
+  /*
+    Get the PortInfo attribute for every port.
+  */
+  __osm_si_rcv_get_port_info( p_rcv, p_sw, p_madw );
+  __osm_si_rcv_get_fwd_tbl( p_rcv, p_sw );
+
+  /*
+    Don't bother retrieving the current multicast tables
+    from the switches.  The current version of SM does
+    not support silent take-over of an existing multicast
+    configuration.
+
+    Gathering the multicast tables can also generate large amounts
+    of extra subnet-init traffic.
+
+    The code to retrieve the tables was fully debugged.
+  */
+#if 0
+  if( !p_rcv->p_subn->opt.disable_multicast )
+    __osm_si_rcv_get_mcast_fwd_tbl( p_rcv, p_sw );
+#endif
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+   Lock must be held on entry to this function.
+   Return 1 if the caller is expected to send a change_detected event.
+   this can not be done internally as the event needs the lock...
+**********************************************************************/
+static boolean_t
+__osm_si_rcv_process_existing(
+  IN const osm_si_rcv_t* const p_rcv,
+  IN osm_node_t* const p_node,
+  IN const osm_madw_t* const p_madw )
+{
+  osm_switch_t *p_sw = p_node->sw;
+  ib_switch_info_t *p_si;
+  osm_si_context_t *p_si_context;
+  ib_smp_t         *p_smp;
+  boolean_t         is_change_detected = FALSE;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_process_existing );
+
+  CL_ASSERT( p_madw );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+  p_si = (ib_switch_info_t*)ib_smp_get_payload_ptr( p_smp );
+  p_si_context = osm_madw_get_si_context_ptr( p_madw );
+
+  if( p_si_context->set_method )
+  {
+    if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+               "__osm_si_rcv_process_existing: "
+               "Received logical SetResp()\n" );
+    }
+
+    osm_switch_set_switch_info( p_sw, p_si );
+  }
+  else
+  {
+    if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+               "__osm_si_rcv_process_existing: "
+               "Received logical GetResp()\n" );
+    }
+
+    osm_switch_set_switch_info( p_sw, p_si );
+
+    /*
+      Check the port state change bit.  If true, then this switch
+      has seen a port state transition, so continue probing.
+    */
+    if( p_si_context->light_sweep == TRUE )
+    {
+      /* This is a light sweep */
+      /* If the mad was returned with an error -
+         signal a change to the state manager. */
+      if ( ib_smp_get_status( p_smp ) != 0 )
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+                 "__osm_si_rcv_process_existing: "
+                 "GetResp() received with error in light sweep. "
+                 "Commencing heavy sweep\n" );
+          is_change_detected = TRUE;
+      }
+      else
+      {
+        /*
+          If something changed, then just signal the state
+          manager.  Don't attempt to probe further during
+          a light sweep.
+        */
+        if( ib_switch_info_get_state_change( p_si ) )
+        {
+          osm_dump_switch_info( p_rcv->p_log, p_si, OSM_LOG_DEBUG );
+          is_change_detected = TRUE;
+        }
+      }
+    }
+    else
+    {
+      /*
+        This is a heavy sweep.  Get information regardless
+        of the state change bit.
+      */
+      osm_switch_discovery_count_inc( p_sw );
+      osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+               "__osm_si_rcv_process_existing: "
+               "discovery_count is:%u\n",
+               osm_switch_discovery_count_get( p_sw ) );
+
+      /* If this is the first discovery - then get the port_info */
+      if ( osm_switch_discovery_count_get( p_sw ) == 1 )
+        __osm_si_rcv_get_port_info( p_rcv, p_sw, p_madw );
+      else
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+                 "__osm_si_rcv_process_existing: "
+                 "Not discovering again through switch:0x%"
+                 PRIx64 "\n",
+                 osm_node_get_node_guid( p_sw->p_node) );
+      }
+    }
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return is_change_detected;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_si_rcv_construct(
+  IN osm_si_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_si_rcv_destroy(
+  IN osm_si_rcv_t* const p_rcv )
+{
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_si_rcv_destroy );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_si_rcv_init(
+  IN osm_si_rcv_t* const p_rcv,
+  IN osm_subn_t* const p_subn,
+  IN osm_log_t* const p_log,
+  IN osm_req_t* const p_req,
+  IN osm_state_mgr_t* const p_state_mgr,
+  IN cl_plock_t* const p_lock )
+{
+  ib_api_status_t status = IB_SUCCESS;
+  OSM_LOG_ENTER( p_log, osm_si_rcv_init );
+
+  osm_si_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_req = p_req;
+  p_rcv->p_state_mgr = p_state_mgr;
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_si_rcv_process(
+  IN const osm_si_rcv_t* const p_rcv,
+  IN osm_madw_t* const p_madw )
+{
+  cl_qmap_t *p_node_guid_tbl;
+  ib_switch_info_t *p_si;
+  ib_smp_t *p_smp;
+  osm_node_t *p_node;
+  ib_net64_t node_guid;
+  osm_si_context_t *p_context;
+
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_si_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_node_guid_tbl = &p_rcv->p_subn->node_guid_tbl;
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+  p_si = (ib_switch_info_t*)ib_smp_get_payload_ptr( p_smp );
+
+  /*
+    Acquire the switch object and add the switch info.
+  */
+
+  p_context = osm_madw_get_si_context_ptr( p_madw );
+
+  node_guid = p_context->node_guid;
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "osm_si_rcv_process: "
+             "Switch GUID 0x%016" PRIx64
+             ", TID 0x%" PRIx64 "\n",
+             cl_ntoh64( node_guid ),
+             cl_ntoh64( p_smp->trans_id ) );
+  }
+
+  CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
+
+  p_node = (osm_node_t*)cl_qmap_get( p_node_guid_tbl, node_guid );
+  if( p_node == (osm_node_t*)cl_qmap_end( p_node_guid_tbl ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_si_rcv_process: ERR 3606: "
+             "SwitchInfo received for nonexistent node "
+             "with GUID 0x%" PRIx64 "\n",
+             cl_ntoh64( node_guid ) );
+  }
+  else
+  {
+
+    /*
+      Hack for bad value in Mellanox switch
+    */
+    if( cl_ntoh16( p_si->lin_top ) > IB_LID_UCAST_END_HO )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_si_rcv_process: ERR 3610: "
+               "\n\t\t\t\tBad LinearFDBTop value = 0x%X "
+               "on switch 0x%" PRIx64
+               "\n\t\t\t\tForcing correction to 0x%X\n",
+               cl_ntoh16( p_si->lin_top ),
+               cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+               0 );
+
+      p_si->lin_top = 0;
+    }
+
+    /*
+      Acquire the switch object for this switch.
+    */
+    if( !p_node->sw )
+    {
+      __osm_si_rcv_process_new( p_rcv, p_node, p_madw );
+      /*
+         A new switch was found during the sweep so we need
+         to ignore the current LFT settings.
+      */
+      p_rcv->p_subn->ignore_existing_lfts = TRUE;
+    }
+    else
+    {
+      /* we might get back a request for signaling change was detected */
+      if (__osm_si_rcv_process_existing( p_rcv, p_node, p_madw ))
+      {
+        CL_PLOCK_RELEASE( p_rcv->p_lock );
+        osm_state_mgr_process( p_rcv->p_state_mgr,
+                               OSM_SIGNAL_CHANGE_DETECTED );
+        goto Exit;
+      }
+    }
+  }
+
+  CL_PLOCK_RELEASE( p_rcv->p_lock );
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sw_info_rcv_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sw_info_rcv_ctrl.c
new file mode 100644 (file)
index 0000000..6c8c478
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sw_info_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_si_rcv_ctrl_t.
+ * This object represents the SwitchInfo request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sw_info_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_si_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_si_rcv_process( ((osm_si_rcv_ctrl_t*)context)->p_rcv,
+                      (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_si_rcv_ctrl_construct(
+  IN osm_si_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_si_rcv_ctrl_destroy(
+  IN osm_si_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_si_rcv_ctrl_init(
+  IN osm_si_rcv_ctrl_t* const p_ctrl,
+  IN osm_si_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_si_rcv_ctrl_init );
+
+  osm_si_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_SWITCH_INFO,
+    __osm_si_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_si_rcv_ctrl_init: ERR 3701: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sweep_fail_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_sweep_fail_ctrl.c
new file mode 100644 (file)
index 0000000..1933562
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_sweep_fail_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_sweep_fail_ctrl_t.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sweep_fail_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sweep_fail_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  osm_sweep_fail_ctrl_t* const p_ctrl = (osm_sweep_fail_ctrl_t*)context;
+
+  OSM_LOG_ENTER( p_ctrl->p_log, __osm_sweep_fail_ctrl_disp_callback );
+
+  UNUSED_PARAM( p_data );
+  /*
+    Notify the state manager that we had a light sweep failure.
+  */
+  osm_state_mgr_process( p_ctrl->p_state_mgr,
+                         OSM_SIGNAL_LIGHT_SWEEP_FAIL );
+
+  OSM_LOG_EXIT( p_ctrl->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sweep_fail_ctrl_construct(
+  IN osm_sweep_fail_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sweep_fail_ctrl_destroy(
+  IN osm_sweep_fail_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sweep_fail_ctrl_init(
+  IN osm_sweep_fail_ctrl_t* const p_ctrl,
+  IN osm_log_t* const p_log,
+  IN osm_state_mgr_t* const p_state_mgr,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_sweep_fail_ctrl_init );
+
+  osm_sweep_fail_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_disp = p_disp;
+  p_ctrl->p_state_mgr = p_state_mgr;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_LIGHT_SWEEP_FAIL,
+    __osm_sweep_fail_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_sweep_fail_ctrl_init: ERR 3501: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_switch.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_switch.c
new file mode 100644 (file)
index 0000000..f59fcf6
--- /dev/null
@@ -0,0 +1,550 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_switch.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_switch_t.
+ * This object represents an Infiniband switch.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.13 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_math.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_switch.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_switch_construct(
+  IN osm_switch_t* const p_sw )
+{
+  CL_ASSERT( p_sw );
+  memset( p_sw, 0, sizeof(*p_sw) );
+  osm_lid_matrix_construct( &p_sw->lmx );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_switch_init(
+  IN osm_switch_t* const p_sw,
+  IN osm_node_t* const p_node,
+  IN const osm_madw_t* const p_madw )
+{
+  ib_api_status_t       status = IB_SUCCESS;
+  ib_switch_info_t      *p_si;
+  ib_smp_t              *p_smp;
+  uint8_t               num_ports;
+  uint32_t              port_num;
+
+  CL_ASSERT( p_sw );
+  CL_ASSERT( p_madw );
+  CL_ASSERT( p_node );
+
+  osm_switch_construct( p_sw );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+  p_si = (ib_switch_info_t*)ib_smp_get_payload_ptr( p_smp );
+  num_ports = osm_node_get_num_physp( p_node );
+
+  CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_SWITCH_INFO );
+
+  p_sw->p_node = p_node;
+  p_sw->switch_info = *p_si;
+
+  status = osm_lid_matrix_init( &p_sw->lmx, num_ports );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osm_fwd_tbl_init( &p_sw->fwd_tbl, p_si );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  p_sw->p_prof = malloc( sizeof(*p_sw->p_prof) * num_ports );
+  if( p_sw->p_prof == NULL )
+  {
+    status = IB_INSUFFICIENT_MEMORY;
+    goto Exit;
+  }
+
+  memset( p_sw->p_prof, 0, sizeof(*p_sw->p_prof) * num_ports );
+
+  status = osm_mcast_tbl_init( &p_sw->mcast_tbl,
+                               osm_node_get_num_physp( p_node ), cl_ntoh16( p_si->mcast_cap ) );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  for( port_num = 0; port_num < num_ports; port_num++ )
+    osm_port_prof_construct( &p_sw->p_prof[port_num] );
+
+ Exit:
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_switch_destroy(
+  IN osm_switch_t* const p_sw )
+{
+  /* free memory to avoid leaks */
+  osm_mcast_tbl_destroy( &p_sw->mcast_tbl );
+  free( p_sw->p_prof );
+  osm_fwd_tbl_destroy( &p_sw->fwd_tbl );
+  osm_lid_matrix_destroy( &p_sw->lmx );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_switch_delete(
+  IN OUT osm_switch_t** const pp_sw )
+{
+  osm_switch_destroy( *pp_sw );
+  free( *pp_sw );
+  *pp_sw = NULL;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_switch_t*
+osm_switch_new(
+  IN osm_node_t* const p_node,
+  IN const osm_madw_t* const p_madw )
+{
+  ib_api_status_t status;
+  osm_switch_t *p_sw;
+
+  p_sw = (osm_switch_t*)malloc( sizeof(*p_sw) );
+  if( p_sw )
+  {
+    memset( p_sw, 0, sizeof(*p_sw) );
+    status = osm_switch_init( p_sw, p_node, p_madw );
+    if( status != IB_SUCCESS )
+      osm_switch_delete( &p_sw );
+  }
+
+  return( p_sw );
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_switch_get_fwd_tbl_block(
+  IN const osm_switch_t* const p_sw,
+  IN const uint32_t block_id,
+  OUT uint8_t* const p_block )
+{
+  uint16_t base_lid_ho;
+  uint16_t max_lid_ho;
+  uint16_t lid_ho;
+  uint16_t block_top_lid_ho;
+  uint32_t lids_per_block;
+  osm_fwd_tbl_t *p_tbl;
+  boolean_t return_flag = FALSE;
+
+  CL_ASSERT( p_sw );
+  CL_ASSERT( p_block );
+
+  p_tbl = osm_switch_get_fwd_tbl_ptr( p_sw );
+  max_lid_ho = osm_switch_get_max_lid_ho( p_sw );
+  lids_per_block = osm_fwd_tbl_get_lids_per_block( &p_sw->fwd_tbl );
+  base_lid_ho = (uint16_t)(block_id * lids_per_block);
+
+  if( base_lid_ho <= max_lid_ho )
+  {
+    /* Initialize LIDs in block to invalid port number. */
+    memset( p_block, 0xff, IB_SMP_DATA_SIZE );
+    /*
+      Determine the range of LIDs we can return with this block.
+    */
+    block_top_lid_ho = (uint16_t)(base_lid_ho + lids_per_block - 1);
+    if( block_top_lid_ho > max_lid_ho )
+      block_top_lid_ho = max_lid_ho;
+
+    /*
+      Configure the forwarding table with the routing
+      information for the specified block of LIDs.
+    */
+    for( lid_ho = base_lid_ho; lid_ho <= block_top_lid_ho; lid_ho++ )
+    {
+      p_block[lid_ho - base_lid_ho] =  osm_fwd_tbl_get( p_tbl, lid_ho );
+    }
+
+    return_flag = TRUE;
+  }
+
+  return( return_flag );
+}
+
+/**********************************************************************
+ **********************************************************************/
+uint8_t
+osm_switch_recommend_path(
+  IN const osm_switch_t* const p_sw,
+  IN const uint16_t lid_ho,
+  IN const boolean_t ignore_existing,
+  IN OUT uint64_t *remote_sys_guids,
+  IN OUT uint16_t *p_num_used_sys,
+  IN OUT uint64_t *remote_node_guids,
+  IN OUT uint16_t *p_num_used_nodes
+  )
+{
+  /*
+    We support an enhanced LMC aware routing mode:
+    In the case of LMC > 0, we can track the remote side
+    system and node for all of the lids of the target
+    and try and avoid routing again through the same
+    system / node.
+
+    If the procedure is provided with the tracking arrays
+    and counters we can conduct this algorithm.
+  */
+  boolean_t routing_for_lmc = remote_sys_guids && remote_node_guids &&
+    p_num_used_sys && p_num_used_nodes;
+  boolean_t sys_used, node_used;
+  uint16_t i;
+  uint8_t hops;
+  uint8_t least_hops;
+  uint8_t port_num;
+  uint8_t num_ports;
+  uint32_t least_paths = 0xFFFFFFFF;
+  /*
+    The follwing will track the least paths if the
+    route should go through a new system/node
+  */
+  uint32_t least_paths_other_sys = 0xFFFFFFFF;
+  uint32_t least_paths_other_nodes = 0xFFFFFFFF;
+  uint32_t check_count;
+  uint8_t best_port = 0;
+  /*
+    These vars track the best port if it connects to
+    not used system/node.
+  */
+  uint8_t best_port_other_sys = 0;
+  uint8_t best_port_other_node = 0;
+  boolean_t port_found = FALSE;
+  osm_physp_t *p_physp;
+  osm_physp_t *p_rem_physp;
+  osm_node_t *p_rem_node;
+
+  CL_ASSERT( lid_ho > 0 );
+
+  num_ports = osm_switch_get_num_ports( p_sw );
+
+  least_hops = osm_switch_get_least_hops( p_sw, lid_ho );
+  if ( least_hops == OSM_NO_PATH )
+    return (OSM_NO_PATH);
+
+  /*
+    First, inquire with the forwarding table for an existing
+    route.  If one is found, honor it unless:
+    1. the ignore existing flag is set.
+    2. the physical port is not a valid one or not healthy
+    3. the physical port has a remote port (the link is up)
+    4. the port has min-hops to the target (avoid loops)
+  */
+  if( !ignore_existing )
+  {
+    port_num = osm_fwd_tbl_get( &p_sw->fwd_tbl, lid_ho );
+
+    if (port_num != OSM_NO_PATH)
+    {
+      p_physp = osm_node_get_physp_ptr(p_sw->p_node, port_num);
+      /*
+        Don't be too trusting of the current forwarding table!
+        Verify that the port number is legal and that the
+        LID is reachable through this port.
+      */
+      if( (port_num < num_ports )  &&
+          osm_physp_is_valid(p_physp) &&
+          osm_physp_is_healthy(p_physp) &&
+          osm_physp_get_remote(p_physp) )
+      {
+        hops = osm_switch_get_hop_count( p_sw, lid_ho, port_num );
+        /* 
+           If we aren't using pre-defined user routes function, then
+           we need to make sure that the current path is the minimum one.
+           In case of having such a user function - this check will not
+           be done, and the old routing will be used.
+           Note: This means that it is the user's job to clean all data
+           in the forwarding tables that he wants to be overridden by the
+           minimum hop function. 
+        */
+        if ( hops == least_hops )
+        {
+          return( port_num );
+        }
+      }
+    }
+  }
+
+  /*
+    This algorithm selects a port based on a static load balanced
+    selection across equal hop-count ports.
+    There is lots of room for improved sophistication here,
+    possibly guided by user configuration info.
+  */
+
+  /*
+    OpenSM routing is "local" - not considering a full lid to lid
+    path. As such we can not guarantee a path will not loop if we
+    do not always follow least hops.
+    So we must abort if not least hops.
+  */
+
+  /* port number starts with zero and num_ports is 1 + num phys ports */
+  for ( port_num = 0; port_num < num_ports; port_num++ )
+  {
+    if ( osm_switch_get_hop_count( p_sw, lid_ho, port_num ) == least_hops)
+    {
+      /* let us make sure it is not down or unhealthy */
+      p_physp = osm_node_get_physp_ptr(p_sw->p_node, port_num);
+      if (osm_physp_is_valid(p_physp) &&
+          osm_physp_is_healthy(p_physp) &&
+          /*
+            we require all - non sma ports to be linked
+            to be routed through
+          */
+          (!port_num || osm_physp_get_remote(p_physp)))
+      {
+
+        /*
+          We located a least-hop port, possibly one of many.
+          For this port, check the running total count of
+          the number of paths through this port.  Select
+          the port routing the least number of paths.
+        */
+        check_count = osm_port_prof_path_count_get(
+          &p_sw->p_prof[port_num] );
+
+        /*
+          Advanced LMC routing requires tracking of the
+          best port by the node connected to the other side of
+          it.
+        */
+        if (routing_for_lmc && port_num)
+        {
+#if 0
+          printf("LID:0x%X SYS:%d NODE:%d\n", lid_ho, *p_num_used_sys, *p_num_used_nodes);
+#endif
+
+          /* Get the Remote Node */
+          p_rem_physp = osm_physp_get_remote(p_physp);
+          p_rem_node = osm_physp_get_node_ptr(p_rem_physp);
+
+          /* Is the sys guid already used ? */
+          sys_used = FALSE;
+          for (i = 0; !sys_used && (i < *p_num_used_sys); i++)
+            if (!memcmp(&p_rem_node->node_info.sys_guid,
+                        &remote_sys_guids[i],
+                        sizeof(uint64_t)))
+              sys_used = TRUE;
+
+          /* If not update the least hops for this case */
+          if (!sys_used)
+          {
+            if (check_count < least_paths_other_sys)
+            {
+              least_paths_other_sys = check_count;
+              best_port_other_sys = port_num;
+            }
+          }
+          else
+          { /* same sys found - try node */
+
+            /* Else is the node guid already used ? */
+            node_used = FALSE;
+            for (i = 0; !node_used && (i < *p_num_used_nodes); i++)
+              if (!memcmp(&p_rem_node->node_info.node_guid,
+                          &remote_node_guids[i],
+                          sizeof(uint64_t)))
+                node_used = TRUE;
+
+
+            /* If not update the least hops for this case */
+            if (!node_used)
+            {
+              if (check_count < least_paths_other_nodes)
+              {
+                least_paths_other_nodes = check_count;
+                best_port_other_node = port_num;
+              }
+            }
+
+          } /* same sys found */
+        } /* routing for LMC mode */
+
+        /*
+          the count is min but also lower then the max subscribed
+        */
+        if( check_count < least_paths )
+        {
+          port_found = TRUE;
+          best_port = port_num;
+          least_paths = check_count;
+        }
+      }
+    }
+  }
+
+  if ( port_found == FALSE )
+    return (OSM_NO_PATH);
+
+  /*
+    if we are in enhanced routing mode and the best port is not
+    the local port 0
+  */
+  if (routing_for_lmc && best_port)
+  {
+    /* Select the least hop port of the non used sys first */
+    if (best_port_other_sys)
+      best_port = best_port_other_sys;
+    else if (best_port_other_node)
+      best_port = best_port_other_node;
+
+    /* track the remote node and system of the port used. */
+    p_physp = osm_node_get_physp_ptr(p_sw->p_node, best_port);
+    p_rem_physp = osm_physp_get_remote(p_physp);
+    p_rem_node = osm_physp_get_node_ptr(p_rem_physp);
+    memcpy(&remote_node_guids[*p_num_used_nodes],
+           &(p_rem_node->node_info.node_guid),
+           sizeof(uint64_t));
+    (*p_num_used_nodes)++;
+    memcpy(&remote_sys_guids[*p_num_used_sys],
+           &(p_rem_node->node_info.sys_guid),
+           sizeof(uint64_t));
+    (*p_num_used_sys)++;
+  }
+
+  return( best_port );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_switch_prepare_path_rebuild(
+  IN osm_switch_t* const p_sw )
+{
+  uint8_t port_num;
+  uint8_t num_ports;
+
+  num_ports = osm_switch_get_num_ports( p_sw );
+  osm_lid_matrix_clear( &p_sw->lmx );
+  for( port_num = 0; port_num < num_ports; port_num++ )
+    osm_port_prof_construct( &p_sw->p_prof[port_num] );
+}
+
+/**********************************************************************
+ **********************************************************************/
+uint8_t
+osm_switch_recommend_mcast_path(
+  IN osm_switch_t*         const p_sw,
+  IN uint16_t              const lid_ho,
+  IN uint16_t              const mlid_ho,
+  IN boolean_t             const ignore_existing )
+{
+  uint8_t                  hops;
+  uint8_t                  port_num;
+  uint8_t                  num_ports;
+  uint8_t                  least_hops;
+
+  CL_ASSERT( lid_ho > 0 );
+  CL_ASSERT( mlid_ho >= IB_LID_MCAST_START_HO );
+
+  num_ports = osm_switch_get_num_ports( p_sw );
+
+  /*
+    If the user wants us to ignore existing multicast routes,
+    then simply return the shortest hop count path to the
+    target port.
+
+    Otherwise, return the first port that has a path to the target,
+    picking from the ports that are already in the multicast group.
+  */
+  if( !ignore_existing )
+  {
+    for( port_num = 1; port_num < num_ports; port_num++ )
+    {
+      if( osm_mcast_tbl_is_port( &p_sw->mcast_tbl, mlid_ho, port_num ) )
+      {
+        /*
+          Don't be too trusting of the current forwarding table!
+          Verify that the LID is reachable through this port.
+        */
+        hops = osm_switch_get_hop_count( p_sw, lid_ho, port_num );
+        if( hops != OSM_NO_PATH )
+        {
+          return( port_num );
+        }
+      }
+    }
+  }
+
+  /*
+    Either no existing mcast paths reach this port or we are
+    ignoring existing paths.
+
+    Determine the best multicast path to the target.  Note that this
+    algorithm is slightly different from the one used for unicast route
+    recommendation.  In this case (multicast), we must NOT
+    perform any sort of load balancing.  We MUST take the FIRST
+    port found that has <= the lowest hop count path.  This prevents
+    more than one multicast path to the same remote switch which
+    prevents a multicast loop.  Multicast loops are bad since the same
+    multicast packet will go around and around, inevitably creating
+    a black hole that will destroy the Earth in a firey conflagration.
+  */
+  least_hops = osm_switch_get_least_hops( p_sw, lid_ho );
+  for( port_num = 0; port_num < num_ports; port_num++ )
+  {
+    if( osm_switch_get_hop_count( p_sw, lid_ho, port_num ) == least_hops )
+      break;
+  }
+
+  CL_ASSERT( port_num < num_ports );
+  return( port_num );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_trap_rcv.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_trap_rcv.c
new file mode 100644 (file)
index 0000000..dbd511c
--- /dev/null
@@ -0,0 +1,771 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_trap_rcv.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_trap_rcv_t.
+ * This object represents the Trap Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.12 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_trap_rcv.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_inform.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ *
+ * TRAP HANDLING:
+ *
+ * Assuming traps can be caused by bad hardware we should provide
+ * a mechanism for filtering their propagation into the actual logic
+ * of OpenSM such that it is not overloaded by them.
+ *
+ * We will provide a trap filtering mechanism with "Aging" capability.
+ * This mechanism will track incoming traps, clasify them by their
+ * source and content and provide back their age.
+ *
+ * A timer running in the background will toggle a timer counter
+ * that should be referenced by the aging algorithm.
+ * To provide an efficient handling of aging. We also track all traps
+ * in a sorted list by their aging.
+ *
+ * The generic Aging Tracker mechanism is implemented in the
+ * cl_aging_tracker object.
+ *
+ **********************************************************************/
+
+typedef struct _osm_trap_aging_tracker_context
+{
+  osm_log_t*       p_log;
+  osm_physp_t*     p_physp;
+} osm_trap_aging_tracker_context_t;
+
+/**********************************************************************
+ **********************************************************************/
+osm_physp_t *
+__get_physp_by_lid_and_num(
+  IN osm_trap_rcv_t* const p_rcv,
+  IN uint16_t lid,
+  IN uint8_t num)
+{
+  cl_ptr_vector_t *p_vec = &(p_rcv->p_subn->port_lid_tbl);
+  osm_port_t *p_port;
+
+  if (lid > cl_ptr_vector_get_size(p_vec))
+    return NULL;
+
+  p_port = (osm_port_t *)cl_ptr_vector_get(p_vec, lid);
+  if (! p_port)
+    return NULL;
+
+  if (osm_port_get_num_physp(p_port) < num)
+    return NULL;
+
+  return( osm_port_get_phys_ptr(p_port, num) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+uint64_t
+osm_trap_rcv_aging_tracker_callback(
+  IN uint64_t key,
+  IN uint32_t num_regs,
+  IN void*     context )
+{
+  osm_trap_rcv_t* p_rcv = (osm_trap_rcv_t*)context;
+  uint16_t lid;
+  uint8_t  port_num;
+  osm_physp_t* p_physp;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_trap_rcv_aging_tracker_callback );
+
+  if (osm_exit_flag)
+    /* We got an exit flag - do nothing */
+    return 0;
+
+  lid = cl_ntoh16((uint16_t)(( key & 0x0000FFFF00000000ULL) >> 32));
+  port_num = (uint8_t)(( key & 0x00FF000000000000ULL) >> 48);
+
+  p_physp = __get_physp_by_lid_and_num( p_rcv, lid, port_num );
+  if (!p_physp)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+            "osm_trap_rcv_aging_tracker_callback: "
+            "Cannot find port num:0x%X with lid:%u\n",
+            port_num, lid );
+  }
+  else
+  {
+    /* make sure the physp is still valid */
+    if ( osm_physp_is_valid(p_physp) )
+    {
+      /* If the health port was false - set it to true */
+      if (!osm_physp_is_healthy(p_physp) )
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+                 "osm_trap_rcv_aging_tracker_callback: "
+                 "Clearing health bit of port num:%u with lid:%u\n",
+                 port_num, lid );
+
+        /* Clear its health bit */
+        osm_physp_set_health(p_physp, TRUE);
+      }
+    }
+  }
+
+  OSM_LOG_EXIT (p_rcv->p_log );
+
+  /* We want to remove the event from the tracker - so
+     need to return zero. */
+  return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_trap_rcv_construct(
+  IN osm_trap_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+  cl_event_wheel_construct( &p_rcv->trap_aging_tracker );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_trap_rcv_destroy(
+  IN osm_trap_rcv_t* const p_rcv )
+{
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_trap_rcv_destroy );
+
+  cl_event_wheel_destroy( &p_rcv->trap_aging_tracker );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_trap_rcv_init(
+  IN osm_trap_rcv_t* const p_rcv,
+  IN osm_subn_t* const p_subn,
+  IN osm_stats_t* const p_stats,
+  IN osm_resp_t* const p_resp,
+  IN osm_log_t* const p_log,
+  IN osm_state_mgr_t* const p_state_mgr,
+  IN cl_plock_t* const p_lock )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_trap_rcv_init );
+
+  osm_trap_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_stats = p_stats;
+  p_rcv->p_resp = p_resp;
+  p_rcv->p_state_mgr = p_state_mgr;
+
+  cl_event_wheel_init( &p_rcv->trap_aging_tracker, p_log );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ * CRC calculation for notice identification
+ **********************************************************************/
+
+#define CRC32_POLYNOMIAL   0xEDB88320L
+
+/* calculate the crc for a given buffer */
+static uint32_t
+__osm_trap_calc_crc32(void *buffer, uint32_t count)
+{
+  uint32_t temp1, temp2;
+  uint32_t crc = -1L;
+  unsigned char *p = (unsigned char *)buffer;
+  /* pre - calculated table for faster crc calculation */
+  static uint32_t crc_table[256];
+  static boolean_t first = TRUE;
+  int i, j;
+
+  /* if we need to initialize the lookup table */
+  if (first)
+  {
+    /* calc the CRC table */
+    for (i = 0; i <= 255; i++)
+    {
+      crc = i;
+      for (j = 8; j > 0; j--)
+        if (crc & 1)
+          crc = (crc >> 1) ^ CRC32_POLYNOMIAL;
+        else
+          crc >>= 1;
+      crc_table[i] = crc;
+    }
+    first = FALSE;
+  }
+
+  crc = -1L;
+  /* do the calculation */
+  while (count-- != 0)
+  {
+    temp1 = (crc >> 8) & 0x00FFFFFFL;
+    temp2 = crc_table[((int)crc ^ *p++) & 0xFF];
+    crc = temp1 ^ temp2;
+  }
+  return crc;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+/* The key is created in the following manner:
+   port_num  lid   crc
+   \______/ \___/ \___/
+     16b     16b   32b
+*/
+static void
+__osm_trap_get_key(
+  IN uint16_t lid,
+  IN uint8_t  port_num,
+  IN ib_mad_notice_attr_t*  p_ntci,
+  OUT uint64_t *trap_key)
+{
+  uint32_t crc = 0;
+
+  CL_ASSERT(trap_key);
+
+  crc = __osm_trap_calc_crc32(p_ntci, sizeof(ib_mad_notice_attr_t));
+  *trap_key = ((uint64_t)port_num << 48) | ((uint64_t)lid << 32) | crc;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static int
+__print_num_received(
+  IN uint32_t num_received )
+{
+  uint32_t i;
+
+  /* Series is 10, 20, 50, 100, 200, 500, ... */
+  i = num_received;
+  while (i >= 10) {
+    if (i % 10)
+      break;
+    i = i / 10;
+  }
+  if (i == 1 || i == 2 || i == 5)
+    return 1;
+  else
+    return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_trap_rcv_process_request(
+  IN osm_trap_rcv_t* const p_rcv,
+  IN const osm_madw_t*     const p_madw )
+{
+  uint8_t               payload[sizeof(ib_mad_notice_attr_t)];
+  ib_smp_t*             p_smp;
+  ib_mad_notice_attr_t* p_ntci = (ib_mad_notice_attr_t*)payload;
+  ib_api_status_t       status;
+  osm_madw_t            tmp_madw; /* we need a copy to last after repress */
+  uint64_t              trap_key;
+  uint32_t              num_received;
+  osm_physp_t*          p_physp;
+  cl_ptr_vector_t*      p_tbl;
+  osm_port_t*           p_port;
+  ib_net16_t            source_lid = 0;
+  boolean_t             is_gsi = TRUE;
+  uint8_t               port_num = 0;
+  boolean_t             physp_change_trap = FALSE;
+  uint64_t              event_wheel_timeout = OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT;
+  boolean_t             run_heavy_sweep = FALSE;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_trap_rcv_process_request );
+
+  CL_ASSERT( p_madw );
+
+  if (osm_exit_flag)
+  {
+    /*
+       We got an exit flag - do nothing
+       Otherwise we start a sweep on the trap 144 caused by cleaning up
+       SM Cap bit...
+    */
+    goto Exit;
+  }
+
+  /* update the is_gsi flag according to the mgmt_class field */
+  if (p_madw->p_mad->mgmt_class == IB_MCLASS_SUBN_LID ||
+      p_madw->p_mad->mgmt_class == IB_MCLASS_SUBN_DIR )
+    is_gsi = FALSE;
+
+  /*
+    No real need to grab the lock for this function.
+  */
+  memset( payload, 0, sizeof( payload ) );
+  memset( &tmp_madw, 0, sizeof( tmp_madw ));
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+
+  if( p_smp->method != IB_MAD_METHOD_TRAP )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_trap_rcv_process_request: ERR 3801: "
+             "Unsupported method 0x%X\n",
+             p_smp->method );
+    goto Exit;
+  }
+
+  /*
+   * The NOTICE Attribute is part of the SMP CLASS attributes
+   * As such the actual attribute data resides inside the SMP
+   * payload.
+   */
+
+  memcpy(payload, &(p_smp->data), IB_SMP_DATA_SIZE);
+  memcpy(&tmp_madw, p_madw, sizeof( tmp_madw ));
+
+  if (is_gsi == FALSE)
+  {
+    /* We are in smi flow */
+    /*
+     * When we received a TRAP with dlid = 0 - it means it
+     * came from our own node. So we need to fix it.
+     */
+
+    if (p_madw->mad_addr.addr_type.smi.source_lid == 0)
+    {
+      /* Check if the sm_base_lid is 0. If yes - this means that
+         the local lid wasn't configured yet. Don't send a response
+         to the trap. */
+      if (p_rcv->p_subn->sm_base_lid == 0)
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+                 "__osm_trap_rcv_process_request: "
+                 "Received SLID=0 Trap with local LID=0. Ignoring MAD\n");
+        goto Exit;
+      }
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+               "__osm_trap_rcv_process_request: "
+               "Received SLID=0 Trap. Using local LID:0x%04X instead\n",
+               cl_ntoh16(p_rcv->p_subn->sm_base_lid)
+               );
+      tmp_madw.mad_addr.addr_type.smi.source_lid = p_rcv->p_subn->sm_base_lid;
+    }
+
+    source_lid = tmp_madw.mad_addr.addr_type.smi.source_lid;
+
+    /* Print some info about the incoming Trap */
+    if (ib_notice_is_generic(p_ntci))
+    {
+      if ((p_ntci->g_or_v.generic.trap_num == CL_HTON16(129)) ||
+           (p_ntci->g_or_v.generic.trap_num == CL_HTON16(130)) ||
+           (p_ntci->g_or_v.generic.trap_num == CL_HTON16(131)))
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                 "__osm_trap_rcv_process_request: "
+                 "Received Generic Notice type:0x%02X num:%u Producer:%u "
+                 "from LID:0x%04X Port %d TID:0x%016" PRIx64 "\n",
+                 ib_notice_get_type(p_ntci),
+                 cl_ntoh16(p_ntci->g_or_v.generic.trap_num),
+                 cl_ntoh32(ib_notice_get_prod_type(p_ntci)),
+                 cl_hton16(source_lid),
+                 p_ntci->data_details.ntc_129_131.port_num,
+                 cl_ntoh64(p_smp->trans_id)
+                 );
+      }
+      else
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                 "__osm_trap_rcv_process_request: "
+                 "Received Generic Notice type:0x%02X num:%u Producer:%u "
+                 "from LID:0x%04X TID:0x%016" PRIx64 "\n",
+                 ib_notice_get_type(p_ntci),
+                 cl_ntoh16(p_ntci->g_or_v.generic.trap_num),
+                 cl_ntoh32(ib_notice_get_prod_type(p_ntci)),
+                 cl_hton16(source_lid),
+                 cl_ntoh64(p_smp->trans_id)
+                 );
+      }
+    }
+    else
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_trap_rcv_process_request: "
+               "Received Vendor Notice type:0x%02X vend:0x%06X dev:%u "
+               "from LID:0x%04X TID:0x%016" PRIx64 "\n",
+               ib_notice_get_type(p_ntci),
+               cl_ntoh32(ib_notice_get_vend_id(p_ntci)),
+               cl_ntoh16(p_ntci->g_or_v.vend.dev_id),
+               cl_ntoh16(source_lid),
+               cl_ntoh64(p_smp->trans_id)
+               );
+    }
+  }
+
+  osm_dump_notice( p_rcv->p_log, p_ntci, OSM_LOG_VERBOSE );
+
+  status = osm_resp_send( p_rcv->p_resp, &tmp_madw, 0, payload );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_trap_rcv_process_request: ERR 3802: "
+             "Error sending response (%s)\n",
+             ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  /*
+   * We would like to filter out recurring Traps so we track them by
+   * their source lid and content. If the same trap was already
+   * received within the aging time window more than 10 times,
+   * we simply ignore it. This is done only if we are in smi mode
+   */
+
+  if (is_gsi == FALSE)
+  {
+    if (ib_notice_is_generic(p_ntci) &&
+        ((p_ntci->g_or_v.generic.trap_num == CL_HTON16(129)) ||
+         (p_ntci->g_or_v.generic.trap_num == CL_HTON16(130)) ||
+         (p_ntci->g_or_v.generic.trap_num == CL_HTON16(131))) )
+    {
+      /* If this is a trap 129, 130, or 131 - then this is a trap
+         signaling a change on a physical port. Mark the flag physp_change_trap as TRUE. */
+      physp_change_trap = TRUE;
+      /* The source_lid should be based on the source_lid from the trap */
+      source_lid = p_ntci->data_details.ntc_129_131.lid;
+    }
+
+    /* If physp_change_trap is TRUE - the key will include the port number.
+       If not - the port_number in the key will be zero. */
+    if ( physp_change_trap == TRUE )
+    {
+      port_num = p_ntci->data_details.ntc_129_131.port_num;
+      __osm_trap_get_key(source_lid, port_num, p_ntci, &trap_key);
+    }
+    else
+      __osm_trap_get_key(source_lid, 0, p_ntci, &trap_key);
+
+    /* try to find it in the aging tracker */
+    num_received = cl_event_wheel_num_regs(&p_rcv->trap_aging_tracker,
+                                           trap_key);
+
+    /* Now we know how many times it provided this trap */
+    if (num_received > 10)
+    {
+      if (__print_num_received(num_received))
+        osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                 "__osm_trap_rcv_process_request: ERR 3804: "
+                 "Received trap %u times consecutively\n",
+                 num_received);
+      /*
+       * If the trap provides info about a bad port
+       * we mark it as unhealthy.
+       */
+      if (physp_change_trap == TRUE)
+      {
+        /* get the port */
+        p_physp = __get_physp_by_lid_and_num(
+          p_rcv,
+          cl_ntoh16(p_ntci->data_details.ntc_129_131.lid),
+          port_num
+          );
+
+        if (! p_physp)
+        {
+          osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                   "__osm_trap_rcv_process_request: ERR 3805: "
+                   "Failed to find physical port by lid:0x%02X num:%u\n",
+                   cl_ntoh16(p_ntci->data_details.ntc_129_131.lid),
+                   p_ntci->data_details.ntc_129_131.port_num
+                   );
+        }
+        else
+        {
+          osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+                   "__osm_trap_rcv_process_request: "
+                   "Marking unhealthy physical port by lid:0x%02X num:%u\n",
+                   cl_ntoh16(p_ntci->data_details.ntc_129_131.lid),
+                   p_ntci->data_details.ntc_129_131.port_num
+                   );
+          /* check if the current state of the p_physp is healthy. If
+             it is - then this is a first change of state. Run a heavy sweep.
+             if it is not - no need to mark it again - just restart the timer. */
+          if ( osm_physp_is_healthy(p_physp) )
+          {
+            osm_physp_set_health(p_physp, FALSE);
+            /* Make sure we sweep again - force a heavy sweep. */
+            /* The sweep should be done only after the re-registration, or
+               else we'll be losing track of the timer. */
+            run_heavy_sweep = TRUE;
+          }
+          /* If we are marking the port as unhealthy - we want to
+             keep this for a longer period of time than the
+             OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT. Use the
+             OSM_DEFAULT_UNHEALTHY_TIMEOUT */
+          event_wheel_timeout = OSM_DEFAULT_UNHEALTHY_TIMEOUT;
+        }
+      }
+    }
+
+    /* restart the aging anyway */
+    /* If physp_change_trap is TRUE - then use a callback to unset the
+       healthy bit. If not - no need to use a callback. */
+    if (physp_change_trap == TRUE )
+      cl_event_wheel_reg(&p_rcv->trap_aging_tracker,
+                         trap_key,
+                         cl_get_time_stamp() + event_wheel_timeout,
+                         osm_trap_rcv_aging_tracker_callback, /* no callback */
+                         p_rcv /* no context */
+                         );
+    else
+      cl_event_wheel_reg(&p_rcv->trap_aging_tracker,
+                         trap_key,
+                         cl_get_time_stamp() + event_wheel_timeout,
+                         NULL, /* no callback */
+                         NULL /* no context */
+                         );
+
+    /* If was already registered do nothing more */
+    if ( num_received > 10 && run_heavy_sweep == FALSE )
+    {
+      if (__print_num_received(num_received))
+        osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+                 "__osm_trap_rcv_process_request: "
+                 "Continuously received this trap %u times. Ignoring it\n",
+                 num_received);
+      goto Exit;
+    }
+  }
+
+  /* do a sweep if we received a trap */
+  if (p_rcv->p_subn->opt.sweep_on_trap)
+  {
+    /* if this is trap number 128 or run_heavy_sweep is TRUE - update the
+       force_single_heavy_sweep flag of the subnet.
+       Sweep also on traps 144/145 - these traps signal a change on a certain
+       port capability/system image guid.
+       TODO: In the future we can change this to just getting PortInfo on
+       this port instead of sweeping the entire subnet. */
+    if (ib_notice_is_generic(p_ntci) &&
+        ( (cl_ntoh16(p_ntci->g_or_v.generic.trap_num) == 128) ||
+          (cl_ntoh16(p_ntci->g_or_v.generic.trap_num) == 144) ||
+          (cl_ntoh16(p_ntci->g_or_v.generic.trap_num) == 145) ||
+          run_heavy_sweep ))
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+               "__osm_trap_rcv_process_request: "
+               "Forcing immediate heavy sweep. "
+               "Received trap:%u\n",
+               cl_ntoh16(p_ntci->g_or_v.generic.trap_num) );
+
+      p_rcv->p_subn->force_immediate_heavy_sweep = TRUE;
+    }
+    osm_state_mgr_process( p_rcv->p_state_mgr, OSM_SIGNAL_SWEEP );
+  }
+
+  /* If we reached here due to trap 129/130/131 - do not need to do
+     the notice report. Just goto exit. We know this is the case
+     if physp_change_trap is TRUE. */
+  if ( physp_change_trap == TRUE )
+    goto Exit;
+
+  /* Add a call to osm_report_notice */
+  /* We are going to report the notice - so need to fix the IssuerGID
+     accordingly. See IBA 1.1 P.653 or IBA 1.2 P.739 for details. */
+  if (is_gsi)
+  {
+    if (tmp_madw.mad_addr.addr_type.gsi.global_route)
+    {
+      memcpy(&(p_ntci->issuer_gid),
+             &(tmp_madw.mad_addr.addr_type.gsi.grh_info.src_gid),
+             sizeof(ib_gid_t));
+    }
+    else
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_trap_rcv_process_request: ERR 3806: "
+               "Received gsi trap with global_route FALSE. "
+               "Cannot update issuer_gid!\n" );
+      goto Exit;
+    }
+  }
+  else
+  {
+    /* Need to use the IssuerLID */
+    p_tbl = &p_rcv->p_subn->port_lid_tbl;
+
+    CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 );
+
+    if ((uint16_t)cl_ptr_vector_get_size(p_tbl) <= cl_ntoh16(source_lid) )
+    {
+      /*  the source lid is out of range */
+      osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+               "__osm_trap_rcv_process_request: "
+               "source lid is out of range:0x%X\n",
+               cl_ntoh16(source_lid) );
+
+      goto Exit;
+    }
+    p_port = cl_ptr_vector_get( p_tbl, cl_ntoh16(source_lid) );
+    if ( p_port == 0)
+    {
+      /* We have the lid - but no corresponding port */
+      osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+               "__osm_trap_rcv_process_request: "
+               "Cannot find port according to lid:0x%X\n",
+               cl_ntoh16(source_lid) );
+
+      goto Exit;
+    }
+
+    p_ntci->issuer_gid.unicast.prefix = p_rcv->p_subn->opt.subnet_prefix;
+    p_ntci->issuer_gid.unicast.interface_id = p_port->guid;
+  }
+
+  /* we need a lock here as the InformInfo DB must be stable */
+  CL_PLOCK_ACQUIRE( p_rcv->p_lock );
+  status = osm_report_notice(p_rcv->p_log, p_rcv->p_subn, p_ntci);
+  CL_PLOCK_RELEASE( p_rcv->p_lock );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_trap_rcv_process_request: ERR 3803: "
+             "Error sending trap reports (%s)\n",
+             ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+#if 0
+/**********************************************************************
+ CURRENTLY WE ARE NOT CREATING TRAPS - SO THIS CALL IS AN ERROR
+**********************************************************************/
+static void
+__osm_trap_rcv_process_sm(
+  IN const osm_trap_rcv_t* const p_rcv,
+  IN const osm_remote_sm_t*   const p_sm )
+{
+  /*   const ib_sm_info_t*        p_smi; */
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_trap_rcv_process_sm );
+
+  osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+           "__osm_trap_rcv_process_sm: ERR 3807: "
+           "This function is not supported yet\n");
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+#endif
+
+/**********************************************************************
+ CURRENTLY WE ARE NOT CREATING TRAPS - SO THIS CALL IN AN ERROR
+**********************************************************************/
+static void
+__osm_trap_rcv_process_response(
+  IN const osm_trap_rcv_t* const p_rcv,
+  IN const osm_madw_t*     const p_madw )
+{
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_trap_rcv_process_response );
+
+  osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+           "__osm_trap_rcv_process_response: ERR 3808: "
+           "This function is not supported yet\n");
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_trap_rcv_process(
+  IN osm_trap_rcv_t* const p_rcv,
+  IN osm_madw_t* const p_madw )
+{
+  ib_smp_t *p_smp;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_trap_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+
+  /*
+    Determine if this is a request for our own Trap
+    or if this is a response to our request for another
+    SM's Trap.
+  */
+  if( ib_smp_is_response( p_smp ) )
+  {
+    __osm_trap_rcv_process_response( p_rcv, p_madw );
+  }
+  else
+  {
+    __osm_trap_rcv_process_request( p_rcv, p_madw );
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_trap_rcv_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_trap_rcv_ctrl.c
new file mode 100644 (file)
index 0000000..2a33133
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_trap_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_trap_rcv_ctrl_t.
+ * This object represents the Trap request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_trap_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_trap_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_trap_rcv_process( ((osm_trap_rcv_ctrl_t*)context)->p_rcv,
+                        (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_trap_rcv_ctrl_construct(
+  IN osm_trap_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_trap_rcv_ctrl_destroy(
+  IN osm_trap_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_trap_rcv_ctrl_init(
+  IN osm_trap_rcv_ctrl_t* const p_ctrl,
+  IN osm_trap_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_trap_rcv_ctrl_init );
+
+  osm_trap_rcv_ctrl_construct( p_ctrl );
+
+  p_ctrl->p_log = p_log;
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_NOTICE,
+    __osm_trap_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_trap_rcv_ctrl_init: ERR 3901: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_file.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_file.c
new file mode 100644 (file)
index 0000000..424fed2
--- /dev/null
@@ -0,0 +1,413 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of OpenSM unicast routing module which loads
+ *    routes from the dump file
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif                         /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_log.h>
+
+
+static uint16_t remap_lid(osm_opensm_t *p_osm, uint16_t lid, ib_net64_t guid)
+{
+       osm_port_t *p_port;
+       uint16_t min_lid, max_lid;
+       uint8_t lmc;
+
+       p_port = (osm_port_t *)cl_qmap_get(&p_osm->subn.port_guid_tbl, guid);
+       if (!p_port ||
+           p_port == (osm_port_t *)cl_qmap_end(&p_osm->subn.port_guid_tbl)) {
+               osm_log(&p_osm->log, OSM_LOG_VERBOSE,
+                       "remap_lid: cannot find port guid 0x%016" PRIx64
+                       " , will use the same lid\n", cl_ntoh64(guid));
+               return lid;
+       }
+
+       osm_port_get_lid_range_ho(p_port, &min_lid, &max_lid);
+       if (min_lid <= lid && lid <= max_lid)
+               return lid;
+
+       lmc = osm_port_get_lmc(p_port);
+       return min_lid + (lid & ((1 << lmc) - 1));
+}
+
+static void add_path(osm_opensm_t * p_osm,
+                    osm_switch_t * p_sw, uint16_t lid, uint8_t port_num,
+                    ib_net64_t port_guid)
+{
+       uint16_t new_lid;
+       uint8_t old_port;
+
+       new_lid = port_guid ? remap_lid(p_osm, lid, port_guid) : lid;
+       old_port = osm_fwd_tbl_get(osm_switch_get_fwd_tbl_ptr(p_sw), new_lid);
+       if (old_port != OSM_NO_PATH && old_port != port_num) {
+               osm_log(&p_osm->log, OSM_LOG_VERBOSE,
+                       "add_path: LID collision is detected on switch "
+                       "0x016%" PRIx64 ", will overwrite LID 0x%x entry\n",
+                       cl_ntoh64(osm_node_get_node_guid
+                                 (osm_switch_get_node_ptr(p_sw))), new_lid);
+       }
+
+       p_osm->sm.ucast_mgr.lft_buf[new_lid] = port_num;
+       if (!(p_osm->subn.opt.port_profile_switch_nodes && port_guid &&
+             osm_get_switch_by_guid(&p_osm->subn, port_guid)))
+               osm_switch_count_path(p_sw, port_num);
+
+       osm_log(&p_osm->log, OSM_LOG_DEBUG,
+               "add_path: route 0x%04x(was 0x%04x) %u 0x%016" PRIx64
+               " is added to switch 0x%016" PRIx64 "\n",
+               new_lid, lid, port_num, cl_ntoh64(port_guid),
+               cl_ntoh64(osm_node_get_node_guid
+                         (osm_switch_get_node_ptr(p_sw))));
+}
+
+static void add_lid_hops(osm_opensm_t *p_osm, osm_switch_t *p_sw,
+                        uint16_t lid, ib_net64_t guid,
+                        uint8_t hops[], unsigned len)
+{
+       uint16_t new_lid;
+       uint8_t i;
+
+       new_lid = guid ? remap_lid(p_osm, lid, guid) : lid;
+       if (len > osm_switch_get_num_ports(p_sw))
+               len = osm_switch_get_num_ports(p_sw);
+
+       for (i = 0 ; i < len ; i++)
+               osm_switch_set_hops(p_sw, lid, i, hops[i]);
+}
+
+static int do_ucast_file_load(void *context)
+{
+       char line[1024];
+       char *file_name;
+       FILE *file;
+       ib_net64_t sw_guid, port_guid;
+       osm_opensm_t *p_osm = context;
+       osm_switch_t *p_sw;
+       uint16_t lid;
+       uint8_t port_num;
+       unsigned lineno;
+
+       file_name = p_osm->subn.opt.ucast_dump_file;
+       if (!file_name) {
+               osm_log(&p_osm->log, OSM_LOG_ERROR|OSM_LOG_SYS,
+                       "do_ucast_file_load: ERR 6301: "
+                       "ucast dump file name is not defined; "
+                       "using default routing algorithm\n");
+               return -1;
+       }
+
+       file = fopen(file_name, "r");
+       if (!file) {
+               osm_log(&p_osm->log, OSM_LOG_ERROR|OSM_LOG_SYS,
+                       "do_ucast_file_load: ERR 6302: "
+                       "cannot open ucast dump file \'%s\'; "
+                       "using default routing algorithm\n", file_name);
+               return -1;
+       }
+
+       lineno = 0;
+       p_sw = NULL;
+
+       while (fgets(line, sizeof(line) - 1, file) != NULL) {
+               char *p, *q;
+               lineno++;
+
+               p = line;
+               while (isspace(*p))
+                       p++;
+
+               if (*p == '#')
+                       continue;
+
+               if (!strncmp(p, "Multicast mlids", 15)) {
+                       osm_log(&p_osm->log, OSM_LOG_ERROR|OSM_LOG_SYS,
+                               "do_ucast_file_load: ERR 6303: "
+                               "Multicast dump file detected; "
+                               "skipping parsing. Using default "
+                               "routing algorithm\n");
+               } else if (!strncmp(p, "Unicast lids", 12)) {
+                       if (p_sw)
+                               osm_ucast_mgr_set_fwd_table(&p_osm->sm.ucast_mgr, p_sw);
+                       q = strstr(p, " guid 0x");
+                       if (!q) {
+                               osm_log(&p_osm->log, OSM_LOG_ERROR,
+                                       "PARSE ERROR: %s:%u: "
+                                       "cannot parse switch definition\n",
+                                       file_name, lineno);
+                               return -1;
+                       }
+                       p = q + 8;
+                       sw_guid = strtoull(p, &q, 16);
+                       if (q == p || !isspace(*q)) {
+                               osm_log(&p_osm->log, OSM_LOG_ERROR,
+                                       "PARSE ERROR: %s:%u: "
+                                       "cannot parse switch guid: \'%s\'\n",
+                                       file_name, lineno, p);
+                               return -1;
+                       }
+                       sw_guid = cl_hton64(sw_guid);
+
+                       p_sw = osm_get_switch_by_guid(&p_osm->subn, sw_guid);
+                       if (!p_sw) {
+                               osm_log(&p_osm->log, OSM_LOG_VERBOSE,
+                                       "do_ucast_file_load: "
+                                       "cannot find switch %016" PRIx64 "\n",
+                                       cl_ntoh64(sw_guid));
+                               continue;
+                       }
+                       memset(p_osm->sm.ucast_mgr.lft_buf, 0xff, IB_LID_UCAST_END_HO + 1);
+               } else if (p_sw && !strncmp(p, "0x", 2)) {
+                       p += 2;
+                       lid = (uint16_t)strtoul(p, &q, 16);
+                       if (q == p || !isspace(*q)) {
+                               osm_log(&p_osm->log, OSM_LOG_ERROR,
+                                       "PARSE ERROR: %s:%u: "
+                                       "cannot parse lid: \'%s\'\n",
+                                       file_name, lineno, p);
+                               return -1;
+                       }
+                       p = q;
+                       while (isspace(*p))
+                               p++;
+                       port_num = (uint8_t)strtoul(p, &q, 10);
+                       if (q == p || !isspace(*q)) {
+                               osm_log(&p_osm->log, OSM_LOG_ERROR,
+                                       "PARSE ERROR: %s:%u: "
+                                       "cannot parse port: \'%s\'\n",
+                                       file_name, lineno, p);
+                               return -1;
+                       }
+                       p = q;
+                       /* additionally try to exract guid */
+                       q = strstr(p, " portguid 0x");
+                       if (!q) {
+                               osm_log(&p_osm->log, OSM_LOG_VERBOSE,
+                                       "PARSE WARNING: %s:%u: "
+                                       "cannot find port guid "
+                                       "(maybe broken dump): \'%s\'\n",
+                                       file_name, lineno, p);
+                               port_guid = 0;
+                       }
+                       else {
+                               p = q + 12;
+                               port_guid = strtoull(p, &q, 16);
+                               if (q == p || (!isspace(*q) && *q != ':')) {
+                                       osm_log(&p_osm->log, OSM_LOG_VERBOSE,
+                                               "PARSE WARNING: %s:%u: "
+                                               "cannot parse port guid "
+                                               "(maybe broken dump): \'%s\'\n",
+                                               file_name, lineno, p);
+                                       port_guid = 0;
+                               }
+                       }
+                       port_guid = cl_hton64(port_guid);
+                       add_path(p_osm, p_sw, lid, port_num, port_guid);
+               }
+       }
+
+       if (p_sw)
+               osm_ucast_mgr_set_fwd_table(&p_osm->sm.ucast_mgr, p_sw);
+
+       fclose(file);
+       return 0;
+}
+
+static int do_lid_matrix_file_load(void *context)
+{
+       char line[1024];
+       uint8_t hops[256];
+       char *file_name;
+       FILE *file;
+       ib_net64_t guid;
+       osm_opensm_t *p_osm = context;
+       osm_switch_t *p_sw;
+       unsigned lineno;
+       uint16_t lid;
+
+       file_name = p_osm->subn.opt.lid_matrix_dump_file;
+       if (!file_name) {
+               osm_log(&p_osm->log, OSM_LOG_ERROR|OSM_LOG_SYS,
+                       "do_lid_matrix_file_load: ERR 6304: "
+                       "lid matrix file name is not defined; "
+                       "using default lid matrix generation algorithm\n");
+               return -1;
+       }
+
+       file = fopen(file_name, "r");
+       if (!file) {
+               osm_log(&p_osm->log, OSM_LOG_ERROR|OSM_LOG_SYS,
+                       "do_lid_matrix_file_load: ERR 6305: "
+                       "cannot open lid matrix file \'%s\'; "
+                       "using default lid matrix generation algorithm\n",
+                       file_name);
+               return -1;
+       }
+
+       lineno = 0;
+       p_sw = NULL;
+
+       while (fgets(line, sizeof(line) - 1, file) != NULL) {
+               char *p, *q;
+               lineno++;
+
+               p = line;
+               while (isspace(*p))
+                       p++;
+
+               if (*p == '#')
+                       continue;
+
+               if (!strncmp(p, "Switch", 6)) {
+                       q = strstr(p, " guid 0x");
+                       if (!q) {
+                               osm_log(&p_osm->log, OSM_LOG_ERROR,
+                                       "PARSE ERROR: %s:%u: "
+                                       "cannot parse switch definition\n",
+                                       file_name, lineno);
+                               return -1;
+                       }
+                       p = q + 8;
+                       guid = strtoull(p, &q, 16);
+                       if (q == p || !isspace(*q)) {
+                               osm_log(&p_osm->log, OSM_LOG_ERROR,
+                                       "PARSE ERROR: %s:%u: "
+                                       "cannot parse switch guid: \'%s\'\n",
+                                       file_name, lineno, p);
+                               return -1;
+                       }
+                       guid = cl_hton64(guid);
+
+                       p_sw = osm_get_switch_by_guid(&p_osm->subn, guid);
+                       if (!p_sw) {
+                               osm_log(&p_osm->log, OSM_LOG_VERBOSE,
+                                       "do_lid_matrix_file_load: "
+                                       "cannot find switch %016" PRIx64 "\n",
+                                       cl_ntoh64(guid));
+                               continue;
+                       }
+               } else if (p_sw && !strncmp(p, "0x", 2)) {
+                       unsigned long num;
+                       unsigned len = 0;
+
+                       memset(hops, 0xff, sizeof(hops));
+
+                       p += 2;
+                       num = strtoul(p, &q, 16);
+                       if (num > 0xffff || q == p ||
+                           (*q != ':' && !isspace(*q))) {
+                               osm_log(&p_osm->log, OSM_LOG_ERROR,
+                                       "PARSE ERROR: %s:%u: "
+                                       "cannot parse lid: \'%s\'\n",
+                                       file_name, lineno, p);
+                               return -1;
+                       }
+                       /* Just checked the range, so casting is safe */
+                       lid = (uint16_t)num;
+                       p = q;
+                       while (isspace(*p) || *p == ':')
+                               p++;
+                       while (len < 256 && *p && *p != '#') {
+                               num = strtoul(p, &q, 16);
+                               if (num > 0xff || q == p) {
+                                       osm_log(&p_osm->log, OSM_LOG_ERROR,
+                                       "PARSE ERROR: %s:%u: "
+                                       "cannot parse hops number: \'%s\'\n",
+                                       file_name, lineno, p);
+                                       return -1;
+                               }
+                               /* Just checked the range, so casting is safe */
+                               hops[len++] = (uint8_t)num;
+                               p = q;
+                               while (isspace(*p))
+                                       p++;
+                       }
+                       /* additionally try to extract guid */
+                       q = strstr(p, " portguid 0x");
+                       if (!q) {
+                               osm_log(&p_osm->log, OSM_LOG_VERBOSE,
+                                       "PARSE WARNING: %s:%u: "
+                                       "cannot find port guid "
+                                       "(maybe broken dump): \'%s\'\n",
+                                       file_name, lineno, p);
+                               guid = 0;
+                       }
+                       else {
+                               p = q + 12;
+                               guid = strtoull(p, &q, 16);
+                               if (q == p || !isspace(*q)) {
+                                       osm_log(&p_osm->log, OSM_LOG_VERBOSE,
+                                               "PARSE WARNING: %s:%u: "
+                                               "cannot parse port guid "
+                                               "(maybe broken dump): \'%s\'\n",
+                                               file_name, lineno, p);
+                                       guid = 0;
+                               }
+                       }
+                       guid = cl_hton64(guid);
+                       add_lid_hops(p_osm, p_sw, lid, guid, hops, len);
+               }
+       }
+
+       fclose(file);
+       return 0;
+}
+
+int osm_ucast_file_setup(osm_opensm_t * p_osm)
+{
+       p_osm->routing_engine.context = (void *)p_osm;
+       p_osm->routing_engine.build_lid_matrices = do_lid_matrix_file_load;
+       p_osm->routing_engine.ucast_build_fwd_tables = do_ucast_file_load;
+       return 0;
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_ftree.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_ftree.c
new file mode 100644 (file)
index 0000000..6a8eae2
--- /dev/null
@@ -0,0 +1,3141 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of OpenSM FatTree routing
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_pool.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_switch.h>
+
+/*
+ * FatTree rank is bounded between 2 and 8:
+ *  - Tree of rank 1 has only trivial routing pathes,
+ *    so no need to use FatTree routing.
+ *  - Why maximum rank is 8:
+ *    Each node (switch) is assigned a unique tuple.
+ *    Switches are stored in two cl_qmaps - one is 
+ *    ordered by guid, and the other by a key that is
+ *    generated from tuple. Since cl_qmap supports only
+ *    a 64-bit key, the maximal tuple lenght is 8 bytes.
+ *    which means that maximal tree rank is 8.
+ * Note that the above also implies that each switch 
+ * can have at max 255 up/down ports.
+ */
+
+#define FAT_TREE_MIN_RANK 2
+#define FAT_TREE_MAX_RANK 8
+
+typedef enum {
+   FTREE_DIRECTION_DOWN = -1,
+   FTREE_DIRECTION_SAME,
+   FTREE_DIRECTION_UP
+} ftree_direction_t;
+
+
+/***************************************************
+ **
+ **  Forward references
+ **
+ ***************************************************/
+
+struct ftree_sw_t_;
+struct ftree_hca_t_;
+struct ftree_port_t_;
+struct ftree_port_group_t_;
+struct ftree_fabric_t_;
+
+/***************************************************
+ **
+ **  ftree_tuple_t definition
+ **
+ ***************************************************/
+
+#define FTREE_TUPLE_BUFF_LEN 1024
+#define FTREE_TUPLE_LEN 8
+
+typedef uint8_t ftree_tuple_t[FTREE_TUPLE_LEN];
+typedef uint64_t ftree_tuple_key_t;
+
+/***************************************************
+ **
+ **  ftree_sw_table_element_t definition
+ **
+ ***************************************************/
+
+typedef struct {
+   cl_map_item_t map_item;
+   struct ftree_sw_t_ * p_sw;
+} ftree_sw_tbl_element_t;
+
+/***************************************************
+ **
+ **  ftree_fwd_tbl_t definition
+ **
+ ***************************************************/
+
+typedef uint8_t * ftree_fwd_tbl_t;
+#define FTREE_FWD_TBL_LEN (IB_LID_UCAST_END_HO + 1)
+
+/***************************************************
+ **
+ **  ftree_port_t definition
+ **
+ ***************************************************/
+
+typedef struct ftree_port_t_ 
+{
+   cl_map_item_t  map_item;
+   uint8_t        port_num;           /* port number on the current node */
+   uint8_t        remote_port_num;    /* port number on the remote node */
+   uint32_t       counter_up;         /* number of allocated routs upwards */
+   uint32_t       counter_down;       /* number of allocated routs downwards */
+} ftree_port_t;
+
+/***************************************************
+ **
+ **  ftree_port_group_t definition
+ **
+ ***************************************************/
+
+typedef struct ftree_port_group_t_
+{
+   cl_map_item_t  map_item;
+   ib_net16_t     base_lid;           /* base lid of the current node */
+   ib_net16_t     remote_base_lid;    /* base lid of the remote node */
+   ib_net64_t     port_guid;          /* port guid of this port */
+   ib_net64_t     remote_port_guid;   /* port guid of the remote port */
+   ib_net64_t     remote_node_guid;   /* node guid of the remote node */
+   uint8_t        remote_node_type;   /* IB_NODE_TYPE_{CA,SWITCH,ROUTER,...} */
+   union remote_hca_or_sw_
+   {
+      struct ftree_hca_t_ * remote_hca;
+      struct ftree_sw_t_  * remote_sw;
+   } remote_hca_or_sw;                /* pointer to remote hca/switch */
+   cl_ptr_vector_t ports;             /* vector of ports to the same lid */
+} ftree_port_group_t;
+
+/***************************************************
+ **
+ **  ftree_sw_t definition
+ **
+ ***************************************************/
+
+typedef struct ftree_sw_t_ 
+{
+   cl_map_item_t          map_item;
+   osm_switch_t         * p_osm_sw;
+   uint8_t                rank;
+   ftree_tuple_t          tuple;
+   ib_net16_t             base_lid;
+   ftree_port_group_t  ** down_port_groups;
+   uint8_t                down_port_groups_num;
+   ftree_port_group_t  ** up_port_groups;
+   uint8_t                up_port_groups_num;
+   ftree_fwd_tbl_t        lft_buf;
+} ftree_sw_t;
+
+/***************************************************
+ **
+ **  ftree_hca_t definition
+ **
+ ***************************************************/
+
+typedef struct ftree_hca_t_ {
+   cl_map_item_t          map_item;
+   osm_node_t           * p_osm_node;
+   ftree_port_group_t  ** up_port_groups;
+   uint16_t               up_port_groups_num;
+} ftree_hca_t;
+
+/***************************************************
+ **
+ **  ftree_fabric_t definition
+ **
+ ***************************************************/
+
+typedef struct ftree_fabric_t_ 
+{
+   osm_opensm_t  * p_osm;
+   cl_qmap_t       hca_tbl;
+   cl_qmap_t       sw_tbl;
+   cl_qmap_t       sw_by_tuple_tbl;
+   uint8_t         tree_rank;
+   ftree_sw_t   ** leaf_switches;
+   uint32_t        leaf_switches_num;
+   uint16_t        max_hcas_per_leaf;
+   cl_pool_t       sw_fwd_tbl_pool;
+   uint16_t        lft_max_lid_ho;
+   boolean_t       fabric_built;
+} ftree_fabric_t;
+
+/***************************************************
+ **
+ ** comparators
+ **
+ ***************************************************/
+
+static int OSM_CDECL
+__osm_ftree_compare_switches_by_index(
+   IN  const void * p1, 
+   IN  const void * p2)
+{
+   ftree_sw_t ** pp_sw1 = (ftree_sw_t **)p1; 
+   ftree_sw_t ** pp_sw2 = (ftree_sw_t **)p2; 
+
+   uint16_t i;
+   for (i = 0; i < FTREE_TUPLE_LEN; i++)
+   {
+      if ((*pp_sw1)->tuple[i] > (*pp_sw2)->tuple[i])
+         return 1;
+      if ((*pp_sw1)->tuple[i] < (*pp_sw2)->tuple[i])
+         return -1;
+   }
+   return 0;
+}
+
+/***************************************************/
+
+static int OSM_CDECL
+__osm_ftree_compare_port_groups_by_remote_switch_index(
+   IN  const void * p1, 
+   IN  const void * p2)
+{
+   ftree_port_group_t ** pp_g1 = (ftree_port_group_t **)p1; 
+   ftree_port_group_t ** pp_g2 = (ftree_port_group_t **)p2; 
+
+   return __osm_ftree_compare_switches_by_index( 
+                  &((*pp_g1)->remote_hca_or_sw.remote_sw),
+                  &((*pp_g2)->remote_hca_or_sw.remote_sw) );
+}
+
+/***************************************************/
+
+boolean_t
+__osm_ftree_sw_less_by_index(
+   IN  ftree_sw_t * p_sw1,
+   IN  ftree_sw_t * p_sw2)
+{
+   if (__osm_ftree_compare_switches_by_index((void *)&p_sw1,
+                                             (void *)&p_sw2) < 0)
+      return TRUE;
+   return FALSE;
+}
+
+/***************************************************/
+
+boolean_t
+__osm_ftree_sw_greater_by_index(
+   IN  ftree_sw_t * p_sw1,
+   IN  ftree_sw_t * p_sw2)
+{
+   if (__osm_ftree_compare_switches_by_index((void *)&p_sw1,
+                                             (void *)&p_sw2) > 0)
+      return TRUE;
+   return FALSE;
+}
+
+/***************************************************
+ **
+ ** ftree_tuple_t functions
+ **
+ ***************************************************/
+
+static void 
+__osm_ftree_tuple_init(
+   IN  ftree_tuple_t tuple)
+{
+   memset(tuple, 0xFF, FTREE_TUPLE_LEN);
+}
+
+/***************************************************/
+
+static inline boolean_t
+__osm_ftree_tuple_assigned(
+   IN  ftree_tuple_t tuple)
+{
+   return (tuple[0] != 0xFF);
+}
+
+/***************************************************/
+
+#define FTREE_TUPLE_BUFFERS_NUM 6
+
+static char * 
+__osm_ftree_tuple_to_str(
+   IN  ftree_tuple_t tuple)
+{
+   static char buffer[FTREE_TUPLE_BUFFERS_NUM][FTREE_TUPLE_BUFF_LEN];
+   static uint8_t ind = 0;
+   char * ret_buffer;
+   uint32_t i;
+
+   if (!__osm_ftree_tuple_assigned(tuple))
+      return "INDEX.NOT.ASSIGNED";
+
+   buffer[ind][0] = '\0';
+
+   for(i = 0; (i < FTREE_TUPLE_LEN) && (tuple[i] != 0xFF); i++)
+   {
+      if ((strlen(buffer[ind]) + 10) > FTREE_TUPLE_BUFF_LEN)
+         return "INDEX.TOO.LONG";
+      if (i != 0)
+         strcat(buffer[ind],".");
+      sprintf(&buffer[ind][strlen(buffer[ind])], "%u", tuple[i]);
+   }
+
+   ret_buffer = buffer[ind];
+   ind = (ind + 1) % FTREE_TUPLE_BUFFERS_NUM;
+   return ret_buffer;
+} /* __osm_ftree_tuple_to_str() */
+
+/***************************************************/
+
+static inline ftree_tuple_key_t 
+__osm_ftree_tuple_to_key(
+   IN  ftree_tuple_t tuple)
+{
+   ftree_tuple_key_t key;
+   memcpy(&key, tuple, FTREE_TUPLE_LEN);
+   return key;
+}
+
+/***************************************************/
+
+static inline void 
+__osm_ftree_tuple_from_key(
+   IN  ftree_tuple_t tuple, 
+   IN  ftree_tuple_key_t key)
+{
+   memcpy(tuple, &key, FTREE_TUPLE_LEN);
+}
+
+/***************************************************
+ **
+ ** ftree_sw_tbl_element_t functions
+ **
+ ***************************************************/
+
+static ftree_sw_tbl_element_t *
+__osm_ftree_sw_tbl_element_create(
+   IN  ftree_sw_t * p_sw)
+{
+   ftree_sw_tbl_element_t * p_element = 
+      (ftree_sw_tbl_element_t *) malloc(sizeof(ftree_sw_tbl_element_t));
+   if (!p_element)
+       return NULL;
+   memset(p_element, 0,sizeof(ftree_sw_tbl_element_t));
+
+   if (p_element)
+      p_element->p_sw = p_sw;
+   return p_element;
+}
+
+/***************************************************/
+
+static void
+__osm_ftree_sw_tbl_element_destroy(
+   IN  ftree_sw_tbl_element_t * p_element)
+{
+   if (!p_element)
+      return;
+   free(p_element);
+}
+
+/***************************************************
+ **
+ ** ftree_port_t functions
+ **
+ ***************************************************/
+
+static ftree_port_t * 
+__osm_ftree_port_create( 
+   IN  uint8_t port_num,
+   IN  uint8_t remote_port_num)
+{
+   ftree_port_t * p_port = (ftree_port_t *)malloc(sizeof(ftree_port_t));
+   if (!p_port)
+      return NULL;
+   memset(p_port,0,sizeof(ftree_port_t));
+
+   p_port->port_num = port_num;
+   p_port->remote_port_num = remote_port_num;
+
+   return p_port;
+}
+
+/***************************************************/
+
+static void 
+__osm_ftree_port_destroy(
+   IN  ftree_port_t * p_port)
+{
+   if(p_port)
+      free(p_port);
+}
+
+/***************************************************
+ **
+ ** ftree_port_group_t functions
+ **
+ ***************************************************/
+
+static ftree_port_group_t * 
+__osm_ftree_port_group_create( 
+   IN  ib_net16_t    base_lid,
+   IN  ib_net16_t    remote_base_lid,
+   IN  ib_net64_t  * p_port_guid,
+   IN  ib_net64_t  * p_remote_port_guid,
+   IN  ib_net64_t  * p_remote_node_guid,
+   IN  uint8_t       remote_node_type,
+   IN  void        * p_remote_hca_or_sw)
+{
+   ftree_port_group_t * p_group = 
+            (ftree_port_group_t *)malloc(sizeof(ftree_port_group_t));
+   if (p_group == NULL) 
+      return NULL;
+   memset(p_group, 0, sizeof(ftree_port_group_t));
+
+   p_group->base_lid = base_lid;
+   p_group->remote_base_lid = remote_base_lid;
+   memcpy(&p_group->port_guid, p_port_guid, sizeof(ib_net64_t));
+   memcpy(&p_group->remote_port_guid, p_remote_port_guid, sizeof(ib_net64_t));
+   memcpy(&p_group->remote_node_guid, p_remote_node_guid, sizeof(ib_net64_t));
+
+   p_group->remote_node_type = remote_node_type;
+   switch (remote_node_type)
+   {
+      case IB_NODE_TYPE_CA:
+         p_group->remote_hca_or_sw.remote_hca = (ftree_hca_t *)p_remote_hca_or_sw;
+         break;
+      case IB_NODE_TYPE_SWITCH:
+         p_group->remote_hca_or_sw.remote_sw = (ftree_sw_t *)p_remote_hca_or_sw;
+         break;
+      default:
+         /* we shouldn't get here - port is created only in hca or switch */
+         CL_ASSERT(0);
+   }
+
+   cl_ptr_vector_init(&p_group->ports,
+                      0,  /* min size */
+                      8); /* grow size */
+   return p_group;
+} /* __osm_ftree_port_group_create() */
+
+/***************************************************/
+
+static void 
+__osm_ftree_port_group_destroy(
+   IN  ftree_port_group_t * p_group)
+{
+   uint32_t i;
+   uint32_t size;
+   ftree_port_t * p_port;
+
+   if (!p_group)
+      return;
+
+   /* remove all the elements of p_group->ports vector */
+   size = cl_ptr_vector_get_size(&p_group->ports);
+   for (i = 0; i < size; i++)
+   {
+      cl_ptr_vector_at(&p_group->ports, i, (void **)&p_port);
+      __osm_ftree_port_destroy(p_port);
+   }
+   cl_ptr_vector_destroy(&p_group->ports);
+   free(p_group);
+} /* __osm_ftree_port_group_destroy() */
+
+/***************************************************/
+
+static void 
+__osm_ftree_port_group_dump(
+   IN  ftree_fabric_t *p_ftree,
+   IN  ftree_port_group_t * p_group,
+   IN  ftree_direction_t direction)
+{
+   ftree_port_t * p_port;
+   uint32_t size;
+   uint32_t i;
+   char buff[10*1024];
+
+   if (!p_group)
+      return;
+
+   if (!osm_log_is_active(&p_ftree->p_osm->log, OSM_LOG_DEBUG))
+      return;
+
+   size = cl_ptr_vector_get_size(&p_group->ports);
+   buff[0] = '\0';
+
+   for (i = 0; i < size; i++)
+   {
+      cl_ptr_vector_at(&p_group->ports, i, (void **)&p_port);
+      CL_ASSERT(p_port);
+
+      if (i != 0)
+         strcat(buff,", ");
+      sprintf(buff + strlen(buff), "%u", p_port->port_num);
+   }
+
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+           "__osm_ftree_port_group_dump:"
+           "    Port Group of size %u, port(s): %s, direction: %s\n" 
+           "                  Local <--> Remote GUID (LID):"
+           "0x%016" PRIx64 " (0x%x) <--> 0x%016" PRIx64 " (0x%x)\n", 
+           size,
+           buff,
+           (direction == FTREE_DIRECTION_DOWN)? "DOWN" : "UP",
+           cl_ntoh64(p_group->port_guid),
+           cl_ntoh16(p_group->base_lid),
+           cl_ntoh64(p_group->remote_port_guid),
+           cl_ntoh16(p_group->remote_base_lid));
+
+} /* __osm_ftree_port_group_dump() */
+
+/***************************************************/
+
+static void
+__osm_ftree_port_group_add_port(
+   IN  ftree_port_group_t * p_group,
+   IN  uint8_t              port_num,
+   IN  uint8_t              remote_port_num)
+{
+   uint16_t i;
+   ftree_port_t * p_port;
+
+   for (i = 0; i < cl_ptr_vector_get_size(&p_group->ports); i++)
+   {
+      cl_ptr_vector_at(&p_group->ports, i, (void **)&p_port);
+      if (p_port->port_num == port_num)
+         return;
+   }
+
+   p_port = __osm_ftree_port_create(port_num,remote_port_num);
+   cl_ptr_vector_insert(&p_group->ports, p_port, NULL);
+}
+
+/***************************************************
+ **
+ ** ftree_sw_t functions
+ **
+ ***************************************************/
+
+static ftree_sw_t * 
+__osm_ftree_sw_create(
+   IN  ftree_fabric_t * p_ftree,
+   IN  osm_switch_t   * p_osm_sw)
+{
+   ftree_sw_t * p_sw;
+   uint8_t ports_num;
+
+   /* make sure that the switch has ports */
+   if (osm_switch_get_num_ports(p_osm_sw) == 1)
+      return NULL;
+
+   p_sw = (ftree_sw_t *)malloc(sizeof(ftree_sw_t));
+   if (p_sw == NULL) 
+      return NULL;
+   memset(p_sw, 0, sizeof(ftree_sw_t));
+
+   p_sw->p_osm_sw = p_osm_sw;
+   p_sw->rank = 0xFF;
+   __osm_ftree_tuple_init(p_sw->tuple);
+
+   p_sw->base_lid = osm_node_get_base_lid(osm_switch_get_node_ptr(p_sw->p_osm_sw),0);
+
+   ports_num = osm_node_get_num_physp(osm_switch_get_node_ptr(p_sw->p_osm_sw));
+   p_sw->down_port_groups = 
+      (ftree_port_group_t **) malloc(ports_num * sizeof(ftree_port_group_t *));
+   p_sw->up_port_groups = 
+      (ftree_port_group_t **) malloc(ports_num * sizeof(ftree_port_group_t *));
+   if (!p_sw->down_port_groups || !p_sw->up_port_groups)
+      return NULL;
+   p_sw->down_port_groups_num = 0;
+   p_sw->up_port_groups_num = 0;
+
+   /* initialize lft buffer */
+   p_sw->lft_buf = (ftree_fwd_tbl_t)cl_pool_get(&p_ftree->sw_fwd_tbl_pool);
+   memset(p_sw->lft_buf, OSM_NO_PATH, FTREE_FWD_TBL_LEN);
+
+   return p_sw;
+} /* __osm_ftree_sw_create() */
+
+/***************************************************/
+
+static void 
+__osm_ftree_sw_destroy(
+   IN  ftree_fabric_t * p_ftree,
+   IN  ftree_sw_t     * p_sw)
+{
+   uint8_t i;
+
+   if (!p_sw)
+      return;
+
+   for (i = 0; i < p_sw->down_port_groups_num; i++)
+      __osm_ftree_port_group_destroy(p_sw->down_port_groups[i]);
+   for (i = 0; i < p_sw->up_port_groups_num; i++)
+      __osm_ftree_port_group_destroy(p_sw->up_port_groups[i]);
+   if (p_sw->down_port_groups)
+      free(p_sw->down_port_groups);
+   if (p_sw->up_port_groups)
+      free(p_sw->up_port_groups);
+
+   /* return switch fwd_tbl to pool */
+   if (p_sw->lft_buf)
+      cl_pool_put(&p_ftree->sw_fwd_tbl_pool, (void *)p_sw->lft_buf);
+
+   free(p_sw);
+} /* __osm_ftree_sw_destroy() */
+
+/***************************************************/
+
+static void 
+__osm_ftree_sw_dump(
+   IN  ftree_fabric_t * p_ftree,
+   IN  ftree_sw_t * p_sw)
+{
+   uint32_t i;
+
+   if (!p_sw)
+      return;
+
+   if (!osm_log_is_active(&p_ftree->p_osm->log, OSM_LOG_DEBUG))
+      return;
+
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+           "__osm_ftree_sw_dump: "
+           "Switch index: %s, GUID: 0x%016" PRIx64 ", Ports: %u DOWN, %u UP\n",
+          __osm_ftree_tuple_to_str(p_sw->tuple),
+          cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))), 
+          p_sw->down_port_groups_num, 
+          p_sw->up_port_groups_num);
+
+   for( i = 0; i < p_sw->down_port_groups_num; i++ )
+      __osm_ftree_port_group_dump(p_ftree,
+                                  p_sw->down_port_groups[i],
+                                  FTREE_DIRECTION_DOWN);
+   for( i = 0; i < p_sw->up_port_groups_num; i++ )
+      __osm_ftree_port_group_dump(p_ftree,
+                                  p_sw->up_port_groups[i],
+                                  FTREE_DIRECTION_UP);
+
+} /* __osm_ftree_sw_dump() */
+
+/***************************************************/
+
+static boolean_t
+__osm_ftree_sw_ranked(
+   IN  ftree_sw_t * p_sw)
+{
+   return (p_sw->rank != 0xFF); 
+}
+
+/***************************************************/
+
+static ftree_port_group_t *
+__osm_ftree_sw_get_port_group_by_remote_lid(
+   IN  ftree_sw_t       * p_sw,
+   IN  ib_net16_t         remote_base_lid,
+   IN  ftree_direction_t  direction)
+{
+   uint32_t i;
+   uint32_t size;
+   ftree_port_group_t ** port_groups;
+
+   if (direction == FTREE_DIRECTION_UP)
+   {
+      port_groups = p_sw->up_port_groups;
+      size = p_sw->up_port_groups_num;
+   }
+   else
+   {
+      port_groups = p_sw->down_port_groups;
+      size = p_sw->down_port_groups_num;
+   }
+
+   for (i = 0; i < size; i++)
+      if (remote_base_lid == port_groups[i]->remote_base_lid)
+         return port_groups[i];
+
+   return NULL;
+} /* __osm_ftree_sw_get_port_group_by_remote_lid() */
+
+/***************************************************/
+
+static void 
+__osm_ftree_sw_add_port(
+   IN  ftree_sw_t       * p_sw,
+   IN  uint8_t            port_num,
+   IN  uint8_t            remote_port_num,
+   IN  ib_net16_t         base_lid,
+   IN  ib_net16_t         remote_base_lid,
+   IN  ib_net64_t         port_guid,
+   IN  ib_net64_t         remote_port_guid,
+   IN  ib_net64_t         remote_node_guid,
+   IN  uint8_t            remote_node_type,
+   IN  void             * p_remote_hca_or_sw,
+   IN  ftree_direction_t  direction)
+{
+   ftree_port_group_t * p_group = 
+       __osm_ftree_sw_get_port_group_by_remote_lid(p_sw,remote_base_lid,direction);
+
+   if (!p_group)
+   {
+      p_group = __osm_ftree_port_group_create(
+                     base_lid,
+                     remote_base_lid,
+                     &port_guid,
+                     &remote_port_guid,
+                     &remote_node_guid,
+                     remote_node_type,
+                     p_remote_hca_or_sw);
+      CL_ASSERT(p_group);
+
+      if (direction == FTREE_DIRECTION_UP)
+         p_sw->up_port_groups[p_sw->up_port_groups_num++] = p_group;
+      else
+         p_sw->down_port_groups[p_sw->down_port_groups_num++] = p_group;
+   }
+   __osm_ftree_port_group_add_port(p_group,port_num,remote_port_num);
+
+} /* __osm_ftree_sw_add_port() */
+
+/***************************************************/
+
+static inline void
+__osm_ftree_sw_set_fwd_table_block(
+    IN  ftree_sw_t * p_sw,
+    IN  uint16_t     lid_ho, 
+    IN  uint8_t      port_num)
+{
+   p_sw->lft_buf[lid_ho] = port_num;
+}
+
+/***************************************************/
+
+static inline uint8_t
+__osm_ftree_sw_get_fwd_table_block(
+    IN  ftree_sw_t * p_sw,
+    IN  uint16_t     lid_ho)
+{
+   return p_sw->lft_buf[lid_ho];
+}
+
+/***************************************************/
+
+static inline cl_status_t
+__osm_ftree_sw_set_hops(
+   IN  ftree_sw_t     * p_sw,
+   IN  uint16_t         max_lid_ho,
+   IN  uint16_t         lid_ho,
+   IN  uint8_t          port_num,
+   IN  uint8_t          hops)
+{
+   /* make sure the lid matrix has enough room */
+   osm_switch_set_min_lid_size(p_sw->p_osm_sw, max_lid_ho);
+
+   /* set local min hop table(LID) */
+   return osm_switch_set_hops(p_sw->p_osm_sw,
+                              lid_ho,
+                              port_num,
+                              hops);
+}
+
+/***************************************************
+ **
+ ** ftree_hca_t functions
+ **
+ ***************************************************/
+
+static ftree_hca_t * 
+__osm_ftree_hca_create(
+   IN  osm_node_t * p_osm_node)
+{
+   ftree_hca_t * p_hca = (ftree_hca_t *)malloc(sizeof(ftree_hca_t));
+   if (p_hca == NULL) 
+      return NULL;
+   memset(p_hca,0,sizeof(ftree_hca_t));
+
+   p_hca->p_osm_node = p_osm_node;
+   p_hca->up_port_groups = (ftree_port_group_t **) 
+        malloc(osm_node_get_num_physp(p_hca->p_osm_node) * sizeof (ftree_port_group_t *));
+   if (!p_hca->up_port_groups)
+      return NULL;
+   p_hca->up_port_groups_num = 0;
+   return p_hca;
+}
+
+/***************************************************/
+
+static void 
+__osm_ftree_hca_destroy(
+   IN  ftree_hca_t * p_hca)
+{
+   uint32_t i;
+
+   if (!p_hca)
+      return;
+
+   for (i = 0; i < p_hca->up_port_groups_num; i++)
+      __osm_ftree_port_group_destroy(p_hca->up_port_groups[i]);
+
+   if (p_hca->up_port_groups)
+      free(p_hca->up_port_groups);
+
+   free(p_hca);
+}
+
+/***************************************************/
+
+static void 
+__osm_ftree_hca_dump(
+   IN  ftree_fabric_t * p_ftree,
+   IN  ftree_hca_t * p_hca)
+{
+   uint32_t i;
+
+   if (!p_hca)
+      return;
+
+   if (!osm_log_is_active(&p_ftree->p_osm->log,OSM_LOG_DEBUG))
+      return;
+
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+           "__osm_ftree_hca_dump: "
+           "HCA GUID: 0x%016" PRIx64 ", Ports: %u UP\n",
+          cl_ntoh64(osm_node_get_node_guid(p_hca->p_osm_node)), 
+          p_hca->up_port_groups_num);
+
+   for( i = 0; i < p_hca->up_port_groups_num; i++ ) 
+      __osm_ftree_port_group_dump(p_ftree,
+                                  p_hca->up_port_groups[i],
+                                  FTREE_DIRECTION_UP);
+}
+
+/***************************************************/
+
+static ftree_port_group_t *
+__osm_ftree_hca_get_port_group_by_remote_lid(
+   IN  ftree_hca_t * p_hca,
+   IN  ib_net16_t    remote_base_lid)
+{
+   uint32_t i;
+   for (i = 0; i < p_hca->up_port_groups_num; i++)
+      if (remote_base_lid == p_hca->up_port_groups[i]->remote_base_lid)
+         return p_hca->up_port_groups[i];
+
+   return NULL;
+}
+
+/***************************************************/
+
+static void 
+__osm_ftree_hca_add_port(
+   IN  ftree_hca_t * p_hca,
+   IN  uint8_t       port_num,
+   IN  uint8_t       remote_port_num,
+   IN  ib_net16_t    base_lid,
+   IN  ib_net16_t    remote_base_lid,
+   IN  ib_net64_t    port_guid,
+   IN  ib_net64_t    remote_port_guid,
+   IN  ib_net64_t    remote_node_guid,
+   IN  uint8_t       remote_node_type,
+   IN  void        * p_remote_hca_or_sw)
+{
+   ftree_port_group_t * p_group;
+
+   /* this function is supposed to be called only for adding ports
+      in hca's that lead to switches */ 
+   CL_ASSERT(remote_node_type == IB_NODE_TYPE_SWITCH);
+
+   p_group = __osm_ftree_hca_get_port_group_by_remote_lid(p_hca,remote_base_lid);
+
+   if (!p_group)
+   {
+      p_group = __osm_ftree_port_group_create(
+                     base_lid,
+                     remote_base_lid,
+                     &port_guid,
+                     &remote_port_guid,
+                     &remote_node_guid,
+                     remote_node_type,
+                     p_remote_hca_or_sw);
+      p_hca->up_port_groups[p_hca->up_port_groups_num++] = p_group;
+   }
+   __osm_ftree_port_group_add_port(p_group, port_num, remote_port_num);
+
+} /* __osm_ftree_hca_add_port() */
+
+/***************************************************
+ **
+ ** ftree_fabric_t functions
+ **
+ ***************************************************/
+
+static ftree_fabric_t * 
+__osm_ftree_fabric_create()
+{
+   cl_status_t status;
+   ftree_fabric_t * p_ftree = (ftree_fabric_t *)malloc(sizeof(ftree_fabric_t));
+   if (p_ftree == NULL) 
+      return NULL;
+
+   memset(p_ftree,0,sizeof(ftree_fabric_t));
+
+   cl_qmap_init(&p_ftree->hca_tbl);
+   cl_qmap_init(&p_ftree->sw_tbl);
+   cl_qmap_init(&p_ftree->sw_by_tuple_tbl);
+
+   status = cl_pool_init( &p_ftree->sw_fwd_tbl_pool,
+                          8,                 /* min pool size */
+                          0,                 /* max pool size - unlimited */
+                          8,                 /* grow size */
+                          FTREE_FWD_TBL_LEN, /* object_size */
+                          NULL,              /* object initializer */
+                          NULL,              /* object destructor */
+                          NULL );            /* context */
+   if (status != CL_SUCCESS)
+      return NULL;
+
+   p_ftree->tree_rank = 1;
+   return p_ftree;
+}
+
+/***************************************************/
+
+static void 
+__osm_ftree_fabric_clear(ftree_fabric_t * p_ftree)
+{
+   ftree_hca_t * p_hca;
+   ftree_hca_t * p_next_hca;
+   ftree_sw_t * p_sw;
+   ftree_sw_t * p_next_sw;
+   ftree_sw_tbl_element_t * p_element;
+   ftree_sw_tbl_element_t * p_next_element;
+
+   if (!p_ftree)
+      return;
+
+   /* remove all the elements of hca_tbl */
+
+   p_next_hca = (ftree_hca_t *)cl_qmap_head(&p_ftree->hca_tbl);
+   while( p_next_hca != (ftree_hca_t *)cl_qmap_end( &p_ftree->hca_tbl ) )
+   {
+      p_hca = p_next_hca;
+      p_next_hca = (ftree_hca_t *)cl_qmap_next(&p_hca->map_item );
+      __osm_ftree_hca_destroy(p_hca);
+   }
+   cl_qmap_remove_all(&p_ftree->hca_tbl);
+
+   /* remove all the elements of sw_tbl */
+
+   p_next_sw = (ftree_sw_t *)cl_qmap_head(&p_ftree->sw_tbl);
+   while( p_next_sw != (ftree_sw_t *)cl_qmap_end( &p_ftree->sw_tbl ) )
+   {
+      p_sw = p_next_sw;
+      p_next_sw = (ftree_sw_t *)cl_qmap_next(&p_sw->map_item );
+      __osm_ftree_sw_destroy(p_ftree,p_sw);
+   }
+   cl_qmap_remove_all(&p_ftree->sw_tbl);
+
+   /* remove all the elements of sw_by_tuple_tbl */
+
+   p_next_element = 
+      (ftree_sw_tbl_element_t *)cl_qmap_head(&p_ftree->sw_by_tuple_tbl);
+   while( p_next_element != 
+          (ftree_sw_tbl_element_t *)cl_qmap_end( &p_ftree->sw_by_tuple_tbl ) )
+   {
+      p_element = p_next_element;
+      p_next_element = 
+         (ftree_sw_tbl_element_t *)cl_qmap_next(&p_element->map_item);
+      __osm_ftree_sw_tbl_element_destroy(p_element);
+   }
+   cl_qmap_remove_all(&p_ftree->sw_by_tuple_tbl);
+
+   /* free the leaf switches array */
+   if ((p_ftree->leaf_switches_num > 0) && (p_ftree->leaf_switches))
+      free(p_ftree->leaf_switches);
+
+   p_ftree->leaf_switches_num = 0;
+   p_ftree->leaf_switches = NULL;
+   p_ftree->fabric_built = FALSE;
+
+} /* __osm_ftree_fabric_destroy() */
+
+/***************************************************/
+
+static void 
+__osm_ftree_fabric_destroy(ftree_fabric_t * p_ftree)
+{
+   if (!p_ftree)
+      return;
+   __osm_ftree_fabric_clear(p_ftree);
+   cl_pool_destroy(&p_ftree->sw_fwd_tbl_pool);
+   free(p_ftree);
+}
+
+/***************************************************/
+
+static void 
+__osm_ftree_fabric_set_rank(ftree_fabric_t * p_ftree, uint8_t rank)
+{
+   if (rank > p_ftree->tree_rank)
+      p_ftree->tree_rank = rank;
+}
+
+/***************************************************/
+
+static uint8_t 
+__osm_ftree_fabric_get_rank(ftree_fabric_t * p_ftree)
+{
+   return p_ftree->tree_rank;
+}
+
+/***************************************************/
+
+static void 
+__osm_ftree_fabric_add_hca(ftree_fabric_t * p_ftree, osm_node_t * p_osm_node)
+{
+   ftree_hca_t * p_hca = __osm_ftree_hca_create(p_osm_node);
+
+   CL_ASSERT(osm_node_get_type(p_osm_node) == IB_NODE_TYPE_CA);
+
+   cl_qmap_insert(&p_ftree->hca_tbl,
+                  p_osm_node->node_info.node_guid,
+                  &p_hca->map_item);
+}
+
+/***************************************************/
+
+static void 
+__osm_ftree_fabric_add_sw(ftree_fabric_t * p_ftree, osm_switch_t * p_osm_sw)
+{
+   ftree_sw_t * p_sw = __osm_ftree_sw_create(p_ftree,p_osm_sw);
+
+   CL_ASSERT(osm_node_get_type(p_osm_sw->p_node) == IB_NODE_TYPE_SWITCH);
+
+   cl_qmap_insert(&p_ftree->sw_tbl,
+                  p_osm_sw->p_node->node_info.node_guid,
+                  &p_sw->map_item);
+
+   /* track the max lid (in host order) that exists in the fabric */
+   if (cl_ntoh16(p_sw->base_lid) > p_ftree->lft_max_lid_ho)
+      p_ftree->lft_max_lid_ho = cl_ntoh16(p_sw->base_lid);
+}
+
+/***************************************************/
+
+static void 
+__osm_ftree_fabric_add_sw_by_tuple(
+   IN  ftree_fabric_t * p_ftree, 
+   IN  ftree_sw_t * p_sw)
+{
+   CL_ASSERT(__osm_ftree_tuple_assigned(p_sw->tuple));
+
+   cl_qmap_insert(&p_ftree->sw_by_tuple_tbl,
+                  __osm_ftree_tuple_to_key(p_sw->tuple),
+                  &__osm_ftree_sw_tbl_element_create(p_sw)->map_item);
+}
+
+/***************************************************/
+
+static ftree_sw_t * 
+__osm_ftree_fabric_get_sw_by_tuple(
+   IN  ftree_fabric_t * p_ftree, 
+   IN  ftree_tuple_t tuple)
+{
+   ftree_sw_tbl_element_t * p_element;
+
+   CL_ASSERT(__osm_ftree_tuple_assigned(tuple));
+
+   __osm_ftree_tuple_to_key(tuple);
+
+   p_element = (ftree_sw_tbl_element_t * )cl_qmap_get(&p_ftree->sw_by_tuple_tbl,
+                                                      __osm_ftree_tuple_to_key(tuple));
+   if (p_element == (ftree_sw_tbl_element_t * )cl_qmap_end(&p_ftree->sw_by_tuple_tbl))
+      return NULL;
+
+   return p_element->p_sw;
+}
+
+/***************************************************/
+
+static void 
+__osm_ftree_fabric_dump(ftree_fabric_t * p_ftree)
+{
+   uint32_t i;
+   ftree_hca_t * p_hca;
+   ftree_sw_t * p_sw;
+
+   if (!osm_log_is_active(&p_ftree->p_osm->log,OSM_LOG_DEBUG))
+      return;
+
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,"__osm_ftree_fabric_dump: \n"
+           "                       |-------------------------------|\n"
+           "                       |-  Full fabric topology dump  -|\n"
+           "                       |-------------------------------|\n\n");
+
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+           "__osm_ftree_fabric_dump: -- HCAs:\n");
+
+   for ( p_hca = (ftree_hca_t *)cl_qmap_head(&p_ftree->hca_tbl);
+         p_hca != (ftree_hca_t *)cl_qmap_end(&p_ftree->hca_tbl);
+         p_hca = (ftree_hca_t *)cl_qmap_next(&p_hca->map_item) )
+   {
+      __osm_ftree_hca_dump(p_ftree, p_hca);
+   }
+
+   for (i = 0; i < __osm_ftree_fabric_get_rank(p_ftree); i++)
+   {
+      osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+              "__osm_ftree_fabric_dump: -- Rank %u switches\n", i);
+      for ( p_sw = (ftree_sw_t *)cl_qmap_head(&p_ftree->sw_tbl);
+            p_sw != (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl);
+            p_sw = (ftree_sw_t *)cl_qmap_next(&p_sw->map_item) )
+      {
+         if (p_sw->rank == i)
+            __osm_ftree_sw_dump(p_ftree, p_sw);
+      }
+   }
+
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,"__osm_ftree_fabric_dump: \n"
+           "                       |---------------------------------------|\n"
+           "                       |- Full fabric topology dump completed -|\n"
+           "                       |---------------------------------------|\n\n");
+} /* __osm_ftree_fabric_dump() */
+
+/***************************************************/
+
+static void 
+__osm_ftree_fabric_dump_general_info(
+   IN  ftree_fabric_t * p_ftree)
+{
+   uint32_t i,j;
+   ftree_sw_t * p_sw;
+   char * addition_str;
+
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_INFO,
+           "__osm_ftree_fabric_dump_general_info: "
+           "General fabric topology info\n");
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_INFO,"__osm_ftree_fabric_dump_general_info: "
+           "============================\n");
+
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_INFO,
+           "__osm_ftree_fabric_dump_general_info: "
+           "  - FatTree rank (switches only): %u\n",
+           p_ftree->tree_rank);
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_INFO,
+           "__osm_ftree_fabric_dump_general_info: "
+           "  - Fabric has %u HCAs, %u switches\n",
+           cl_qmap_count(&p_ftree->hca_tbl),
+           cl_qmap_count(&p_ftree->sw_tbl));
+
+   for (i = 0; i < __osm_ftree_fabric_get_rank(p_ftree); i++)
+   {
+      j = 0;
+      for ( p_sw = (ftree_sw_t *)cl_qmap_head(&p_ftree->sw_tbl);
+            p_sw != (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl);
+            p_sw = (ftree_sw_t *)cl_qmap_next(&p_sw->map_item) )
+      {
+         if (p_sw->rank == i)
+            j++;
+      }
+      if (i == 0)
+         addition_str = " (root) ";
+      else 
+         if (i == (__osm_ftree_fabric_get_rank(p_ftree) - 1))
+            addition_str = " (leaf) ";
+         else
+            addition_str = " ";
+         osm_log(&p_ftree->p_osm->log, OSM_LOG_INFO,
+                 "__osm_ftree_fabric_dump_general_info: "
+                 "  - Fabric has %u rank %u%s switches\n",
+                 j, i, addition_str);
+   }
+
+   if (osm_log_is_active(&p_ftree->p_osm->log, OSM_LOG_VERBOSE))
+   {
+      osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+              "__osm_ftree_fabric_dump_general_info: "
+              "  - Root switches:\n");
+      for ( p_sw = (ftree_sw_t *)cl_qmap_head(&p_ftree->sw_tbl);
+            p_sw != (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl);
+            p_sw = (ftree_sw_t *)cl_qmap_next(&p_sw->map_item) )
+      {
+         if (p_sw->rank == 0)
+               osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+                       "__osm_ftree_fabric_dump_general_info: "
+                       "      GUID: 0x%016" PRIx64 ", LID: 0x%x, Index %s\n",
+                       cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))),
+                       cl_ntoh16(p_sw->base_lid),
+                       __osm_ftree_tuple_to_str(p_sw->tuple));
+      }
+
+      osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+              "__osm_ftree_fabric_dump_general_info: "
+              "  - Leaf switches (sorted by index):\n");
+      for (i = 0; i < p_ftree->leaf_switches_num; i++)
+      {
+            osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+                    "__osm_ftree_fabric_dump_general_info: "
+                    "      GUID: 0x%016" PRIx64 ", LID: 0x%x, Index %s\n",
+                    cl_ntoh64(osm_node_get_node_guid(
+                                 osm_switch_get_node_ptr(
+                                    p_ftree->leaf_switches[i]->p_osm_sw))),
+                    cl_ntoh16(p_ftree->leaf_switches[i]->base_lid),
+                    __osm_ftree_tuple_to_str(p_ftree->leaf_switches[i]->tuple));
+      }
+   }
+} /* __osm_ftree_fabric_dump_general_info() */
+
+/***************************************************/
+
+static void 
+__osm_ftree_fabric_dump_hca_ordering(
+   IN  ftree_fabric_t * p_ftree)
+{  
+   ftree_hca_t        * p_hca;
+   ftree_sw_t         * p_sw;
+   ftree_port_group_t * p_group;
+   uint32_t             i;
+   uint32_t             j;
+
+   char desc[IB_NODE_DESCRIPTION_SIZE + 1];
+   char path[1024];
+   FILE * p_hca_ordering_file;
+   char * filename = "osm-ftree-ca-order.dump";
+
+   snprintf(path, sizeof(path), "%s/%s", 
+            p_ftree->p_osm->subn.opt.dump_files_dir, filename);
+   p_hca_ordering_file = fopen(path, "w");
+   if (!p_hca_ordering_file) 
+   {
+      osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+              "__osm_ftree_fabric_dump_hca_ordering: ERR AB01: "
+              "cannot open file \'%s\': %s\n",
+               filename, strerror(errno));
+      OSM_LOG_EXIT(&p_ftree->p_osm->log);
+      return;
+   }
+   
+   /* for each leaf switch (in indexing order) */
+   for(i = 0; i < p_ftree->leaf_switches_num; i++)
+   {
+      p_sw = p_ftree->leaf_switches[i];
+      /* for each real HCA connected to this switch */
+      for (j = 0; j < p_sw->down_port_groups_num; j++)
+      {
+         p_group = p_sw->down_port_groups[j];
+         p_hca = p_group->remote_hca_or_sw.remote_hca;
+         memcpy(desc,p_hca->p_osm_node->node_desc.description,IB_NODE_DESCRIPTION_SIZE);
+         desc[IB_NODE_DESCRIPTION_SIZE] = '\0';
+
+         fprintf(p_hca_ordering_file,"0x%x\t%s\n", 
+                 cl_ntoh16(p_group->remote_base_lid), desc);
+      }
+
+      /* now print dummy HCAs */
+      for (j = p_sw->down_port_groups_num; j < p_ftree->max_hcas_per_leaf; j++)
+      {
+         fprintf(p_hca_ordering_file,"0xFFFF\tDUMMY\n");
+      }
+
+   }
+   /* done going through all the leaf switches */
+
+   fclose(p_hca_ordering_file);
+} /* __osm_ftree_fabric_dump_hca_ordering() */
+
+/***************************************************/
+
+static void 
+__osm_ftree_fabric_assign_tuple(
+   IN   ftree_fabric_t * p_ftree,
+   IN   ftree_sw_t * p_sw,
+   IN   ftree_tuple_t new_tuple)
+{
+   memcpy(p_sw->tuple, new_tuple, FTREE_TUPLE_LEN);
+   __osm_ftree_fabric_add_sw_by_tuple(p_ftree,p_sw);
+}
+
+/***************************************************/
+
+static void 
+__osm_ftree_fabric_assign_first_tuple(
+   IN   ftree_fabric_t * p_ftree,
+   IN   ftree_sw_t * p_sw)
+{
+   uint8_t i;
+   ftree_tuple_t new_tuple;
+
+   __osm_ftree_tuple_init(new_tuple);
+   new_tuple[0] = p_sw->rank;
+   for (i = 1; i <= p_sw->rank; i++)
+      new_tuple[i] = 0;
+
+   __osm_ftree_fabric_assign_tuple(p_ftree,p_sw,new_tuple);
+}
+
+/***************************************************/
+
+static void
+__osm_ftree_fabric_get_new_tuple(
+   IN   ftree_fabric_t * p_ftree,
+   OUT  ftree_tuple_t new_tuple,
+   IN   ftree_tuple_t from_tuple,
+   IN   ftree_direction_t direction)
+{
+   ftree_sw_t * p_sw;
+   ftree_tuple_t temp_tuple;
+   uint8_t var_index;
+   uint8_t i;
+
+   __osm_ftree_tuple_init(new_tuple);
+   memcpy(temp_tuple, from_tuple, FTREE_TUPLE_LEN);
+
+   if (direction == FTREE_DIRECTION_DOWN)
+   {
+      temp_tuple[0] ++;
+      var_index = from_tuple[0] + 1;
+   }
+   else
+   {
+      temp_tuple[0] --;
+      var_index = from_tuple[0];
+   }
+
+   for (i = 0; i < 0xFF; i++)
+   {
+      temp_tuple[var_index] = i;
+      p_sw = __osm_ftree_fabric_get_sw_by_tuple(p_ftree,temp_tuple);
+      if (p_sw == NULL) /* found free tuple */ 
+         break;
+   }
+
+   if (i == 0xFF)
+   {
+      /* new tuple not found - there are more than 255 ports in one direction */
+      return;
+   }
+   memcpy(new_tuple, temp_tuple, FTREE_TUPLE_LEN);
+
+} /* __osm_ftree_fabric_get_new_tuple() */
+
+/***************************************************/
+
+static void
+__osm_ftree_fabric_calculate_rank(
+   IN  ftree_fabric_t * p_ftree)
+{
+   ftree_sw_t   * p_sw;
+   ftree_sw_t   * p_next_sw;
+   uint16_t       max_rank = 0;
+
+   /* go over all the switches and find maximal switch rank */
+
+   p_next_sw = (ftree_sw_t *)cl_qmap_head(&p_ftree->sw_tbl);
+   while( p_next_sw != (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl) )
+   {
+      p_sw = p_next_sw;
+      if(p_sw->rank > max_rank)
+         max_rank = p_sw->rank;
+      p_next_sw = (ftree_sw_t *)cl_qmap_next(&p_sw->map_item );
+   }
+
+   /* set FatTree rank */
+   __osm_ftree_fabric_set_rank(p_ftree, max_rank + 1);
+}
+
+/***************************************************/
+
+static void
+__osm_ftree_fabric_make_indexing(
+   IN   ftree_fabric_t * p_ftree)
+{
+   ftree_sw_t         * p_remote_sw;
+   ftree_sw_t         * p_sw;
+   ftree_sw_t         * p_next_sw;
+   ftree_tuple_t        new_tuple;
+   uint32_t             i;
+   cl_list_t            bfs_list;
+   ftree_sw_tbl_element_t * p_sw_tbl_element;
+
+   OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_fabric_make_indexing);
+
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,"__osm_ftree_fabric_make_indexing: "
+           "Starting FatTree indexing\n");
+
+   /* create array of leaf switches */
+   p_ftree->leaf_switches = (ftree_sw_t **)
+         malloc(cl_qmap_count(&p_ftree->sw_tbl) * sizeof(ftree_sw_t *));
+
+   /* Looking for a leaf switch - the one that has rank equal to (tree_rank - 1).
+      This switch will be used as a starting point for indexing algorithm. */
+
+   p_next_sw = (ftree_sw_t *)cl_qmap_head(&p_ftree->sw_tbl);
+   while( p_next_sw != (ftree_sw_t *)cl_qmap_end( &p_ftree->sw_tbl ) )
+   {
+      p_sw = p_next_sw;
+      if(p_sw->rank == (__osm_ftree_fabric_get_rank(p_ftree) - 1))
+         break;
+      p_next_sw = (ftree_sw_t *)cl_qmap_next(&p_sw->map_item );
+   }
+
+   CL_ASSERT(p_next_sw != (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl));
+
+   /* Assign the first tuple to the switch that is used as BFS starting point.
+      The tuple will be as follows: [rank].0.0.0...
+      This fuction also adds the switch it into the switch_by_tuple table. */
+   __osm_ftree_fabric_assign_first_tuple(p_ftree,p_sw);
+
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+           "__osm_ftree_fabric_make_indexing: Indexing starting point:\n"
+           "                                            - Switch rank  : %u\n"
+           "                                            - Switch index : %s\n"
+           "                                            - Node LID     : 0x%x\n"
+           "                                            - Node GUID    : 0x%016" PRIx64 "\n",
+           p_sw->rank,
+           __osm_ftree_tuple_to_str(p_sw->tuple),
+           cl_ntoh16(p_sw->base_lid),
+           cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))));
+
+   /* 
+    * Now run BFS and assign indexes to all switches
+    * Pseudo code of the algorithm is as follows:
+    *
+    *  * Add first switch to BFS queue
+    *  * While (BFS queue not empty)
+    *      - Pop the switch from the head of the queue
+    *      - Scan all the downward and upward ports
+    *      - For each port
+    *          + Get the remote switch
+    *          + Assign index to the remote switch
+    *          + Add remote switch to the BFS queue
+    */
+
+   cl_list_init(&bfs_list, cl_qmap_count(&p_ftree->sw_tbl));
+   cl_list_insert_tail(&bfs_list, &__osm_ftree_sw_tbl_element_create(p_sw)->map_item);
+
+   while (!cl_is_list_empty(&bfs_list))
+   {
+      p_sw_tbl_element = (ftree_sw_tbl_element_t *)cl_list_remove_head(&bfs_list);
+      p_sw = p_sw_tbl_element->p_sw;
+      __osm_ftree_sw_tbl_element_destroy(p_sw_tbl_element);
+
+      /* Discover all the nodes from ports that are pointing down */
+
+      if (p_sw->rank == (__osm_ftree_fabric_get_rank(p_ftree) - 1))
+      {
+         /* add switch to leaf switches array */
+         p_ftree->leaf_switches[p_ftree->leaf_switches_num++] = p_sw;
+         /* update the max_hcas_per_leaf value */
+         if (p_sw->down_port_groups_num > p_ftree->max_hcas_per_leaf)
+            p_ftree->max_hcas_per_leaf = p_sw->down_port_groups_num;
+      }
+      else
+      {
+         /* This is not the leaf switch, which means that all the
+            ports that point down are taking us to another switches.
+            No need to assign indexing to HCAs */
+         for( i = 0; i < p_sw->down_port_groups_num; i++ ) 
+         {
+            p_remote_sw = p_sw->down_port_groups[i]->remote_hca_or_sw.remote_sw;
+            if (__osm_ftree_tuple_assigned(p_remote_sw->tuple))
+            {
+               /* this switch has been already indexed */
+               continue;
+            }
+            /* allocate new tuple */
+            __osm_ftree_fabric_get_new_tuple(p_ftree,
+                                             new_tuple,
+                                             p_sw->tuple,
+                                             FTREE_DIRECTION_DOWN);
+            /* Assign the new tuple to the remote switch.
+               This fuction also adds the switch into the switch_by_tuple table. */
+            __osm_ftree_fabric_assign_tuple(p_ftree,
+                                            p_remote_sw,
+                                            new_tuple);
+
+            /* add the newly discovered switch to the BFS queue */
+            cl_list_insert_tail(&bfs_list, 
+                                &__osm_ftree_sw_tbl_element_create(p_remote_sw)->map_item);
+         }
+         /* Done assigning indexes to all the remote switches 
+            that are pointed by the downgoing ports. 
+            Now sort port groups according to remote index. */
+         qsort(p_sw->down_port_groups,                      /* array */
+               p_sw->down_port_groups_num,                  /* number of elements */
+               sizeof(ftree_port_group_t *),                /* size of each element */
+               __osm_ftree_compare_port_groups_by_remote_switch_index); /* comparator */
+      }
+
+      /* Done indexing switches from ports that go down.
+         Now do the same with ports that are pointing up. */
+
+      if (p_sw->rank != 0)
+      {
+         /* This is not the root switch, which means that all the ports
+            that are pointing up are taking us to another switches. */
+         for( i = 0; i < p_sw->up_port_groups_num; i++ ) 
+         {
+            p_remote_sw = p_sw->up_port_groups[i]->remote_hca_or_sw.remote_sw;
+            if (__osm_ftree_tuple_assigned(p_remote_sw->tuple))
+               continue;
+            /* allocate new tuple */
+            __osm_ftree_fabric_get_new_tuple(p_ftree,
+                                             new_tuple,
+                                             p_sw->tuple,
+                                             FTREE_DIRECTION_UP);
+            /* Assign the new tuple to the remote switch.
+               This fuction also adds the switch to the
+               switch_by_tuple table. */
+            __osm_ftree_fabric_assign_tuple(p_ftree,
+                                            p_remote_sw,
+                                            new_tuple);
+            /* add the newly discovered switch to the BFS queue */
+            cl_list_insert_tail(&bfs_list, 
+                                &__osm_ftree_sw_tbl_element_create(p_remote_sw)->map_item);
+         }
+         /* Done assigning indexes to all the remote switches 
+            that are pointed by the upgoing ports. 
+            Now sort port groups according to remote index. */
+         qsort(p_sw->up_port_groups,                        /* array */
+               p_sw->up_port_groups_num,                    /* number of elements */
+               sizeof(ftree_port_group_t *),                /* size of each element */
+               __osm_ftree_compare_port_groups_by_remote_switch_index); /* comparator */
+      }
+      /* Done assigning indexes to all the switches that are directly connected 
+         to the current switch - go to the next switch in the BFS queue */
+   }
+
+   /* sort array of leaf switches by index */
+   qsort(p_ftree->leaf_switches,     /* array */
+         p_ftree->leaf_switches_num, /* number of elements */
+         sizeof(ftree_sw_t *),       /* size of each element */
+         __osm_ftree_compare_switches_by_index); /* comparator */
+
+   OSM_LOG_EXIT(&p_ftree->p_osm->log);
+} /* __osm_ftree_fabric_make_indexing() */
+
+/***************************************************/
+
+static boolean_t
+__osm_ftree_fabric_validate_topology(
+   IN   ftree_fabric_t * p_ftree)
+{
+   ftree_port_group_t * p_group;
+   ftree_port_group_t * p_ref_group;
+   ftree_sw_t         * p_sw;
+   ftree_sw_t         * p_next_sw;
+   ftree_sw_t        ** reference_sw_arr;
+   uint16_t             tree_rank = __osm_ftree_fabric_get_rank(p_ftree);
+   boolean_t            res = TRUE;
+   uint8_t              i;
+
+   OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_fabric_validate_topology);
+
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+           "__osm_ftree_fabric_validate_topology: "
+           "Validating fabric topology\n");
+
+   reference_sw_arr = (ftree_sw_t **)malloc(tree_rank * sizeof(ftree_sw_t *));
+   if ( reference_sw_arr == NULL )
+   {
+      osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+              "Fat-tree routing: Memory allocation failed\n");
+      return FALSE;
+   }
+   memset(reference_sw_arr, 0, tree_rank * sizeof(ftree_sw_t *));
+
+   p_next_sw = (ftree_sw_t *)cl_qmap_head(&p_ftree->sw_tbl);
+   while( res && 
+          p_next_sw != (ftree_sw_t *)cl_qmap_end( &p_ftree->sw_tbl ) )
+   {
+      p_sw = p_next_sw;
+      p_next_sw = (ftree_sw_t *)cl_qmap_next(&p_sw->map_item );
+
+      if (!reference_sw_arr[p_sw->rank])
+      {
+         /* This is the first switch in the current level that 
+            we're checking - use it as a reference */
+         reference_sw_arr[p_sw->rank] = p_sw;
+      }
+      else
+      {
+         /* compare this switch properties to the reference switch */
+
+         if ( reference_sw_arr[p_sw->rank]->up_port_groups_num != p_sw->up_port_groups_num )
+         {
+            osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+                    "__osm_ftree_fabric_validate_topology: "
+                    "ERR AB09: Different number of upward port groups on switches:\n"
+                    "       GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u groups\n"
+                    "       GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u groups\n",
+                    cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(reference_sw_arr[p_sw->rank]->p_osm_sw))),
+                    cl_ntoh16(reference_sw_arr[p_sw->rank]->base_lid),
+                    __osm_ftree_tuple_to_str(reference_sw_arr[p_sw->rank]->tuple),
+                    reference_sw_arr[p_sw->rank]->up_port_groups_num,
+                    cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))),
+                    cl_ntoh16(p_sw->base_lid),
+                    __osm_ftree_tuple_to_str(p_sw->tuple),
+                    p_sw->up_port_groups_num);
+            res = FALSE;
+            break;
+         }
+
+         if ( p_sw->rank != (__osm_ftree_fabric_get_rank(p_ftree) - 1) &&
+              reference_sw_arr[p_sw->rank]->down_port_groups_num != p_sw->down_port_groups_num )
+         {
+            /* we're allowing some hca's to be missing */
+            osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+                    "__osm_ftree_fabric_validate_topology: "
+                    "ERR AB0A: Different number of downward port groups on switches:\n"
+                    "       GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u port groups\n"
+                    "       GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u port groups\n",
+                    cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(reference_sw_arr[p_sw->rank]->p_osm_sw))),
+                    cl_ntoh16(reference_sw_arr[p_sw->rank]->base_lid),
+                    __osm_ftree_tuple_to_str(reference_sw_arr[p_sw->rank]->tuple),
+                    reference_sw_arr[p_sw->rank]->down_port_groups_num,
+                    cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))),
+                    cl_ntoh16(p_sw->base_lid),
+                    __osm_ftree_tuple_to_str(p_sw->tuple),
+                    p_sw->down_port_groups_num);
+            res = FALSE;
+            break;
+         }
+
+         if ( reference_sw_arr[p_sw->rank]->up_port_groups_num != 0 )
+         {
+            p_ref_group = reference_sw_arr[p_sw->rank]->up_port_groups[0];
+            for (i = 0; i < p_sw->up_port_groups_num; i++)
+            {
+                p_group = p_sw->up_port_groups[i];
+                if (cl_ptr_vector_get_size(&p_ref_group->ports) != cl_ptr_vector_get_size(&p_group->ports))
+                {
+                   osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+                           "__osm_ftree_fabric_validate_topology: "
+                           "ERR AB0B: Different number of ports in an upward port group on switches:\n"
+                           "       GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u ports\n"
+                           "       GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u ports\n",
+                           cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(reference_sw_arr[p_sw->rank]->p_osm_sw))),
+                           cl_ntoh16(reference_sw_arr[p_sw->rank]->base_lid),
+                           __osm_ftree_tuple_to_str(reference_sw_arr[p_sw->rank]->tuple),
+                           cl_ptr_vector_get_size(&p_ref_group->ports),
+                           cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))),
+                           cl_ntoh16(p_sw->base_lid),
+                           __osm_ftree_tuple_to_str(p_sw->tuple),
+                           cl_ptr_vector_get_size(&p_group->ports));
+                   res = FALSE;
+                   break;
+                }
+            }
+         }
+         if ( reference_sw_arr[p_sw->rank]->down_port_groups_num != 0 &&
+              p_sw->rank != (tree_rank - 1) )
+         {
+            /* we're allowing some hca's to be missing */
+            p_ref_group = reference_sw_arr[p_sw->rank]->down_port_groups[0];
+            for (i = 0; i < p_sw->down_port_groups_num; i++)
+            {
+                p_group = p_sw->down_port_groups[0];
+                if (cl_ptr_vector_get_size(&p_ref_group->ports) != cl_ptr_vector_get_size(&p_group->ports))
+                {
+                   osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+                           "__osm_ftree_fabric_validate_topology: "
+                           "ERR AB0C: Different number of ports in an downward port group on switches:\n"
+                           "       GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u ports\n"
+                           "       GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u ports\n",
+                           cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(reference_sw_arr[p_sw->rank]->p_osm_sw))),
+                           cl_ntoh16(reference_sw_arr[p_sw->rank]->base_lid),
+                           __osm_ftree_tuple_to_str(reference_sw_arr[p_sw->rank]->tuple),
+                           cl_ptr_vector_get_size(&p_ref_group->ports),
+                           cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))),
+                           cl_ntoh16(p_sw->base_lid),
+                           __osm_ftree_tuple_to_str(p_sw->tuple),
+                           cl_ptr_vector_get_size(&p_group->ports));
+                   res = FALSE;
+                   break;
+                }
+            }
+         }
+      } /* end of else */
+   } /* end of while */
+
+   if (res == TRUE)
+      osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+              "__osm_ftree_fabric_validate_topology: "
+              "Fabric topology has been identified as FatTree\n");
+   else
+      osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+              "__osm_ftree_fabric_validate_topology: "
+              "ERR AB0D: Fabric topology hasn't been identified as FatTree\n");
+
+   free(reference_sw_arr);
+   OSM_LOG_EXIT(&p_ftree->p_osm->log);
+   return res;
+} /* __osm_ftree_fabric_validate_topology() */
+
+/***************************************************
+ ***************************************************/
+
+static void
+__osm_ftree_set_sw_fwd_table(
+   IN  cl_map_item_t* const p_map_item, 
+   IN  void *context)
+{
+   ftree_sw_t * p_sw = (ftree_sw_t * const) p_map_item;
+   ftree_fabric_t * p_ftree = (ftree_fabric_t *)context;
+
+   /* calculate lft length rounded up to a multiple of 64 (block length) */ 
+   uint16_t lft_len = 64 * ((p_ftree->lft_max_lid_ho + 1 + 63) / 64);
+
+   p_sw->p_osm_sw->max_lid_ho = p_ftree->lft_max_lid_ho;
+
+   memcpy(p_ftree->p_osm->sm.ucast_mgr.lft_buf, 
+          p_sw->lft_buf, 
+          lft_len);
+   osm_ucast_mgr_set_fwd_table(&p_ftree->p_osm->sm.ucast_mgr, p_sw->p_osm_sw);
+}
+
+/***************************************************
+ ***************************************************/
+
+/*  
+ * Function: assign-up-going-port-by-descending-down
+ * Given   : a switch and a LID
+ * Pseudo code: 
+ *    foreach down-going-port-group (in indexing order)
+ *        skip this group if the LFT(LID) port is part of this group
+ *        find the least loaded port of the group (scan in indexing order)
+ *        r-port is the remote port connected to it
+ *        assign the remote switch node LFT(LID) to r-port
+ *        increase r-port usage counter
+ *        assign-up-going-port-by-descending-down to r-port node (recursion)
+ */
+
+static void
+__osm_ftree_fabric_route_upgoing_by_going_down(
+   IN  ftree_fabric_t * p_ftree,
+   IN  ftree_sw_t     * p_sw,
+   IN  ftree_sw_t     * p_prev_sw,
+   IN  ib_net16_t       target_lid,
+   IN  uint8_t          target_rank,
+   IN  boolean_t        is_real_lid,
+   IN  boolean_t        is_main_path,
+   IN  uint8_t          highest_rank_in_route)
+{
+   ftree_sw_t          * p_remote_sw;
+   uint16_t              ports_num;
+   ftree_port_group_t  * p_group;
+   ftree_port_t        * p_port;
+   ftree_port_t        * p_min_port;
+   uint16_t              i;
+   uint16_t              j;
+
+   /* we shouldn't enter here if both real_lid and main_path are false */
+   CL_ASSERT(is_real_lid || is_main_path);
+
+   /* can't be here for leaf switch, */
+   CL_ASSERT(p_sw->rank != (__osm_ftree_fabric_get_rank(p_ftree) - 1));
+
+   /* if there is no down-going ports */
+   if (p_sw->down_port_groups_num == 0) 
+       return;
+
+   /* foreach down-going port group (in indexing order) */
+   for (i = 0; i < p_sw->down_port_groups_num; i++)
+   {
+      p_group = p_sw->down_port_groups[i];
+
+      if ( p_prev_sw && (p_group->remote_base_lid == p_prev_sw->base_lid) ) 
+      {
+         /* This port group has a port that was used when we entered this switch,
+            which means that the current group points to the switch where we were
+            at the previous step of the algorithm (before going up).
+            Skipping this group. */
+            continue;
+      }
+
+      /* find the least loaded port of the group (in indexing order) */
+      p_min_port = NULL;
+      ports_num = (uint16_t)cl_ptr_vector_get_size(&p_group->ports);
+      /* ToDo: no need to select a least loaded port for non-main path.
+         Think about optimization. */
+      for (j = 0; j < ports_num; j++) 
+      {
+          cl_ptr_vector_at(&p_group->ports, j, (void **)&p_port);
+          if (!p_min_port)
+          {
+             /* first port that we're checking - set as port with the lowest load */
+             p_min_port = p_port;
+          }
+          else if (p_port->counter_up < p_min_port->counter_up)
+          {
+             /* this port is less loaded - use it as min */
+             p_min_port = p_port;
+          }
+      }
+      /* At this point we have selected a port in this group with the 
+         lowest load of upgoing routes.
+         Set on the remote switch how to get to the target_lid -
+         set LFT(target_lid) on the remote switch to the remote port */
+      p_remote_sw = p_group->remote_hca_or_sw.remote_sw;
+
+      /* Four possible cases:
+       *
+       *  1. is_real_lid == TRUE && is_main_path == TRUE: 
+       *      - going DOWN(TRUE,TRUE) through ALL the groups
+       *         + promoting port counter
+       *         + setting path in remote switch fwd tbl
+       *         + setting hops in remote switch on all the ports of each group
+       *      
+       *  2. is_real_lid == TRUE && is_main_path == FALSE: 
+       *      - going DOWN(TRUE,FALSE) through ALL the groups but only if
+       *        the remote (upper) switch hasn't been already configured 
+       *        for this target LID
+       *         + NOT promoting port counter
+       *         + setting path in remote switch fwd tbl if it hasn't been set yet
+       *         + setting hops in remote switch on all the ports of each group
+       *           if it hasn't been set yet
+       *
+       *  3. is_real_lid == FALSE && is_main_path == TRUE: 
+       *      - going DOWN(FALSE,TRUE) through ALL the groups
+       *         + promoting port counter
+       *         + NOT setting path in remote switch fwd tbl
+       *         + NOT setting hops in remote switch
+       *
+       *  4. is_real_lid == FALSE && is_main_path == FALSE: 
+       *      - illegal state - we shouldn't get here
+       */
+
+      /* second case: skip the port group if the remote (upper)
+         switch has been already configured for this target LID */
+      if ( is_real_lid && !is_main_path &&
+           __osm_ftree_sw_get_fwd_table_block(p_remote_sw,
+                                              cl_ntoh16(target_lid)) != OSM_NO_PATH )
+            continue;
+
+      /* setting fwd tbl port only if this is real LID */
+      if (is_real_lid)
+      {
+         __osm_ftree_sw_set_fwd_table_block(p_remote_sw,
+                                            cl_ntoh16(target_lid),
+                                            p_min_port->remote_port_num);
+         osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+                 "__osm_ftree_fabric_route_upgoing_by_going_down: "
+                 "Switch %s: set path to HCA LID 0x%x through port %u\n",
+                 __osm_ftree_tuple_to_str(p_remote_sw->tuple),
+                 cl_ntoh16(target_lid),
+                 p_min_port->remote_port_num);
+
+         /* On the remote switch that is pointed by the p_group,
+            set hops for ALL the ports in the remote group. */
+
+         for (j = 0; j < ports_num; j++)
+         {
+            cl_ptr_vector_at(&p_group->ports, j, (void **)&p_port);
+
+            __osm_ftree_sw_set_hops(p_remote_sw,
+                                    p_ftree->lft_max_lid_ho,
+                                    cl_ntoh16(target_lid),
+                                    p_port->remote_port_num,
+                                    ( (target_rank - highest_rank_in_route) +
+                                      (p_remote_sw->rank - highest_rank_in_route) ));
+         }
+
+
+      }
+   
+      /* The number of upgoing routes is tracked in the 
+         p_port->counter_up counter of the port that belongs to
+         the upper side of the link (on switch with lower rank).
+         Counter is promoted only if we're routing LID on the main
+         path (whether it's a real LID or a dummy one). */
+      if (is_main_path)
+         p_min_port->counter_up++;
+
+      /* Recursion step:
+         Assign upgoing ports by stepping down, starting on REMOTE switch.
+         Recursion stop condition - if the REMOTE switch is a leaf switch. */
+      if (p_remote_sw->rank != (__osm_ftree_fabric_get_rank(p_ftree) - 1))
+      {
+         __osm_ftree_fabric_route_upgoing_by_going_down(
+               p_ftree,
+               p_remote_sw,   /* remote switch - used as a route-upgoing alg. start point */
+               NULL,          /* prev. position - NULL to mark that we went down and not up */
+               target_lid,    /* LID that we're routing to */
+               target_rank,   /* rank of the LID that we're routing to */
+               is_real_lid,   /* whether the target LID is real or dummy */
+               is_main_path,  /* whether this is path to HCA that should by tracked by counters */
+               highest_rank_in_route); /* highest visited point in the tree before going down */
+      }
+   }
+   /* done scanning all the down-going port groups */
+
+} /* __osm_ftree_fabric_route_upgoing_by_going_down() */
+
+/***************************************************/
+
+/*  
+ * Function: assign-down-going-port-by-descending-up
+ * Given   : a switch and a LID
+ * Pseudo code: 
+ *    find the least loaded port of all the upgoing groups (scan in indexing order)
+ *    assign the LFT(LID) of remote switch to that port
+ *    track that port usage
+ *    assign-up-going-port-by-descending-down on CURRENT switch
+ *    assign-down-going-port-by-descending-up on REMOTE switch (recursion)
+ */
+
+static void
+__osm_ftree_fabric_route_downgoing_by_going_up(
+   IN  ftree_fabric_t * p_ftree,
+   IN  ftree_sw_t     * p_sw,
+   IN  ftree_sw_t     * p_prev_sw,
+   IN  ib_net16_t       target_lid,
+   IN  uint8_t          target_rank,
+   IN  boolean_t        is_real_lid,
+   IN  boolean_t        is_main_path)
+{
+   ftree_sw_t          * p_remote_sw;
+   uint16_t              ports_num;
+   ftree_port_group_t  * p_group;
+   ftree_port_t        * p_port;
+   ftree_port_group_t  * p_min_group;
+   ftree_port_t        * p_min_port;
+   uint16_t              i;
+   uint16_t              j;
+
+   /* we shouldn't enter here if both real_lid and main_path are false */
+   CL_ASSERT(is_real_lid || is_main_path);
+
+   /* If this switch isn't a leaf switch:
+      Assign upgoing ports by stepping down, starting on THIS switch. */
+   if (p_sw->rank != (__osm_ftree_fabric_get_rank(p_ftree) - 1))
+   {
+      __osm_ftree_fabric_route_upgoing_by_going_down(
+         p_ftree,
+         p_sw,          /* local switch - used as a route-upgoing alg. start point */
+         p_prev_sw,     /* switch that we went up from (NULL means that we went down) */
+         target_lid,    /* LID that we're routing to */
+         target_rank,   /* rank of the LID that we're routing to */
+         is_real_lid,   /* whether this target LID is real or dummy */
+         is_main_path,  /* whether this path to HCA should by tracked by counters */
+         p_sw->rank);   /* the highest visited point in the tree before going down */
+   }
+
+   /* recursion stop condition - if it's a root switch, */
+   if (p_sw->rank == 0)
+      return;
+
+   /* Find the least loaded port of all the upgoing port groups
+      (in indexing order of the remote switches). */
+   p_min_group = NULL;
+   p_min_port = NULL;
+   for (i = 0; i < p_sw->up_port_groups_num; i++)
+   {
+      p_group = p_sw->up_port_groups[i];
+
+      ports_num = (uint16_t)cl_ptr_vector_get_size(&p_group->ports);
+      for (j = 0; j < ports_num; j++)
+      {
+         cl_ptr_vector_at(&p_group->ports, j, (void **)&p_port);
+         if (!p_min_group)
+         {
+            /* first port that we're checking - use
+               it as a port with the lowest load */
+            p_min_group = p_group;
+            p_min_port = p_port;
+         }
+         else
+         { 
+            if ( p_port->counter_down < p_min_port->counter_down  )
+            {
+               /* this port is less loaded - use it as min */
+               p_min_group = p_group;
+               p_min_port = p_port;
+            }
+         }
+      }
+   }
+
+   /* At this point we have selected a group and port with the 
+      lowest load of downgoing routes.
+      Set on the remote switch how to get to the target_lid -
+      set LFT(target_lid) on the remote switch to the remote port */
+   p_remote_sw = p_min_group->remote_hca_or_sw.remote_sw;
+
+   /* Four possible cases:
+    *
+    *  1. is_real_lid == TRUE && is_main_path == TRUE: 
+    *      - going UP(TRUE,TRUE) on selected min_group and min_port
+    *         + promoting port counter
+    *         + setting path in remote switch fwd tbl
+    *         + setting hops in remote switch on all the ports of selected group
+    *      - going UP(TRUE,FALSE) on rest of the groups, each time on port 0
+    *         + NOT promoting port counter
+    *         + setting path in remote switch fwd tbl if it hasn't been set yet
+    *         + setting hops in remote switch on all the ports of each group
+    *           if it hasn't been set yet
+    *      
+    *  2. is_real_lid == TRUE && is_main_path == FALSE: 
+    *      - going UP(TRUE,FALSE) on ALL the groups, each time on port 0,
+    *        but only if the remote (upper) switch hasn't been already 
+    *        configured for this target LID
+    *         + NOT promoting port counter
+    *         + setting path in remote switch fwd tbl if it hasn't been set yet
+    *         + setting hops in remote switch on all the ports of each group
+    *           if it hasn't been set yet
+    *
+    *  3. is_real_lid == FALSE && is_main_path == TRUE: 
+    *      - going UP(FALSE,TRUE) ONLY on selected min_group and min_port
+    *         + promoting port counter
+    *         + NOT setting path in remote switch fwd tbl
+    *         + NOT setting hops in remote switch
+    *
+    *  4. is_real_lid == FALSE && is_main_path == FALSE: 
+    *      - illegal state - we shouldn't get here
+    */
+
+   /* covering first half of case 1, and case 3 */
+   if (is_main_path)
+   {
+      if (p_sw->rank == (__osm_ftree_fabric_get_rank(p_ftree) - 1))
+      {
+         osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+                 "__osm_ftree_fabric_route_downgoing_by_going_up: "
+                 " - Routing MAIN path for %s HCA LID 0x%x: %s --> %s\n",
+                 (is_real_lid)? "real" : "DUMMY",
+                 cl_ntoh16(target_lid),
+                 __osm_ftree_tuple_to_str(p_sw->tuple),
+                 __osm_ftree_tuple_to_str(p_remote_sw->tuple));
+      }
+      /* The number of downgoing routes is tracked in the 
+         p_port->counter_down counter of the port that belongs to
+         the lower side of the link (on switch with higher rank) */
+      p_min_port->counter_down++;
+      if (is_real_lid)
+      {
+         __osm_ftree_sw_set_fwd_table_block(p_remote_sw,
+                                            cl_ntoh16(target_lid),
+                                            p_min_port->remote_port_num);
+         osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+                 "__osm_ftree_fabric_route_downgoing_by_going_up: "
+                 "Switch %s: set path to HCA LID 0x%x through port %u\n",
+                 __osm_ftree_tuple_to_str(p_remote_sw->tuple),
+                 cl_ntoh16(target_lid),p_min_port->remote_port_num);
+
+         /* On the remote switch that is pointed by the min_group,
+            set hops for ALL the ports in the remote group. */
+
+         ports_num = (uint16_t)cl_ptr_vector_get_size(&p_min_group->ports);
+         for (j = 0; j < ports_num; j++)
+         {
+            cl_ptr_vector_at(&p_min_group->ports, j, (void **)&p_port);
+            __osm_ftree_sw_set_hops(p_remote_sw,
+                                    p_ftree->lft_max_lid_ho,
+                                    cl_ntoh16(target_lid),
+                                    p_port->remote_port_num,
+                                    target_rank - p_remote_sw->rank);
+         }
+      }
+
+      /* Recursion step: 
+         Assign downgoing ports by stepping up, starting on REMOTE switch. */
+      __osm_ftree_fabric_route_downgoing_by_going_up(
+            p_ftree,
+            p_remote_sw,    /* remote switch - used as a route-downgoing alg. next step point */
+            p_sw,           /* this switch - prev. position switch for the function */
+            target_lid,     /* LID that we're routing to */
+            target_rank,    /* rank of the LID that we're routing to */
+            is_real_lid,    /* whether this target LID is real or dummy */
+            is_main_path);  /* whether this is path to HCA that should by tracked by counters */
+   }
+
+   /* we're done for the third case */
+   if (!is_real_lid)
+      return;
+
+   /* What's left to do at this point:
+    *
+    *  1. is_real_lid == TRUE && is_main_path == TRUE: 
+    *      - going UP(TRUE,FALSE) on rest of the groups, each time on port 0, 
+    *        but only if the remote (upper) switch hasn't been already 
+    *        configured for this target LID
+    *         + NOT promoting port counter
+    *         + setting path in remote switch fwd tbl if it hasn't been set yet
+    *         + setting hops in remote switch on all the ports of each group
+    *           if it hasn't been set yet
+    *      
+    *  2. is_real_lid == TRUE && is_main_path == FALSE: 
+    *      - going UP(TRUE,FALSE) on ALL the groups, each time on port 0,
+    *        but only if the remote (upper) switch hasn't been already 
+    *        configured for this target LID
+    *         + NOT promoting port counter
+    *         + setting path in remote switch fwd tbl if it hasn't been set yet
+    *         + setting hops in remote switch on all the ports of each group
+    *           if it hasn't been set yet
+    *
+    *  These two rules can be rephrased this way:
+    *   - foreach UP port group
+    *      + if remote switch has been set with the target LID
+    *         - skip this port group
+    *      + else
+    *         - select port 0
+    *         - do NOT promote port counter
+    *         - set path in remote switch fwd tbl
+    *         - set hops in remote switch on all the ports of this group
+    *         - go UP(TRUE,FALSE) to the remote switch
+    */
+
+   for (i = 0; i < p_sw->up_port_groups_num; i++)
+   {
+      p_group = p_sw->up_port_groups[i];
+      p_remote_sw = p_group->remote_hca_or_sw.remote_sw;
+
+      /* skip if target lid has been already set on remote switch fwd tbl */
+      if (__osm_ftree_sw_get_fwd_table_block(
+                  p_remote_sw,cl_ntoh16(target_lid)) != OSM_NO_PATH)
+         continue;
+
+      if (p_sw->rank == (__osm_ftree_fabric_get_rank(p_ftree) - 1))
+      {
+         osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+                 "__osm_ftree_fabric_route_downgoing_by_going_up: "
+                 " - Routing SECONDARY path for LID 0x%x: %s --> %s\n",
+                cl_ntoh16(target_lid),
+                __osm_ftree_tuple_to_str(p_sw->tuple),
+                __osm_ftree_tuple_to_str(p_remote_sw->tuple));
+      }
+    
+      cl_ptr_vector_at(&p_group->ports, 0, (void **)&p_port);
+      __osm_ftree_sw_set_fwd_table_block(p_remote_sw,
+                                         cl_ntoh16(target_lid),
+                                         p_port->remote_port_num);
+
+      /* On the remote switch that is pointed by the p_group,
+         set hops for ALL the ports in the remote group. */
+
+      ports_num = (uint16_t)cl_ptr_vector_get_size(&p_group->ports);
+      for (j = 0; j < ports_num; j++)
+      {
+         cl_ptr_vector_at(&p_group->ports, j, (void **)&p_port);
+
+         __osm_ftree_sw_set_hops(p_remote_sw,
+                                 p_ftree->lft_max_lid_ho,
+                                 cl_ntoh16(target_lid),
+                                 p_port->remote_port_num,
+                                 target_rank - p_remote_sw->rank);
+      }
+
+      /* Recursion step: 
+         Assign downgoing ports by stepping up, starting on REMOTE switch. */
+      __osm_ftree_fabric_route_downgoing_by_going_up(
+            p_ftree,
+            p_remote_sw, /* remote switch - used as a route-downgoing alg. next step point */
+            p_sw,        /* this switch - prev. position switch for the function */
+            target_lid,  /* LID that we're routing to */
+            target_rank, /* rank of the LID that we're routing to */
+            TRUE,        /* whether the target LID is real or dummy */
+            FALSE);      /* whether this is path to HCA that should by tracked by counters */
+   }
+
+} /* ftree_fabric_route_downgoing_by_going_up() */
+
+/***************************************************/
+
+/*  
+ * Pseudo code: 
+ *    foreach leaf switch (in indexing order)
+ *       for each compute node (in indexing order)
+ *          obtain the LID of the compute node
+ *          set local LFT(LID) of the port connecting to compute node
+ *          call assign-down-going-port-by-descending-up(TRUE,TRUE) on CURRENT switch
+ *       for each MISSING compute node
+ *          call assign-down-going-port-by-descending-up(FALSE,TRUE) on CURRENT switch
+ */
+
+static void
+__osm_ftree_fabric_route_to_hcas(
+   IN  ftree_fabric_t * p_ftree)
+{
+   ftree_sw_t         * p_sw;
+   ftree_port_group_t * p_group;
+   ftree_port_t       * p_port;
+   uint32_t             i;
+   uint32_t             j;
+   ib_net16_t           remote_lid;
+
+   OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_fabric_route_to_hcas);
+
+   /* for each leaf switch (in indexing order) */
+   for(i = 0; i < p_ftree->leaf_switches_num; i++)
+   {
+      p_sw = p_ftree->leaf_switches[i];
+
+      /* for each HCA connected to this switch */
+      for (j = 0; j < p_sw->down_port_groups_num; j++)
+      {
+         /* obtain the LID of HCA port */
+         p_group = p_sw->down_port_groups[j];
+         remote_lid = p_group->remote_base_lid;
+
+         /* set local LFT(LID) to the port that is connected to HCA */
+         cl_ptr_vector_at(&p_group->ports, 0, (void **)&p_port);
+         __osm_ftree_sw_set_fwd_table_block(p_sw,
+                                            cl_ntoh16(remote_lid),
+                                            p_port->port_num);
+         osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+                 "__osm_ftree_fabric_route_to_hcas: "
+                 "Switch %s: set path to HCA LID 0x%x through port %u\n",
+                 __osm_ftree_tuple_to_str(p_sw->tuple),
+                 cl_ntoh16(remote_lid),
+                 p_port->port_num);
+
+         /* set local min hop table(LID) to route to the CA */
+         __osm_ftree_sw_set_hops(p_sw,
+                                 p_ftree->lft_max_lid_ho,
+                                 cl_ntoh16(remote_lid),
+                                 p_port->port_num,
+                                 1);
+
+         /* assign downgoing ports by stepping up */
+         __osm_ftree_fabric_route_downgoing_by_going_up(
+               p_ftree,
+               p_sw,       /* local switch - used as a route-downgoing alg. start point */
+               NULL,       /* prev. position switch */
+               remote_lid, /* LID that we're routing to */
+               __osm_ftree_fabric_get_rank(p_ftree), /* rank of the LID that we're routing to */
+               TRUE,       /* whether this HCA LID is real or dummy */
+               TRUE);      /* whether this path to HCA should by tracked by counters */
+      }
+
+      /* We're done with the real HCAs. Now route the dummy HCAs that are missing.
+         When routing to dummy HCAs we don't fill lid matrices. */
+
+      if (p_ftree->max_hcas_per_leaf > p_sw->down_port_groups_num)
+      {
+         osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,"__osm_ftree_fabric_route_to_hcas: "
+                 "Routing %u dummy HCAs\n",
+                 p_ftree->max_hcas_per_leaf - p_sw->down_port_groups_num);
+         for ( j = 0;
+               ((int)j) < (p_ftree->max_hcas_per_leaf - p_sw->down_port_groups_num);
+               j++)
+         {
+            /* assign downgoing ports by stepping up */
+            __osm_ftree_fabric_route_downgoing_by_going_up(
+                  p_ftree,
+                  p_sw,    /* local switch - used as a route-downgoing alg. start point */
+                  NULL,    /* prev. position switch */
+                  0,       /* LID that we're routing to - ignored for dummy HCA */
+                  0,       /* rank of the LID that we're routing to - ignored for dummy HCA */
+                  FALSE,   /* whether this HCA LID is real or dummy */
+                  TRUE);   /* whether this path to HCA should by tracked by counters */
+         }
+      }
+   }
+   /* done going through all the leaf switches */
+   OSM_LOG_EXIT(&p_ftree->p_osm->log);
+} /* __osm_ftree_fabric_route_to_hcas() */
+
+/***************************************************/
+
+/*  
+ * Pseudo code: 
+ *    foreach switch in fabric
+ *       obtain its LID
+ *       set local LFT(LID) to port 0
+ *       call assign-down-going-port-by-descending-up(TRUE,FALSE) on CURRENT switch
+ *
+ * Routing to switch is similar to routing a REAL hca lid on SECONDARY path:
+ *   - we should set fwd tables
+ *   - we should NOT update port counters
+ */
+
+static void
+__osm_ftree_fabric_route_to_switches(
+   IN  ftree_fabric_t * p_ftree)
+{
+   ftree_sw_t         * p_sw;
+   ftree_sw_t         * p_next_sw;
+
+   OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_fabric_route_to_switches);
+
+   p_next_sw = (ftree_sw_t *)cl_qmap_head(&p_ftree->sw_tbl);
+   while( p_next_sw != (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl) )
+   {
+      p_sw = p_next_sw;
+      p_next_sw = (ftree_sw_t *)cl_qmap_next(&p_sw->map_item );
+
+      /* set local LFT(LID) to 0 (route to itself) */
+      __osm_ftree_sw_set_fwd_table_block(p_sw,
+                                         cl_ntoh16(p_sw->base_lid),
+                                         0);
+
+      osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+              "__osm_ftree_fabric_route_to_switches: "
+              "Switch %s (LID 0x%x): routing switch-to-switch pathes\n",
+              __osm_ftree_tuple_to_str(p_sw->tuple),
+              cl_ntoh16(p_sw->base_lid));
+
+      /* set min hop table of the switch to itself */
+      __osm_ftree_sw_set_hops(p_sw,
+                              p_ftree->lft_max_lid_ho,
+                              cl_ntoh16(p_sw->base_lid),
+                              0, /* port_num */
+                              0);/* hops     */
+
+      __osm_ftree_fabric_route_downgoing_by_going_up(
+            p_ftree,
+            p_sw,           /* local switch - used as a route-downgoing alg. start point */
+            NULL,           /* prev. position switch */
+            p_sw->base_lid, /* LID that we're routing to */
+            p_sw->rank,     /* rank of the LID that we're routing to */
+            TRUE,           /* whether the target LID is a real or dummy */
+            FALSE);         /* whether this path should by tracked by counters */
+   }
+
+   OSM_LOG_EXIT(&p_ftree->p_osm->log);
+} /* __osm_ftree_fabric_route_to_switches() */
+
+/***************************************************
+ ***************************************************/
+
+static int 
+__osm_ftree_fabric_populate_switches(
+   IN  ftree_fabric_t * p_ftree)
+{
+   osm_switch_t * p_osm_sw;
+   osm_switch_t * p_next_osm_sw;
+
+   OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_fabric_populate_switches);
+
+   p_next_osm_sw = (osm_switch_t *)cl_qmap_head(&p_ftree->p_osm->subn.sw_guid_tbl);
+   while( p_next_osm_sw != (osm_switch_t *)cl_qmap_end(&p_ftree->p_osm->subn.sw_guid_tbl) )
+   {
+      p_osm_sw = p_next_osm_sw;
+      p_next_osm_sw = (osm_switch_t *)cl_qmap_next(&p_osm_sw->map_item );
+      __osm_ftree_fabric_add_sw(p_ftree,p_osm_sw);
+   }
+   OSM_LOG_EXIT(&p_ftree->p_osm->log);
+   return 0;
+} /* __osm_ftree_fabric_populate_switches() */
+
+/***************************************************
+ ***************************************************/
+
+static int 
+__osm_ftree_fabric_populate_hcas(
+   IN  ftree_fabric_t * p_ftree)
+{
+   osm_node_t   * p_osm_node;
+   osm_node_t   * p_next_osm_node;
+
+   OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_fabric_populate_hcas);
+
+   p_next_osm_node = (osm_node_t *)cl_qmap_head(&p_ftree->p_osm->subn.node_guid_tbl);
+   while( p_next_osm_node != (osm_node_t *)cl_qmap_end(&p_ftree->p_osm->subn.node_guid_tbl) )
+   {
+      p_osm_node = p_next_osm_node;
+      p_next_osm_node = (osm_node_t *)cl_qmap_next(&p_osm_node->map_item);
+      switch (osm_node_get_type(p_osm_node))
+      {
+         case IB_NODE_TYPE_CA:
+            __osm_ftree_fabric_add_hca(p_ftree,p_osm_node);
+            break;
+         case IB_NODE_TYPE_ROUTER:
+            break;
+         case IB_NODE_TYPE_SWITCH:
+            /* all the switches added separately */
+            break;
+         default:
+            osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+                    "__osm_ftree_fabric_populate_hcas: ERR AB0E: "
+                    "Node GUID 0x%016" PRIx64 " - Unknown node type: %s\n",
+                    cl_ntoh64(osm_node_get_node_guid(p_osm_node)),
+                    ib_get_node_type_str(osm_node_get_type(p_osm_node)));
+            OSM_LOG_EXIT(&p_ftree->p_osm->log);
+            return -1;
+      }
+   }
+
+   OSM_LOG_EXIT(&p_ftree->p_osm->log);
+   return 0;
+} /* __osm_ftree_fabric_populate_hcas() */
+
+/***************************************************
+ ***************************************************/
+
+static void
+__osm_ftree_rank_from_switch(
+   IN  ftree_fabric_t * p_ftree, 
+   IN  ftree_sw_t *     p_starting_sw)
+{
+   ftree_sw_t   * p_sw;
+   ftree_sw_t   * p_remote_sw;
+   osm_node_t   * p_node;
+   osm_node_t   * p_remote_node;
+   osm_physp_t  * p_osm_port;
+   uint8_t        i;
+   cl_list_t      bfs_list;
+   ftree_sw_tbl_element_t * p_sw_tbl_element = NULL;
+
+   p_starting_sw->rank = 0;
+
+   /* Run BFS scan of the tree, starting from this switch */
+
+   cl_list_init(&bfs_list, cl_qmap_count(&p_ftree->sw_tbl));
+   cl_list_insert_tail(&bfs_list, &__osm_ftree_sw_tbl_element_create(p_starting_sw)->map_item);
+
+   while (!cl_is_list_empty(&bfs_list))
+   {
+      p_sw_tbl_element = (ftree_sw_tbl_element_t *)cl_list_remove_head(&bfs_list);
+      p_sw = p_sw_tbl_element->p_sw;
+      __osm_ftree_sw_tbl_element_destroy(p_sw_tbl_element);
+
+      p_node = osm_switch_get_node_ptr(p_sw->p_osm_sw);
+
+      /* note: skipping port 0 on switches */
+      for (i = 1; i < osm_node_get_num_physp(p_node); i++)
+      {
+         p_osm_port = osm_node_get_physp_ptr(p_node,i);
+         if (!osm_physp_is_valid(p_osm_port)) 
+            continue;
+         if (!osm_link_is_healthy(p_osm_port)) 
+            continue;
+
+         p_remote_node = osm_node_get_remote_node(p_node,i,NULL);
+         if (!p_remote_node)
+            continue;
+         if (osm_node_get_type(p_remote_node) != IB_NODE_TYPE_SWITCH)
+            continue;
+
+         p_remote_sw = (ftree_sw_t *)cl_qmap_get(&p_ftree->sw_tbl,
+                                                 osm_node_get_node_guid(p_remote_node));
+         if (p_remote_sw == (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl))
+         {
+            /* remote node is not a switch */
+            continue;
+         }
+         if (__osm_ftree_sw_ranked(p_remote_sw) && p_remote_sw->rank <= (p_sw->rank + 1))
+            continue;
+
+         /* rank the remote switch and add it to the BFS list */
+         p_remote_sw->rank = p_sw->rank + 1;
+         cl_list_insert_tail(&bfs_list, 
+                             &__osm_ftree_sw_tbl_element_create(p_remote_sw)->map_item);
+      }
+   }
+} /* __osm_ftree_rank_from_switch() */
+
+
+/***************************************************
+ ***************************************************/
+
+static int 
+__osm_ftree_rank_switches_from_hca(
+   IN  ftree_fabric_t * p_ftree,
+   IN  ftree_hca_t    * p_hca)
+{
+   ftree_sw_t     * p_sw;
+   osm_node_t     * p_osm_node = p_hca->p_osm_node;
+   osm_node_t     * p_remote_osm_node;
+   osm_physp_t    * p_osm_port;
+   static uint8_t   i = 0;
+   int res = 0;
+
+   OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_rank_switches_from_hca);
+
+   for (i = 0; i < osm_node_get_num_physp(p_osm_node); i++)
+   {
+      p_osm_port = osm_node_get_physp_ptr(p_osm_node,i);
+      if (!osm_physp_is_valid(p_osm_port)) 
+         continue;
+      if (!osm_link_is_healthy(p_osm_port)) 
+         continue;
+
+      p_remote_osm_node = osm_node_get_remote_node(p_osm_node,i,NULL);
+
+      switch (osm_node_get_type(p_remote_osm_node))
+      {
+         case IB_NODE_TYPE_CA:
+            /* HCA connected directly to another HCA - not FatTree */
+            osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+                    "__osm_ftree_rank_switches_from_hca: ERR AB0F: "
+                    "HCA conected directly to another HCA: "
+                    "0x%016" PRIx64 " <---> 0x%016" PRIx64 "\n",
+                    cl_ntoh64(osm_node_get_node_guid(p_hca->p_osm_node)),
+                    cl_ntoh64(osm_node_get_node_guid(p_remote_osm_node)));
+            res = -1;
+            goto Exit;
+
+         case IB_NODE_TYPE_ROUTER:
+            /* leaving this port - proceeding to the next one */
+            continue;
+
+         case IB_NODE_TYPE_SWITCH:
+            /* continue with this port */
+            break;
+
+         default:
+            osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+                    "__osm_ftree_rank_switches_from_hca: ERR AB10: "
+                    "Node GUID 0x%016" PRIx64 " - Unknown node type: %s\n",
+                    cl_ntoh64(osm_node_get_node_guid(p_remote_osm_node)),
+                    ib_get_node_type_str(osm_node_get_type(p_remote_osm_node)));
+            res = -1;
+            goto Exit;
+      }
+
+      /* remote node is switch */
+
+      p_sw = (ftree_sw_t *)cl_qmap_get(&p_ftree->sw_tbl,
+                                       p_osm_port->p_remote_physp->p_node->node_info.node_guid);
+
+      CL_ASSERT(p_sw != (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl));
+
+      if (__osm_ftree_sw_ranked(p_sw) && p_sw->rank == 0)
+         continue;
+
+      osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+              "__osm_ftree_rank_switches_from_hca: "
+              "Marking rank of switch that is directly connected to HCA:\n"
+              "                                            - HCA guid   : 0x%016" PRIx64 "\n"
+              "                                            - Switch guid: 0x%016" PRIx64 "\n"
+              "                                            - Switch LID : 0x%x\n",
+              cl_ntoh64(osm_node_get_node_guid(p_hca->p_osm_node)),
+              cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))),
+              cl_ntoh16(p_sw->base_lid));
+      __osm_ftree_rank_from_switch(p_ftree, p_sw);
+   }
+
+ Exit:
+   OSM_LOG_EXIT(&p_ftree->p_osm->log);
+   return res;
+} /* __osm_ftree_rank_switches_from_hca() */
+
+/***************************************************/
+
+static void 
+__osm_ftree_sw_reverse_rank(
+   IN  cl_map_item_t* const p_map_item, 
+   IN  void *context)
+{
+   ftree_fabric_t * p_ftree = (ftree_fabric_t *)context;
+   ftree_sw_t     * p_sw = (ftree_sw_t * const) p_map_item;
+   p_sw->rank = __osm_ftree_fabric_get_rank(p_ftree) - p_sw->rank - 1;
+}
+
+/***************************************************
+ ***************************************************/
+
+static int
+__osm_ftree_fabric_construct_hca_ports(
+   IN  ftree_fabric_t  * p_ftree, 
+   IN  ftree_hca_t     * p_hca)
+{
+   ftree_sw_t      * p_remote_sw;
+   osm_node_t      * p_node = p_hca->p_osm_node;
+   osm_node_t      * p_remote_node;
+   uint8_t           remote_node_type;
+   ib_net64_t        remote_node_guid;
+   osm_physp_t     * p_remote_osm_port;
+   uint8_t           i;
+   uint8_t           remote_port_num;
+   int res = 0;
+
+   for (i = 0; i < osm_node_get_num_physp(p_node); i++)
+   {
+      osm_physp_t * p_osm_port = osm_node_get_physp_ptr(p_node,i);
+
+      if (!osm_physp_is_valid(p_osm_port)) 
+         continue;
+      if (!osm_link_is_healthy(p_osm_port)) 
+         continue;
+
+      p_remote_osm_port = osm_physp_get_remote(p_osm_port);
+      p_remote_node = osm_node_get_remote_node(p_node,i,&remote_port_num);
+
+      if (!p_remote_osm_port)
+         continue;
+
+      remote_node_type = osm_node_get_type(p_remote_node);
+      remote_node_guid = osm_node_get_node_guid(p_remote_node);
+
+      switch (remote_node_type)
+      {
+         case IB_NODE_TYPE_ROUTER:
+            /* leaving this port - proceeding to the next one */
+            continue;
+
+         case IB_NODE_TYPE_CA:
+            /* HCA connected directly to another HCA - not FatTree */
+            osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+                    "__osm_ftree_fabric_construct_hca_ports: ERR AB11: "
+                    "HCA conected directly to another HCA: "
+                    "0x%016" PRIx64 " <---> 0x%016" PRIx64 "\n",
+                    cl_ntoh64(osm_node_get_node_guid(p_node)),
+                    cl_ntoh64(remote_node_guid));
+            res = -1;
+            goto Exit;
+
+         case IB_NODE_TYPE_SWITCH:
+            /* continue with this port */
+            break;
+
+         default:
+            osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+                    "__osm_ftree_fabric_construct_hca_ports: ERR AB12: "
+                    "Node GUID 0x%016" PRIx64 " - Unknown node type: %s\n",
+                    cl_ntoh64(remote_node_guid),
+                    ib_get_node_type_str(remote_node_type));
+            res = -1;
+            goto Exit;
+      }
+
+      /* remote node is switch */
+
+      p_remote_sw = (ftree_sw_t *)cl_qmap_get(&p_ftree->sw_tbl,remote_node_guid);
+      CL_ASSERT( p_remote_sw != (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl) );
+      CL_ASSERT( (p_remote_sw->rank + 1) == __osm_ftree_fabric_get_rank(p_ftree) );
+
+      __osm_ftree_hca_add_port(
+            p_hca,                                     /* local ftree_hca object */
+            i,                                         /* local port number */
+            remote_port_num,                           /* remote port number */
+            osm_node_get_base_lid(p_node, i),          /* local lid */
+            osm_node_get_base_lid(p_remote_node, 0),   /* remote lid */
+            osm_physp_get_port_guid(p_osm_port),       /* local port guid */
+            osm_physp_get_port_guid(p_remote_osm_port),/* remote port guid */
+            remote_node_guid,                          /* remote node guid */
+            remote_node_type,                          /* remote node type */
+            (void *) p_remote_sw);                     /* remote ftree_hca/sw object */
+   }
+
+ Exit:
+   return res;
+} /* __osm_ftree_fabric_construct_hca_ports() */
+
+/***************************************************
+ ***************************************************/
+
+static int 
+__osm_ftree_fabric_construct_sw_ports(
+   IN  ftree_fabric_t  * p_ftree, 
+   IN  ftree_sw_t      * p_sw)
+{
+   ftree_hca_t       * p_remote_hca;
+   ftree_sw_t        * p_remote_sw;
+   osm_node_t        * p_node = osm_switch_get_node_ptr(p_sw->p_osm_sw);
+   osm_node_t        * p_remote_node;
+   ib_net16_t          remote_base_lid;
+   uint8_t             remote_node_type;
+   ib_net64_t          remote_node_guid;
+   osm_physp_t       * p_remote_osm_port;
+   ftree_direction_t   direction;
+   void              * p_remote_hca_or_sw;
+   uint8_t             i;
+   uint8_t             remote_port_num;
+   int res = 0;
+
+   CL_ASSERT(osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH);
+
+   for (i = 0; i < osm_node_get_num_physp(p_node); i++)
+   {
+      osm_physp_t * p_osm_port = osm_node_get_physp_ptr(p_node,i);
+
+      if (!osm_physp_is_valid(p_osm_port)) 
+         continue;
+      if (!osm_link_is_healthy(p_osm_port)) 
+         continue;
+
+      p_remote_osm_port = osm_physp_get_remote(p_osm_port);
+      p_remote_node = osm_node_get_remote_node(p_node,i,&remote_port_num);
+
+      if (!p_remote_osm_port)
+         continue;
+
+      remote_node_type = osm_node_get_type(p_remote_node);
+      remote_node_guid = osm_node_get_node_guid(p_remote_node);
+
+      switch (remote_node_type)
+      {
+         case IB_NODE_TYPE_ROUTER:
+            /* leaving this port - proceeding to the next one */
+            continue;
+
+         case IB_NODE_TYPE_CA:
+            /* switch connected to hca */
+
+            CL_ASSERT((p_sw->rank + 1) == __osm_ftree_fabric_get_rank(p_ftree));
+
+            p_remote_hca = (ftree_hca_t *)cl_qmap_get(&p_ftree->hca_tbl,remote_node_guid);
+            CL_ASSERT(p_remote_hca != (ftree_hca_t *)cl_qmap_end(&p_ftree->hca_tbl));
+
+            p_remote_hca_or_sw = (void *)p_remote_hca;
+            direction = FTREE_DIRECTION_DOWN;
+
+            remote_base_lid = osm_physp_get_base_lid(p_remote_osm_port);
+            break;
+
+         case IB_NODE_TYPE_SWITCH:
+            /* switch connected to another switch */
+
+            p_remote_sw = (ftree_sw_t *)cl_qmap_get(&p_ftree->sw_tbl,remote_node_guid);
+            CL_ASSERT(p_remote_sw != (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl));
+            p_remote_hca_or_sw = (void *)p_remote_sw;
+
+            if (abs(p_sw->rank - p_remote_sw->rank) != 1)
+            {
+               osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+                       "__osm_ftree_fabric_construct_sw_ports: ERR AB16: "
+                       "Illegal link between switches with ranks %u and %u:\n"
+                       "       GUID 0x%016" PRIx64 ", LID 0x%x, rank %u\n"
+                       "       GUID 0x%016" PRIx64 ", LID 0x%x, rank %u\n",
+                       p_sw->rank,
+                       p_remote_sw->rank,
+                       cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))),
+                       cl_ntoh16(p_sw->base_lid),
+                       p_sw->rank,
+                       cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_remote_sw->p_osm_sw))),
+                       cl_ntoh16(p_remote_sw->base_lid),
+                       p_remote_sw->rank);
+               res = -1;
+               goto Exit;
+            }
+
+            if (p_sw->rank > p_remote_sw->rank)
+               direction = FTREE_DIRECTION_UP;
+            else
+               direction = FTREE_DIRECTION_DOWN;
+
+            /* switch LID is only in port 0 port_info structure */
+            remote_base_lid = osm_node_get_base_lid(p_remote_node, 0);
+
+            break;
+
+         default:
+            osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+                    "__osm_ftree_fabric_construct_sw_ports: ERR AB13: "
+                    "Node GUID 0x%016" PRIx64 " - Unknown node type: %s\n",
+                    cl_ntoh64(remote_node_guid),
+                    ib_get_node_type_str(remote_node_type));
+            res = -1;
+            goto Exit;
+      }
+      __osm_ftree_sw_add_port(
+            p_sw,                                       /* local ftree_sw object */     
+            i,                                          /* local port number */          
+            remote_port_num,                            /* remote port number */         
+            p_sw->base_lid,                             /* local lid */                  
+            remote_base_lid,                            /* remote lid */                 
+            osm_physp_get_port_guid(p_osm_port),        /* local port guid */            
+            osm_physp_get_port_guid(p_remote_osm_port), /* remote port guid */           
+            remote_node_guid,                           /* remote node guid */           
+            remote_node_type,                           /* remote node type */           
+            p_remote_hca_or_sw,                         /* remote ftree_hca/sw object */ 
+            direction);                                 /* port direction (up or down) */
+
+      /* Track the max lid (in host order) that exists in the fabric */
+      if (cl_ntoh16(remote_base_lid) > p_ftree->lft_max_lid_ho)
+         p_ftree->lft_max_lid_ho = cl_ntoh16(remote_base_lid);
+   }
+
+ Exit:
+   return res;
+} /* __osm_ftree_fabric_construct_sw_ports() */
+
+/***************************************************
+ ***************************************************/
+
+/* ToDo: improve ranking algorithm complexity
+   by propogating BFS from more nodes */ 
+static int
+__osm_ftree_fabric_perform_ranking(
+   IN  ftree_fabric_t * p_ftree)
+{
+   ftree_hca_t * p_hca;
+   ftree_hca_t * p_next_hca;
+   int res = 0;
+
+   OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_fabric_perform_ranking);
+
+   /* Mark REVERSED rank of all the switches in the subnet. 
+      Start from switches that are connected to hca's, and 
+      scan all the switches in the subnet. */
+   p_next_hca = (ftree_hca_t *)cl_qmap_head(&p_ftree->hca_tbl);
+   while( p_next_hca != (ftree_hca_t *)cl_qmap_end( &p_ftree->hca_tbl ) )
+   {
+      p_hca = p_next_hca;
+      p_next_hca = (ftree_hca_t *)cl_qmap_next(&p_hca->map_item );
+      if (__osm_ftree_rank_switches_from_hca(p_ftree,p_hca) != 0)
+      {
+         res = -1;
+         osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+                 "__osm_ftree_fabric_perform_ranking: ERR AB14: "
+                 "Subnet ranking failed - subnet is not FatTree");
+         goto Exit;
+      }
+   }
+
+   /* calculate and set FatTree rank */
+   __osm_ftree_fabric_calculate_rank(p_ftree);
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_INFO,
+           "__osm_ftree_fabric_perform_ranking: "
+           "FatTree rank is %u\n", __osm_ftree_fabric_get_rank(p_ftree));
+   
+   /* fix ranking of the switches by reversing the ranking direction */
+   cl_qmap_apply_func(&p_ftree->sw_tbl, __osm_ftree_sw_reverse_rank, (void *)p_ftree);
+
+   if ( __osm_ftree_fabric_get_rank(p_ftree) > FAT_TREE_MAX_RANK ||
+        __osm_ftree_fabric_get_rank(p_ftree) < FAT_TREE_MIN_RANK )
+   {
+      osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR, 
+              "__osm_ftree_fabric_perform_ranking: ERR AB15: "
+              "Tree rank is %u (should be between %u and %u)\n",
+              __osm_ftree_fabric_get_rank(p_ftree),
+              FAT_TREE_MIN_RANK,
+              FAT_TREE_MAX_RANK);
+      res = -1;
+      goto Exit;
+   }
+
+  Exit:
+   OSM_LOG_EXIT(&p_ftree->p_osm->log);
+   return res;
+} /* __osm_ftree_fabric_perform_ranking() */
+
+/***************************************************
+ ***************************************************/
+
+static int
+__osm_ftree_fabric_populate_ports(
+   IN  ftree_fabric_t * p_ftree)
+{
+   ftree_hca_t * p_hca;
+   ftree_hca_t * p_next_hca;
+   ftree_sw_t * p_sw;
+   ftree_sw_t * p_next_sw;
+   int res = 0;
+
+   OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_fabric_populate_ports);
+
+   p_next_hca = (ftree_hca_t *)cl_qmap_head(&p_ftree->hca_tbl);
+   while( p_next_hca != (ftree_hca_t *)cl_qmap_end( &p_ftree->hca_tbl ) )
+   {
+      p_hca = p_next_hca;
+      p_next_hca = (ftree_hca_t *)cl_qmap_next(&p_hca->map_item );
+      if (__osm_ftree_fabric_construct_hca_ports(p_ftree,p_hca) != 0)
+      {
+         res = -1;
+         goto Exit;
+      }
+   }
+
+   p_next_sw = (ftree_sw_t *)cl_qmap_head(&p_ftree->sw_tbl);
+   while( p_next_sw != (ftree_sw_t *)cl_qmap_end( &p_ftree->sw_tbl ) )
+   {
+      p_sw = p_next_sw;
+      p_next_sw = (ftree_sw_t *)cl_qmap_next(&p_sw->map_item );
+      if (__osm_ftree_fabric_construct_sw_ports(p_ftree,p_sw) != 0)
+      {
+         res = -1;
+         goto Exit;
+      }
+   }
+ Exit:
+   OSM_LOG_EXIT(&p_ftree->p_osm->log);
+   return res;
+} /* __osm_ftree_fabric_populate_ports() */
+
+/***************************************************
+ ***************************************************/
+
+static int 
+__osm_ftree_construct_fabric(
+   IN  void * context)
+{
+   ftree_fabric_t * p_ftree = context;
+   int status = 0;
+
+   OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_construct_fabric);
+
+   if (p_ftree->p_osm->subn.opt.lmc > 0)
+   {
+      osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+              "LMC > 0 is not supported by fat-tree routing.\n"
+              "Falling back to default routing.\n");
+      status = -1;
+      goto Exit;
+   }
+
+   if ( cl_qmap_count(&p_ftree->p_osm->subn.sw_guid_tbl) < 2 )
+   {
+      osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+              "Fabric has %u switches - topology is not fat-tree.\n"
+              "Falling back to default routing.\n",
+              cl_qmap_count(&p_ftree->p_osm->subn.sw_guid_tbl));
+      status = -1;
+      goto Exit;
+   }
+
+   if ( (cl_qmap_count(&p_ftree->p_osm->subn.node_guid_tbl) - 
+         cl_qmap_count(&p_ftree->p_osm->subn.sw_guid_tbl)) < 2)
+   {
+      osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+              "Fabric has %u nodes (%u switches) - topology is not fat-tree.\n"
+              "Falling back to default routing.\n",
+              cl_qmap_count(&p_ftree->p_osm->subn.node_guid_tbl),
+              cl_qmap_count(&p_ftree->p_osm->subn.sw_guid_tbl));
+      status = -1;
+      goto Exit;
+   }
+
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,"__osm_ftree_construct_fabric: \n"
+           "                       |----------------------------------------|\n"
+           "                       |- Starting FatTree fabric construction -|\n"
+           "                       |----------------------------------------|\n\n");
+
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+           "__osm_ftree_construct_fabric: "
+           "Populating FatTree switch table\n");
+   /* ToDo: now that the pointer from node to switch exists,  
+      no need to fill the switch table in a separate loop */
+   if (__osm_ftree_fabric_populate_switches(p_ftree) != 0)
+   {
+      osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+              "Fabric topology is not fat-tree - "
+              "falling back to default routing\n");
+      status = -1;
+      goto Exit;
+   }
+
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+           "__osm_ftree_construct_fabric: "
+           "Populating FatTree HCA table\n");
+   if (__osm_ftree_fabric_populate_hcas(p_ftree) != 0)
+   {
+      osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+              "Fabric topology is not fat-tree - "
+              "falling back to default routing\n");
+      status = -1;
+      goto Exit;
+   }
+
+   if (cl_qmap_count(&p_ftree->hca_tbl) < 2)
+   {
+      osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+              "Fabric has %u HCAa - topology is not fat-tree.\n"
+              "Falling back to default routing.\n",
+              cl_qmap_count(&p_ftree->hca_tbl));
+      status = -1;
+      goto Exit;
+   }
+
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+           "__osm_ftree_construct_fabric: Ranking FatTree\n");
+
+   if (__osm_ftree_fabric_perform_ranking(p_ftree) != 0)
+   {
+      if (__osm_ftree_fabric_get_rank(p_ftree) > FAT_TREE_MAX_RANK)
+         osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+                 "Fabric rank is %u (>%u) - "
+                 "fat-tree routing falls back to default routing\n",
+                 __osm_ftree_fabric_get_rank(p_ftree), FAT_TREE_MAX_RANK);
+      else if (__osm_ftree_fabric_get_rank(p_ftree) < FAT_TREE_MIN_RANK)
+         osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+                 "Fabric rank is %u (<%u) - "
+                 "fat-tree routing falls back to default routing\n",
+                 __osm_ftree_fabric_get_rank(p_ftree), FAT_TREE_MIN_RANK);
+      status = -1;
+      goto Exit;
+   }
+
+   /* For each hca and switch, construct array of ports.
+      This is done after the whole FatTree data structure is ready, because
+      we want the ports to have pointers to ftree_{sw,hca}_t objects.*/
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+           "__osm_ftree_construct_fabric: "
+           "Populating HCA & switch ports\n");
+   if (__osm_ftree_fabric_populate_ports(p_ftree) != 0)
+   {
+      osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+              "Fabric topology is not a fat-tree - "
+              "routing falls back to default routing\n");
+      status = -1;
+      goto Exit;
+   }
+
+   /* Assign index to all the switches and hca's in the fabric.
+      This function also sorts all the port arrays of the switches
+      by the remote switch index, creates a leaf switch array
+      sorted by the switch index, and tracks the maximal number of
+      hcas per leaf switch. */
+   __osm_ftree_fabric_make_indexing(p_ftree);
+
+   /* print general info about fabric topology */
+   __osm_ftree_fabric_dump_general_info(p_ftree);
+
+   /* dump full tree topology */
+   if (osm_log_is_active(&p_ftree->p_osm->log, OSM_LOG_DEBUG))
+       __osm_ftree_fabric_dump(p_ftree);
+
+   if (! __osm_ftree_fabric_validate_topology(p_ftree))
+   {
+      osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+              "Fabric topology is not a fat-tree - "
+              "routing falls back to default routing\n");
+      status = -1;
+      goto Exit;
+   }
+
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+           "__osm_ftree_construct_fabric: "
+           "Max LID in switch LFTs (in host order): 0x%x\n",
+           p_ftree->lft_max_lid_ho);
+
+ Exit:
+   if (status != 0)
+   {
+      osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+              "__osm_ftree_construct_fabric: "
+             "Clearing FatTree Fabric data structures\n");
+     __osm_ftree_fabric_clear(p_ftree);
+   }
+   else
+      p_ftree->fabric_built = TRUE;
+
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+           "__osm_ftree_construct_fabric: \n"
+           "                       |--------------------------------------------------|\n"
+           "                       |- Done constructing FatTree fabric (status = %d) -|\n"
+           "                       |--------------------------------------------------|\n\n",
+           status);
+
+   OSM_LOG_EXIT(&p_ftree->p_osm->log);
+   return status;
+} /* __osm_ftree_construct_fabric() */
+
+/***************************************************
+ ***************************************************/
+
+static int 
+__osm_ftree_do_routing(
+   IN  void * context)
+{
+   ftree_fabric_t * p_ftree = context;
+
+   OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_do_routing);
+
+   if (!p_ftree->fabric_built)
+      goto Exit;
+
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,"__osm_ftree_do_routing: "
+           "Starting FatTree routing\n");
+
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,"__osm_ftree_do_routing: "
+           "Filling switch forwarding tables for routes to HCAs\n");
+   __osm_ftree_fabric_route_to_hcas(p_ftree);
+
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,"__osm_ftree_do_routing: "
+           "Filling switch forwarding tables for switch-to-switch pathes\n");
+   __osm_ftree_fabric_route_to_switches(p_ftree);
+
+   /* for each switch, set its fwd table */
+   cl_qmap_apply_func(&p_ftree->sw_tbl, __osm_ftree_set_sw_fwd_table, (void *)p_ftree);
+
+   /* write out hca ordering file */
+   __osm_ftree_fabric_dump_hca_ordering(p_ftree);
+
+   osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,"__osm_ftree_do_routing: "
+           "FatTree routing is done\n");
+
+ Exit:
+   OSM_LOG_EXIT(&p_ftree->p_osm->log);
+   return 0;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void 
+__osm_ftree_delete(
+   IN  void * context)
+{
+   if (!context)
+      return;
+   __osm_ftree_fabric_destroy((ftree_fabric_t *)context);
+}
+
+/***************************************************
+ ***************************************************/
+
+int osm_ucast_ftree_setup(osm_opensm_t * p_osm)
+{
+   ftree_fabric_t * p_ftree = __osm_ftree_fabric_create();
+   if (!p_ftree)
+      return -1;
+
+   p_ftree->p_osm = p_osm;
+
+   p_osm->routing_engine.context = (void *)p_ftree;
+   p_osm->routing_engine.build_lid_matrices = __osm_ftree_construct_fabric;
+   p_osm->routing_engine.ucast_build_fwd_tables = __osm_ftree_do_routing;
+   p_osm->routing_engine.delete = __osm_ftree_delete;
+   return 0;
+}
+
+/***************************************************
+ ***************************************************/
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_mgr.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_mgr.c
new file mode 100644 (file)
index 0000000..a1433a9
--- /dev/null
@@ -0,0 +1,1277 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_ucast_mgr.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_ucast_mgr_t.
+ * This file implements the Unicast Manager object.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.14 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_ucast_mgr.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_opensm.h>
+
+#define LINE_LENGTH 256
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ * This flag is used for stopping the relaxation algorithm if no
+ * change detected during the fabric scan
+ */
+static boolean_t __some_hop_count_set;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ucast_mgr_construct(
+  IN osm_ucast_mgr_t* const p_mgr )
+{
+  memset( p_mgr, 0, sizeof(*p_mgr) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ucast_mgr_destroy(
+  IN osm_ucast_mgr_t* const p_mgr )
+{
+  CL_ASSERT( p_mgr );
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_ucast_mgr_destroy );
+
+  if (p_mgr->lft_buf)
+    free(p_mgr->lft_buf);
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_ucast_mgr_init(
+  IN osm_ucast_mgr_t* const p_mgr,
+  IN osm_req_t* const p_req,
+  IN osm_subn_t* const p_subn,
+  IN osm_log_t* const p_log,
+  IN cl_plock_t* const p_lock )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_ucast_mgr_init );
+
+  CL_ASSERT( p_req );
+  CL_ASSERT( p_subn );
+  CL_ASSERT( p_lock );
+
+  osm_ucast_mgr_construct( p_mgr );
+
+  p_mgr->p_log = p_log;
+  p_mgr->p_subn = p_subn;
+  p_mgr->p_lock = p_lock;
+  p_mgr->p_req = p_req;
+
+  p_mgr->lft_buf = malloc(IB_LID_UCAST_END_HO + 1);
+  if (!p_mgr->lft_buf)
+    return IB_INSUFFICIENT_MEMORY;
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+struct ucast_mgr_dump_context {
+       osm_ucast_mgr_t *p_mgr;
+       FILE *file;
+};
+
+static void
+ucast_mgr_dump(osm_ucast_mgr_t *p_mgr, FILE *file,
+              void (*func)(cl_map_item_t *, void *))
+{
+       struct ucast_mgr_dump_context dump_context;
+
+       dump_context.p_mgr = p_mgr;
+       dump_context.file = file;
+
+       cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl, func, &dump_context);
+}
+
+void
+ucast_mgr_dump_to_file(osm_ucast_mgr_t *p_mgr, const char *file_name,
+                      void (*func)(cl_map_item_t *, void *))
+{
+       char path[1024];
+       FILE *file;
+
+       snprintf(path, sizeof(path), "%s/%s",
+                p_mgr->p_subn->opt.dump_files_dir, file_name);
+  
+       file = fopen(path, "w");
+       if (!file) {
+               osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+                        "ucast_mgr_dump_to_file: ERR 3A12: "
+                        "Failed to open fdb file (%s)\n", path );
+               return;
+       }
+
+       ucast_mgr_dump(p_mgr, file, func);
+
+       fclose(file);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_dump_path_distribution(
+  IN cl_map_item_t *p_map_item,
+  IN void *cxt)
+{
+  osm_node_t *p_node;
+  osm_node_t *p_remote_node;
+  uint8_t i;
+  uint8_t num_ports;
+  uint32_t num_paths;
+  ib_net64_t remote_guid_ho;
+  osm_switch_t* p_sw = (osm_switch_t *)p_map_item;
+  osm_ucast_mgr_t* p_mgr = ((struct ucast_mgr_dump_context *)cxt)->p_mgr;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_dump_path_distribution );
+
+  p_node = osm_switch_get_node_ptr( p_sw );
+  num_ports = osm_switch_get_num_ports( p_sw );
+
+  osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG,
+                  "__osm_ucast_mgr_dump_path_distribution: "
+                  "Switch 0x%" PRIx64 "\n"
+                  "Port : Path Count Through Port",
+                  cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+
+  for( i = 0; i < num_ports; i++ )
+  {
+    num_paths = osm_switch_path_count_get( p_sw , i );
+    osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG,"\n %03u : %u", i, num_paths );
+    if( i == 0 )
+    {
+      osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG, " (switch management port)" );
+      continue;
+    }
+
+    p_remote_node = osm_node_get_remote_node( p_node, i, NULL );
+    if( p_remote_node == NULL )
+      continue;
+
+    remote_guid_ho = cl_ntoh64( osm_node_get_node_guid( p_remote_node ) );
+
+    switch(  osm_node_get_remote_type( p_node, i ) )
+    {
+    case IB_NODE_TYPE_SWITCH:
+      osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG, " (link to switch" );
+      break;
+    case IB_NODE_TYPE_ROUTER:
+      osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG, " (link to router" );
+      break;
+    case IB_NODE_TYPE_CA:
+      osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG, " (link to CA" );
+      break;
+    default:
+      osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG, " (link to unknown node type" );
+      break;
+    }
+
+    osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG, " 0x%" PRIx64 ")",
+                    remote_guid_ho );
+  }
+
+  osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG, "\n" );
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_dump_ucast_routes(
+  IN cl_map_item_t *p_map_item,
+  IN void *cxt )
+{
+  const osm_node_t*        p_node;
+  uint8_t                  port_num;
+  uint8_t                  num_hops;
+  uint8_t                  best_hops;
+  uint8_t                  best_port;
+  uint16_t                 max_lid_ho;
+  uint16_t                 lid_ho;
+  osm_switch_t* p_sw = (osm_switch_t *)p_map_item;
+  osm_ucast_mgr_t* p_mgr = ((struct ucast_mgr_dump_context *)cxt)->p_mgr;
+  FILE *file = ((struct ucast_mgr_dump_context *)cxt)->file;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_dump_ucast_routes );
+
+  p_node = osm_switch_get_node_ptr( p_sw );
+
+  max_lid_ho = osm_switch_get_max_lid_ho( p_sw );
+
+  fprintf( file, "__osm_ucast_mgr_dump_ucast_routes: "
+           "Switch 0x%016" PRIx64 "\n"
+           "LID    : Port : Hops : Optimal\n",
+           cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+  for( lid_ho = 1; lid_ho <= max_lid_ho; lid_ho++ )
+  {
+    fprintf(file, "0x%04X : ", lid_ho);
+
+    port_num = osm_switch_get_port_by_lid( p_sw, lid_ho );
+    if( port_num == OSM_NO_PATH )
+    {
+      /*
+        This may occur if there are 'holes' in the existing
+        LID assignments.  Running SM with --reassign_lids
+        will reassign and compress the LID range.  The
+        subnet should work fine either way.
+      */
+      fprintf( file, "UNREACHABLE\n" );
+      continue;
+    }
+    /*
+      Switches can lie about which port routes a given
+      lid due to a recent reconfiguration of the subnet.
+      Therefore, ensure that the hop count is better than
+      OSM_NO_PATH.
+    */
+    num_hops = osm_switch_get_hop_count( p_sw, lid_ho, port_num );
+    if( num_hops == OSM_NO_PATH )
+    {
+      fprintf( file, "UNREACHABLE\n" );
+      continue;
+    }
+
+    best_hops = osm_switch_get_least_hops( p_sw, lid_ho );
+    fprintf( file, "%03u  : %02u   : ", port_num, num_hops );
+
+    if( best_hops == num_hops )
+      fprintf( file, "yes" );
+    else
+    {
+      best_port = osm_switch_recommend_path(
+        p_sw, lid_ho, TRUE,
+        NULL, NULL, NULL, NULL ); /* No LMC Optimization */
+      fprintf( file, "No %u hop path possible via port %u!",
+               best_hops, best_port );
+    }
+
+    fprintf( file, "\n" );
+  }
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+ucast_mgr_dump_lid_matrix(cl_map_item_t *p_map_item, void *cxt)
+{
+       osm_switch_t* p_sw = (osm_switch_t *)p_map_item;
+       osm_ucast_mgr_t* p_mgr = ((struct ucast_mgr_dump_context *)cxt)->p_mgr;
+       FILE *file = ((struct ucast_mgr_dump_context *)cxt)->file;
+       osm_node_t *p_node = osm_switch_get_node_ptr(p_sw);
+       unsigned max_lid = osm_switch_get_max_lid_ho(p_sw);
+       unsigned max_port = osm_switch_get_num_ports(p_sw);
+       uint16_t lid;
+       uint8_t port;
+
+       fprintf(file, "Switch: guid 0x%016" PRIx64 "\n",
+               cl_ntoh64(osm_node_get_node_guid(p_node)));
+       for (lid = 1; lid <= max_lid; lid++) {
+               osm_port_t *p_port;
+
+               fprintf(file, "0x%04x:", lid);
+               for (port = 0 ; port < max_port ; port++)
+                       fprintf(file, " %02x",
+                               osm_switch_get_hop_count(p_sw, lid, port));
+               p_port = cl_ptr_vector_get(&p_mgr->p_subn->port_lid_tbl, lid);
+               if (p_port)
+                       fprintf(file, " # portguid 0x%" PRIx64,
+                               cl_ntoh64(osm_port_get_guid(p_port)));
+               fprintf(file, "\n");
+       }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+ucast_mgr_dump_lfts(cl_map_item_t *p_map_item, void *cxt)
+{
+       osm_switch_t* p_sw = (osm_switch_t *)p_map_item;
+       osm_ucast_mgr_t* p_mgr = ((struct ucast_mgr_dump_context *)cxt)->p_mgr;
+       FILE *file = ((struct ucast_mgr_dump_context *)cxt)->file;
+       osm_node_t *p_node = osm_switch_get_node_ptr(p_sw);
+       unsigned max_lid = osm_switch_get_max_lid_ho(p_sw);
+       unsigned max_port = osm_switch_get_num_ports(p_sw);
+       uint16_t lid;
+       uint8_t port;
+       char desc[IB_NODE_DESCRIPTION_SIZE + 1];
+
+       memcpy(desc, p_node->node_desc.description, IB_NODE_DESCRIPTION_SIZE);
+       desc[IB_NODE_DESCRIPTION_SIZE] = '\0';
+       fprintf(file, "Unicast lids [0x0-0x%x] of switch Lid %u guid 0x%016"
+               PRIx64 " (\'%s\'):\n",
+               max_lid, osm_node_get_base_lid(p_node, 0),
+               cl_ntoh64(osm_node_get_node_guid(p_node)), desc);
+       for (lid = 0; lid <= max_lid; lid++) {
+               osm_port_t *p_port;
+               port = osm_switch_get_port_by_lid(p_sw, lid);
+
+               if (port >= max_port)
+                       continue;
+
+               fprintf(file, "0x%04x %03u # ", lid, port);
+
+               p_port = cl_ptr_vector_get(&p_mgr->p_subn->port_lid_tbl, lid);
+               if (p_port) {
+                       p_node = osm_port_get_parent_node(p_port);
+                       memcpy(desc, p_node->node_desc.description,
+                              IB_NODE_DESCRIPTION_SIZE);
+                       desc[IB_NODE_DESCRIPTION_SIZE] = '\0';
+                       fprintf(file, "%s portguid 0x016%" PRIx64 ": \'%s\'",
+                               ib_get_node_type_str(osm_node_get_type(p_node)),
+                               cl_ntoh64(osm_port_get_guid(p_port)), desc);
+               }
+               else
+                       fprintf(file, "unknown node and type");
+               fprintf(file, "\n");
+       }
+       fprintf(file, "%u lids dumped\n", max_lid);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void __osm_ucast_mgr_dump_tables(osm_ucast_mgr_t *p_mgr)
+{
+  ucast_mgr_dump_to_file(p_mgr, "opensm-lid-matrix.dump",
+                         ucast_mgr_dump_lid_matrix);
+  ucast_mgr_dump_to_file(p_mgr, "opensm-lfts.dump", ucast_mgr_dump_lfts);
+  if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+    ucast_mgr_dump(p_mgr, NULL, __osm_ucast_mgr_dump_path_distribution);
+  ucast_mgr_dump_to_file(p_mgr, "osm.fdbs", __osm_ucast_mgr_dump_ucast_routes);
+}
+
+/**********************************************************************
+ Starting a rebuild, so notify the switch so it can clear tables, etc...
+**********************************************************************/
+static void
+__osm_ucast_mgr_clean_switch(
+  IN cl_map_item_t* const  p_map_item,
+  IN void* context )
+{
+  osm_switch_prepare_path_rebuild((osm_switch_t *)p_map_item);
+}
+
+/**********************************************************************
+ Add each switch's own LID(s) to its LID matrix.
+**********************************************************************/
+static void
+__osm_ucast_mgr_process_hop_0(
+  IN cl_map_item_t* const  p_map_item,
+  IN void* context )
+{
+  osm_switch_t* const p_sw = (osm_switch_t*)p_map_item;
+  osm_ucast_mgr_t* const p_mgr = (osm_ucast_mgr_t*)context;
+  osm_node_t *p_node;
+  uint16_t lid_ho, base_lid_ho, max_lid_ho;
+  cl_status_t status;
+  uint8_t lmc;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_hop_0 );
+
+  p_node = p_sw->p_node;
+
+  CL_ASSERT( p_node );
+  CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
+
+  base_lid_ho = cl_ntoh16( osm_node_get_base_lid( p_node, 0 ) );
+  if (osm_switch_sp0_is_lmc_capable( p_sw, p_mgr->p_subn ))
+    lmc = osm_node_get_lmc( p_node, 0 );
+  else
+    lmc = 0;
+  max_lid_ho = (uint16_t)( base_lid_ho + (1 << lmc) - 1 );
+
+  for (lid_ho = base_lid_ho; lid_ho <= max_lid_ho; lid_ho++)
+  {
+    if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "__osm_ucast_mgr_process_hop_0: "
+               "Processing switch GUID 0x%" PRIx64 ", LID 0x%X\n",
+               cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+               lid_ho );
+    }
+
+    status = osm_switch_set_hops( p_sw, lid_ho, 0, 0 );
+    if( status != CL_SUCCESS )
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "__osm_ucast_mgr_process_hop_0: ERR 3A02: "
+               "Setting hop count failed (%s) for "
+               "switch GUID 0x%" PRIx64 ", LID 0x%X\n",
+               CL_STATUS_MSG( status ),
+               cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+               lid_ho );
+    }
+  }
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_process_neighbor(
+  IN osm_ucast_mgr_t* const p_mgr,
+  IN osm_switch_t* const p_sw,
+  IN osm_switch_t* const p_remote_sw,
+  IN const uint8_t port_num,
+  IN const uint8_t remote_port_num )
+{
+  uint16_t lid_ho;
+  uint16_t max_lid_ho;
+  osm_node_t* p_node;
+  const osm_node_t* p_remote_node;
+  uint8_t hops;
+  cl_status_t status;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_neighbor );
+
+  CL_ASSERT( p_sw );
+  CL_ASSERT( p_remote_sw );
+  CL_ASSERT( port_num );
+  CL_ASSERT( remote_port_num );
+
+  p_node = osm_switch_get_node_ptr( p_sw );
+  p_remote_node = osm_switch_get_node_ptr( p_remote_sw );
+
+  CL_ASSERT( p_node );
+  CL_ASSERT( p_remote_node );
+
+  CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
+  CL_ASSERT( osm_node_get_type( p_remote_node ) == IB_NODE_TYPE_SWITCH );
+
+  if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+             "__osm_ucast_mgr_process_neighbor: "
+             "Node 0x%" PRIx64 ", remote node 0x%" PRIx64 "\n"
+             "\t\t\t\tport 0x%X, remote port 0x%X\n",
+             cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+             cl_ntoh64( osm_node_get_node_guid( p_remote_node ) ),
+             port_num, remote_port_num );
+  }
+
+  /*
+    Iterate through all the LIDs in the neighbor switch.
+  */
+  max_lid_ho = osm_switch_get_max_lid_ho( p_remote_sw );
+
+  /*
+    Make sure the local lid matrix has enough room to hold
+    all the LID info coming from the remote LID matrix.
+  */
+  osm_switch_set_min_lid_size( p_sw, max_lid_ho );
+
+  hops = OSM_NO_PATH;
+  for( lid_ho = 1; lid_ho <= max_lid_ho; lid_ho++ )
+  {
+    /*
+      Find the lowest hop count value to this LID.
+    */
+      hops = osm_switch_get_least_hops( p_remote_sw, lid_ho );
+
+      if( hops != OSM_NO_PATH )
+      {
+        /*
+          Increment hop count of the neighbor by 1, since it
+          takes 1 hop to get to the neighbor.
+        */
+        hops++;
+
+        CL_ASSERT( hops <= osm_switch_get_hop_count( p_sw, lid_ho,
+                                                     port_num ) );
+        if( osm_switch_get_hop_count( p_sw, lid_ho,
+                                      port_num ) > hops )
+        {
+          if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+          {
+            osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+                     "__osm_ucast_mgr_process_neighbor: "
+                     "New best path is %u hops for LID 0x%X\n",
+                     hops, lid_ho );
+          }
+
+          /* mark the fact we have got to change anything */
+          __some_hop_count_set = TRUE;
+
+          status = osm_switch_set_hops( p_sw, lid_ho,
+                                        port_num, hops );
+          if( status != CL_SUCCESS )
+          {
+            osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+                     "__osm_ucast_mgr_process_neighbor: ERR 3A03: "
+                     "Setting hop count failed (%s)\n",
+                     CL_STATUS_MSG( status ) );
+          }
+        }
+      }
+  }
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_process_leaf(
+  IN osm_ucast_mgr_t* const p_mgr,
+  IN osm_switch_t* const p_sw,
+  IN osm_node_t* const p_node,
+  IN const uint8_t port_num,
+  IN osm_node_t* const p_remote_node,
+  IN const uint8_t remote_port_num )
+{
+  uint16_t i;
+  uint16_t base_lid_ho;
+  uint16_t max_lid_ho;
+  uint8_t lmc;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_leaf );
+
+  CL_ASSERT( p_node );
+  CL_ASSERT( p_remote_node );
+  CL_ASSERT( port_num );
+  CL_ASSERT( remote_port_num );
+
+  switch( osm_node_get_type( p_remote_node ) )
+  {
+  case IB_NODE_TYPE_CA:
+  case IB_NODE_TYPE_ROUTER:
+    base_lid_ho = cl_ntoh16( osm_node_get_base_lid(
+                               p_remote_node, remote_port_num ) );
+    lmc = osm_node_get_lmc( p_remote_node, remote_port_num );
+    break;
+#if 0
+  case IB_NODE_TYPE_SWITCH:
+    base_lid_ho = cl_ntoh16( osm_node_get_base_lid(
+                               p_remote_node, 0 ) );
+    lmc = 0;
+    break;
+#endif
+
+  default:
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "__osm_ucast_mgr_process_leaf: ERR 3A01: "
+             "Bad node type %u, GUID 0x%" PRIx64 "\n",
+             osm_node_get_type( p_remote_node ),
+             cl_ntoh64( osm_node_get_node_guid( p_node ) ));
+    goto Exit;
+  }
+
+  max_lid_ho = (uint16_t)(base_lid_ho + (1 << lmc) - 1 );
+
+  if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+             "__osm_ucast_mgr_process_leaf: "
+             "Discovered LIDs [0x%X,0x%X]\n"
+             "\t\t\t\tport number 0x%X, node 0x%" PRIx64 "\n",
+             base_lid_ho, max_lid_ho,
+             port_num, cl_ntoh64( osm_node_get_node_guid( p_node ) ));
+  }
+
+  for( i = base_lid_ho; i <= max_lid_ho; i++ )
+    osm_switch_set_hops( p_sw, i, port_num, 1 );
+
+ Exit:
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_process_leaves(
+  IN cl_map_item_t* const  p_map_item,
+  IN void* context )
+{
+  osm_switch_t* const p_sw = (osm_switch_t*)p_map_item;
+  osm_ucast_mgr_t* const p_mgr = (osm_ucast_mgr_t*)context;
+  osm_node_t *p_node;
+  osm_node_t *p_remote_node;
+  uint32_t port_num;
+  uint8_t remote_port_num;
+  uint32_t num_ports;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_leaves );
+
+  p_node = p_sw->p_node;
+
+  CL_ASSERT( p_node );
+  CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
+
+  if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+             "__osm_ucast_mgr_process_leaves: "
+             "Processing switch 0x%" PRIx64 "\n",
+             cl_ntoh64( osm_node_get_node_guid( p_node ) ));
+  }
+
+  /*
+    Add the LIDs of all leaves of this switch to the LID matrix.
+    Don't bother processing loopback paths from one port of
+    this switch to the another port.
+    Don't process neighbor switches yet.
+    Start with port 1 to skip the switch's management port.
+  */
+  num_ports = osm_node_get_num_physp( p_node );
+
+  for( port_num = 1; port_num < num_ports; port_num++ )
+  {
+    p_remote_node = osm_node_get_remote_node( p_node,
+                                              (uint8_t)port_num, &remote_port_num );
+
+    if( p_remote_node && (p_remote_node != p_node )
+        && (osm_node_get_type( p_remote_node ) != IB_NODE_TYPE_SWITCH ) )
+    {
+      __osm_ucast_mgr_process_leaf(
+        p_mgr,
+        p_sw,
+        p_node,
+        (uint8_t)port_num,
+        p_remote_node,
+        remote_port_num );
+    }
+  }
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_process_port(
+  IN osm_ucast_mgr_t* const p_mgr,
+  IN osm_switch_t* const p_sw,
+  IN const osm_port_t* const p_port )
+{
+  uint16_t min_lid_ho;
+  uint16_t max_lid_ho;
+  uint16_t lid_ho;
+  uint8_t port;
+  boolean_t is_ignored_by_port_prof;
+  ib_net64_t node_guid;
+  /*
+    The following are temporary structures that will aid
+    in providing better routing in LMC > 0 situations
+  */
+  uint16_t lids_per_port = 1 << p_mgr->p_subn->opt.lmc;
+  uint64_t *remote_sys_guids = NULL;
+  uint64_t *remote_node_guids = NULL;
+  uint16_t num_used_sys = 0;
+  uint16_t num_used_nodes = 0;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_port );
+
+  remote_sys_guids = malloc( sizeof(uint64_t) * lids_per_port );
+  if( remote_sys_guids == NULL )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "__osm_ucast_mgr_process_port: ERR 3A09: "
+             "Cannot allocate array. Insufficient memory\n");
+    goto Exit;
+  }
+
+  memset( remote_sys_guids, 0, sizeof(uint64_t) * lids_per_port );
+
+  remote_node_guids = malloc( sizeof(uint64_t) * lids_per_port );
+  if( remote_node_guids == NULL )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "__osm_ucast_mgr_process_port: ERR 3A0A: "
+             "Cannot allocate array. Insufficient memory\n");
+    goto Exit;
+  }
+
+  memset( remote_node_guids, 0, sizeof(uint64_t) * lids_per_port );
+
+  osm_port_get_lid_range_ho( p_port, &min_lid_ho, &max_lid_ho );
+
+  /* If the lids are zero - then there was some problem with the initialization.
+     Don't handle this port. */
+  if ( min_lid_ho == 0 || max_lid_ho == 0 )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "__osm_ucast_mgr_process_port: ERR 3A04: "
+             "Port 0x%" PRIx64 " has LID 0. An initialization "
+             "error occurred. Ignoring port\n",
+             cl_ntoh64( osm_port_get_guid( p_port ) ) );
+    goto Exit;
+  }
+
+  if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+             "__osm_ucast_mgr_process_port: "
+             "Processing port 0x%" PRIx64
+             ", LIDs [0x%X,0x%X]\n",
+             cl_ntoh64( osm_port_get_guid( p_port ) ),
+             min_lid_ho, max_lid_ho );
+  }
+
+  /*
+    TO DO - This should be runtime error, not a CL_ASSERT()
+  */
+  CL_ASSERT( max_lid_ho < osm_switch_get_fwd_tbl_size( p_sw ) );
+
+  node_guid = osm_node_get_node_guid(osm_switch_get_node_ptr( p_sw ) );
+
+  /*
+    The lid matrix contains the number of hops to each
+    lid from each port.  From this information we determine
+    how best to distribute the LID range across the ports
+    that can reach those LIDs.
+  */
+  for( lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++ )
+  {
+    /* Use the enhanced algorithm only for LMC > 0 */
+    if (lids_per_port > 1)
+      port = osm_switch_recommend_path( p_sw, lid_ho,
+                                        p_mgr->p_subn->ignore_existing_lfts,
+                                        remote_sys_guids, &num_used_sys,
+                                        remote_node_guids, &num_used_nodes );
+    else
+      port = osm_switch_recommend_path( p_sw, lid_ho,
+                                        p_mgr->p_subn->ignore_existing_lfts,
+                                        NULL, NULL, NULL, NULL );
+
+    /*
+      There might be no path to the target
+    */
+    if (port == OSM_NO_PATH)
+    {
+      /* do not try to overwrite the ppro of non existing port ... */ 
+      is_ignored_by_port_prof = TRUE;
+
+      /* Up/Down routing can cause unreachable routes between some 
+         switches so we do not report that as an error in that case */
+      if (!p_mgr->p_subn->p_osm->routing_engine.build_lid_matrices)
+      {
+        osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+                 "__osm_ucast_mgr_process_port: ERR 3A08: "
+                 "No path to get to LID 0x%X from switch 0x%" PRIx64 "\n",
+                 lid_ho, cl_ntoh64( node_guid ) );
+        /* trigger a new sweep - try again ... */
+        p_mgr->p_subn->subnet_initialization_error = TRUE;
+      }
+      else 
+        osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+                 "__osm_ucast_mgr_process_port: "
+                 "No path to get to LID 0x%X from switch 0x%" PRIx64 "\n",
+                 lid_ho, cl_ntoh64( node_guid ) );
+    }
+    else
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+              "__osm_ucast_mgr_process_port: "
+              "Routing LID 0x%X to port 0x%X"
+              "\n\t\t\t\tFor switch 0x%" PRIx64 "\n",
+              lid_ho, port, cl_ntoh64( node_guid ) );
+
+      /*
+       we would like to optionally ignore this port in equalization
+       like in the case of the Mellanox Anafa Internal PCI TCA port
+      */
+      is_ignored_by_port_prof =
+       osm_port_prof_is_ignored_port(p_mgr->p_subn, cl_ntoh64(node_guid), port);
+
+      /*
+       We also would ignore this route if the target lid is of a switch
+       and the port_profile_switch_node is not TRUE
+      */
+      if (! p_mgr->p_subn->opt.port_profile_switch_nodes)
+      {
+       is_ignored_by_port_prof |=
+         (osm_node_get_type(osm_port_get_parent_node(p_port)) ==
+          IB_NODE_TYPE_SWITCH);
+      }
+    }
+
+    /*
+      We have selected the port for this LID.
+      Write it to the forwarding tables.
+    */
+    p_mgr->lft_buf[lid_ho] = port;
+    if (!is_ignored_by_port_prof)
+      osm_switch_count_path(p_sw, port);
+  }
+
+ Exit:
+  if (remote_sys_guids)
+    free(remote_sys_guids);
+  if (remote_node_guids)
+    free(remote_node_guids);
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ucast_mgr_set_fwd_table(
+  IN osm_ucast_mgr_t* const p_mgr,
+  IN osm_switch_t* const p_sw )
+{
+  osm_node_t *p_node;
+  osm_dr_path_t *p_path;
+  osm_madw_context_t context;
+  ib_api_status_t status;
+  ib_switch_info_t si;
+  uint32_t block_id_ho = 0;
+  uint8_t block[IB_SMP_DATA_SIZE];
+  boolean_t set_swinfo_require = FALSE;
+  uint16_t lin_top;
+  uint8_t life_state;
+
+  CL_ASSERT( p_mgr );
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_ucast_mgr_set_fwd_table );
+
+  CL_ASSERT( p_sw );
+
+  p_node = osm_switch_get_node_ptr( p_sw );
+
+  CL_ASSERT( p_node );
+
+  p_path = osm_node_get_any_dr_path_ptr( p_node );
+
+  CL_ASSERT( p_path );
+
+  /*
+    Set the top of the unicast forwarding table.
+  */
+  si = *osm_switch_get_si_ptr( p_sw );
+  lin_top = cl_hton16( osm_switch_get_max_lid_ho( p_sw ) );
+  if (lin_top != si.lin_top)
+  {
+    set_swinfo_require = TRUE;
+    si.lin_top  = lin_top;
+  }
+
+  /* check to see if the change state bit is on. If it is - then we
+     need to clear it. */
+  if ( ib_switch_info_get_state_change( &si ) )
+    life_state = ( (p_mgr->p_subn->opt.packet_life_time <<3 )
+                   | ( si.life_state & IB_SWITCH_PSC ) )  & 0xfc;
+  else
+    life_state = (p_mgr->p_subn->opt.packet_life_time <<3 ) & 0xf8;
+
+  if ( (life_state != si.life_state) || ib_switch_info_get_state_change( &si ) )
+  {
+    set_swinfo_require = TRUE;
+    si.life_state = life_state;
+  }
+  if ( set_swinfo_require )
+  {
+    if ( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "osm_ucast_mgr_set_fwd_table: "
+               "Setting switch FT top to LID 0x%X\n",
+               osm_switch_get_max_lid_ho( p_sw ) );
+    }
+    
+    context.si_context.light_sweep = FALSE;
+    context.si_context.node_guid = osm_node_get_node_guid( p_node );
+    context.si_context.set_method = TRUE;
+    
+    status = osm_req_set( p_mgr->p_req,
+                          p_path,
+                          (uint8_t*)&si,
+                          sizeof(si),
+                          IB_MAD_ATTR_SWITCH_INFO,
+                          0,
+                          CL_DISP_MSGID_NONE,
+                          &context );
+    
+    if( status != IB_SUCCESS )
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "osm_ucast_mgr_set_fwd_table: ERR 3A06: "
+               "Sending SwitchInfo attribute failed (%s)\n",
+               ib_get_err_str( status ) );
+    }
+    else
+      p_mgr->any_change = TRUE;
+  }
+
+  /*
+    Send linear forwarding table blocks to the switch
+    as long as the switch indicates it has blocks needing
+    configuration.
+  */
+
+  context.lft_context.node_guid = osm_node_get_node_guid( p_node );
+  context.lft_context.set_method = TRUE;
+
+  for (block_id_ho = 0;
+       osm_switch_get_fwd_tbl_block( p_sw, block_id_ho, block ) ;
+       block_id_ho++ )
+  {
+    if (!memcmp(block, p_mgr->lft_buf + block_id_ho * 64, 64))
+      continue;
+
+    if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+               "osm_ucast_mgr_set_fwd_table: "
+               "Writing FT block %u\n", block_id_ho );
+    }
+
+    status = osm_req_set( p_mgr->p_req,
+                          p_path,
+                          p_mgr->lft_buf + block_id_ho * 64,
+                          sizeof(block),
+                          IB_MAD_ATTR_LIN_FWD_TBL,
+                          cl_hton32( block_id_ho ),
+                          CL_DISP_MSGID_NONE,
+                          &context );
+
+    if( status != IB_SUCCESS )
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "osm_ucast_mgr_set_fwd_table: ERR 3A05: "
+               "Sending linear fwd. tbl. block failed (%s)\n",
+               ib_get_err_str( status ) );
+    }
+    else
+    {
+      p_mgr->any_change = TRUE;
+      /*
+        HACK: for now we will assume we succeeded to send
+        and set the local DB based on it. This should allow
+        us to immediatly dump out our routing.
+      */
+      osm_switch_set_ft_block(
+        p_sw, p_mgr->lft_buf + block_id_ho * 64, block_id_ho );
+    }
+  }
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_process_tbl(
+  IN cl_map_item_t* const  p_map_item,
+  IN void* context )
+{
+  osm_switch_t* const p_sw = (osm_switch_t*)p_map_item;
+  osm_ucast_mgr_t* const p_mgr = (osm_ucast_mgr_t*)context;
+  osm_node_t *p_node;
+  const osm_port_t *p_port;
+  const cl_qmap_t* p_port_tbl;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_tbl );
+
+  p_node = p_sw->p_node;
+
+  CL_ASSERT( p_node );
+  CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
+
+  if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+             "__osm_ucast_mgr_process_tbl: "
+             "Processing switch 0x%" PRIx64 "\n",
+             cl_ntoh64( osm_node_get_node_guid( p_node ) ));
+  }
+
+  /* Initialize LIDs in buffer to invalid port number. */
+  memset(p_mgr->lft_buf, 0xff, IB_LID_UCAST_END_HO + 1);
+
+  p_port_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+  /*
+    Iterate through every port setting LID routes for each
+    port based on base LID and LMC value.
+  */
+
+  for( p_port = (osm_port_t*)cl_qmap_head( p_port_tbl );
+       p_port != (osm_port_t*)cl_qmap_end( p_port_tbl );
+       p_port = (osm_port_t*)cl_qmap_next( &p_port->map_item ) )
+  {
+    __osm_ucast_mgr_process_port( p_mgr, p_sw, p_port );
+  }
+
+  osm_ucast_mgr_set_fwd_table( p_mgr, p_sw );
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_process_neighbors(
+  IN cl_map_item_t* const  p_map_item,
+  IN void* context )
+{
+  osm_switch_t* const p_sw = (osm_switch_t*)p_map_item;
+  osm_ucast_mgr_t* const p_mgr = (osm_ucast_mgr_t*)context;
+  osm_node_t *p_node;
+  osm_node_t *p_remote_node;
+  uint32_t port_num;
+  uint8_t remote_port_num;
+  uint32_t num_ports;
+  osm_physp_t* p_physp;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_neighbors );
+
+  p_node = p_sw->p_node;
+
+  CL_ASSERT( p_node );
+  CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
+
+  if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+             "__osm_ucast_mgr_process_neighbors: "
+             "Processing switch with GUID 0x%" PRIx64 "\n",
+             cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+  }
+
+  num_ports = osm_node_get_num_physp( p_node );
+
+  /*
+    Start with port 1 to skip the switch's management port.
+  */
+  for( port_num = 1; port_num < num_ports; port_num++ )
+  {
+    p_remote_node = osm_node_get_remote_node( p_node,
+                                              (uint8_t)port_num, &remote_port_num );
+
+    if( p_remote_node && (p_remote_node != p_node )
+        && p_remote_node->sw )
+    {
+      /* make sure the link is healthy. If it is not - don't 
+         propagate through it. */
+      p_physp = osm_node_get_physp_ptr( p_node, port_num );
+      if (!osm_link_is_healthy( p_physp ) )
+        continue;
+
+      __osm_ucast_mgr_process_neighbor(p_mgr, p_sw, p_remote_node->sw,
+                                       (uint8_t)port_num, remote_port_num );
+
+    }
+  }
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ucast_mgr_build_lid_matrices(
+  IN osm_ucast_mgr_t* const p_mgr )
+{
+  uint32_t i;
+  uint32_t iteration_max;
+  cl_qmap_t *p_sw_guid_tbl;
+
+  p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+  osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+           "osm_ucast_mgr_build_lid_matrices: "
+           "Starting switches Min Hop Table Assignment\n" );
+  
+  /*
+    Set the switch matrices for each switch's own port 0 LID(s)
+    then set the lid matrices for the each switch's leaf nodes.
+  */
+  cl_qmap_apply_func( p_sw_guid_tbl,
+                      __osm_ucast_mgr_process_hop_0, p_mgr );
+
+  cl_qmap_apply_func( p_sw_guid_tbl,
+                      __osm_ucast_mgr_process_leaves, p_mgr );
+
+  /*
+    Get the switch matrices for each switch's neighbors.
+    This process requires a number of iterations equal to
+    the number of switches in the subnet minus 1.
+
+    In each iteration, a switch learns the lid/port/hop
+    information (as contained by a switch's lid matrix) from
+    its immediate neighbors.  After each iteration, a switch
+    (and it's neighbors) know more routing information than
+    it did on the previous iteration.
+    Thus, by repeatedly absorbing the routing information of
+    neighbor switches, every switch eventually learns how to
+    route all LIDs on the subnet.
+
+    Note that there may not be any switches in the subnet if
+    we are in simple p2p configuration.
+  */
+  iteration_max = cl_qmap_count( p_sw_guid_tbl );
+
+  /*
+    If there are switches in the subnet, iterate until the lid
+    matrix has been constructed.  Otherwise, just immediately
+    indicate we're done if no switches exist.
+  */
+  if( iteration_max )
+  {
+    iteration_max--;
+
+    /*
+      we need to find out when the propagation of
+      hop counts has relaxed. So this global variable
+      is preset to 0 on each iteration and if
+      if non of the switches was set will exit the
+      while loop
+    */
+    __some_hop_count_set = TRUE;
+    for( i = 0; (i < iteration_max) && __some_hop_count_set; i++ )
+    {
+      __some_hop_count_set = FALSE;
+      cl_qmap_apply_func( p_sw_guid_tbl,
+                          __osm_ucast_mgr_process_neighbors, p_mgr );
+    }
+    osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+             "osm_ucast_mgr_build_lid_matrices: "
+             "Min-hop propagated in %d steps\n", i );
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_signal_t
+osm_ucast_mgr_process(
+  IN osm_ucast_mgr_t* const p_mgr )
+{
+  struct osm_routing_engine *p_routing_eng;
+  osm_signal_t signal = OSM_SIGNAL_DONE;
+  cl_qmap_t *p_sw_guid_tbl;
+  boolean_t default_routing = TRUE;
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_ucast_mgr_process );
+
+  p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl;
+  p_routing_eng = &p_mgr->p_subn->p_osm->routing_engine;
+
+  CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
+
+  /*
+    If there are no switches in the subnet, we are done.
+  */
+  if (cl_qmap_count( p_sw_guid_tbl ) == 0)
+    goto Exit;
+
+  p_mgr->any_change = FALSE;
+  cl_qmap_apply_func(p_sw_guid_tbl, __osm_ucast_mgr_clean_switch, NULL);
+
+  if (!p_routing_eng->build_lid_matrices ||
+      p_routing_eng->build_lid_matrices(p_routing_eng->context) != 0)
+    osm_ucast_mgr_build_lid_matrices(p_mgr);
+
+  osm_log( p_mgr->p_log, OSM_LOG_INFO,
+           "osm_ucast_mgr_process: "
+           "Min Hop Tables configured on all switches\n" );
+
+  /*
+    Now that the lid matrices have been built, we can
+    build and download the switch forwarding tables.
+  */
+
+  if ( p_routing_eng->ucast_build_fwd_tables && 
+       (p_routing_eng->ucast_build_fwd_tables(p_routing_eng->context) == 0) )
+     default_routing = FALSE;
+  else
+     cl_qmap_apply_func( p_sw_guid_tbl, __osm_ucast_mgr_process_tbl, p_mgr );
+
+  /* dump fdb into file: */
+  if ( osm_log_is_active( p_mgr->p_log, OSM_LOG_ROUTING ) )
+  {
+     if ( !default_routing && p_routing_eng->ucast_dump_tables != 0 )
+        p_routing_eng->ucast_dump_tables(p_routing_eng->context);
+     else
+        __osm_ucast_mgr_dump_tables( p_mgr );
+  }
+
+  if (p_mgr->any_change)
+  {
+    signal = OSM_SIGNAL_DONE_PENDING;
+    osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+             "osm_ucast_mgr_process: "
+             "LFT Tables configured on all switches\n");
+  }
+  else
+  {
+    signal = OSM_SIGNAL_DONE;
+    osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+             "osm_ucast_mgr_process: "
+             "No need to set any LFT Tables on any switches\n");
+  }
+
+ Exit:
+  CL_PLOCK_RELEASE( p_mgr->p_lock );
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return( signal );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_updn.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_ucast_updn.c
new file mode 100644 (file)
index 0000000..c0cbb5c
--- /dev/null
@@ -0,0 +1,1281 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_ucast_updn.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *      Implementation of Up Down Algorithm using ranking & Min Hop
+ *      Calculation functions
+ *
+ * Environment:
+ *      Linux User Mode
+ *
+ * $Revision: 1.0 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qmap.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_opensm.h>
+
+/* //////////////////////////// */
+/*  Local types                 */
+/* //////////////////////////// */
+
+/* direction */
+typedef enum _updn_switch_dir
+{
+    UP = 0,
+    DOWN
+} updn_switch_dir_t;
+
+/* This enum respresent available states in the UPDN algorithm */
+typedef enum _updn_state
+{
+    UPDN_INIT = 0,
+    UPDN_RANK,
+    UPDN_MIN_HOP_CALC,
+} updn_state_t;
+
+/* Rank value of this node */
+typedef struct _updn_rank
+{
+  cl_map_item_t map_item;
+  uint8_t rank;
+} updn_rank_t;
+
+/* Histogram element - the number of occurences of the same hop value */
+typedef struct _updn_hist
+{
+  cl_map_item_t map_item;
+  uint32_t bar_value;
+} updn_hist_t;
+
+typedef struct _updn_next_step
+{
+  updn_switch_dir_t state;
+  osm_switch_t *p_sw;
+} updn_next_step_t;
+
+/* guids list */
+typedef struct _updn_input
+{
+  uint32_t num_guids;
+  uint64_t * guid_list;
+} updn_input_t;
+
+/* updn structure */
+typedef struct _updn
+{
+  updn_state_t   state;
+  boolean_t      auto_detect_root_nodes;
+  cl_qmap_t      guid_rank_tbl;
+  updn_input_t   updn_ucast_reg_inputs;
+  cl_list_t *    p_root_nodes;
+  osm_opensm_t *p_osm;
+} updn_t;
+
+/* ///////////////////////////////// */
+/*  Statics                          */
+/* ///////////////////////////////// */
+static int __osm_updn_find_root_nodes_by_min_hop(OUT updn_t *p_updn);
+
+/**********************************************************************
+ **********************************************************************/
+/* This function returns direction based on rank and guid info of current &
+   remote ports */
+static updn_switch_dir_t
+__updn_get_dir(
+  IN updn_t *p_updn,
+  IN uint8_t cur_rank,
+  IN uint8_t rem_rank,
+  IN uint64_t cur_guid,
+  IN uint64_t rem_guid )
+{
+  uint32_t i = 0, max_num_guids = p_updn->updn_ucast_reg_inputs.num_guids;
+  uint64_t *p_guid = p_updn->updn_ucast_reg_inputs.guid_list;
+  boolean_t cur_is_root = FALSE, rem_is_root = FALSE;
+
+  /* HACK: comes to solve root nodes connection, in a classic subnet root nodes do not connect
+     directly, but in case they are we assign to root node an UP direction to allow UPDN discover
+     the subnet correctly (and not from the point of view of the last root node).
+  */
+  for ( i = 0; i < max_num_guids; i++ )
+  {
+    if (cur_guid == p_guid[i])
+      cur_is_root = TRUE;
+    if (rem_guid == p_guid[i])
+      rem_is_root = TRUE;
+  }
+  if (cur_is_root && rem_is_root)
+    return UP;
+
+  if (cur_rank < rem_rank)
+    return DOWN;
+  else if (cur_rank > rem_rank)
+    return UP;
+  else
+  {
+    /* Equal rank, decide by guid number, bigger == UP direction */
+    if (cur_guid > rem_guid)
+      return UP;
+    else
+      return DOWN;
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* This function creates a new element of updn_next_step_t type then return its
+   pointer , Null if malloc has failed */
+static updn_next_step_t*
+__updn_create_updn_next_step_t(
+  IN updn_switch_dir_t state,
+  IN osm_switch_t* const p_sw )
+{
+  updn_next_step_t *p_next_step;
+
+  p_next_step = (updn_next_step_t*) malloc(sizeof(*p_next_step));
+  if (p_next_step)
+  {
+    memset(p_next_step, 0, sizeof(*p_next_step));
+    p_next_step->state = state;
+    p_next_step->p_sw = p_sw;
+  }
+
+  return p_next_step;
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* This function updates an element in the qmap list by guid index and rank value */
+/* Return 0 if no need to futher update 1 if brought a new value */
+static int
+__updn_update_rank(
+  IN cl_qmap_t *p_guid_rank_tbl,
+  IN ib_net64_t guid,
+  IN uint8_t rank )
+{
+  updn_rank_t *p_updn_rank;
+
+  p_updn_rank = (updn_rank_t*) cl_qmap_get(p_guid_rank_tbl, guid);
+  if (p_updn_rank == (updn_rank_t*) cl_qmap_end(p_guid_rank_tbl))
+  {
+    p_updn_rank = (updn_rank_t*) malloc(sizeof(updn_rank_t));
+
+    CL_ASSERT (p_updn_rank);
+
+    p_updn_rank->rank = rank;
+
+    cl_qmap_insert(p_guid_rank_tbl, guid, &p_updn_rank->map_item);
+    return 1;
+  }
+  else
+  {
+    if (p_updn_rank->rank > rank)
+    {
+      p_updn_rank->rank = rank;
+      return 1;
+    }
+  }
+  return 0;
+}
+
+/**********************************************************************
+ * This function does the bfs of min hop table calculation by guid index
+ * as a starting point.
+ **********************************************************************/
+static int
+__updn_bfs_by_node(
+  IN updn_t *p_updn,
+  IN osm_subn_t *p_subn,
+  IN osm_port_t *p_port,
+  IN cl_qmap_t *p_guid_rank_tbl )
+{
+  /* Init local vars */
+  osm_switch_t *p_self_node = NULL;
+  uint8_t pn, pn_rem;
+  osm_physp_t   *p_physp, *p_remote_physp;
+  cl_list_t     *p_currList, *p_nextList;
+  uint16_t root_lid, max_sw_lid;
+  updn_next_step_t *p_updn_switch, *p_tmp;
+  updn_switch_dir_t next_dir, current_dir;
+  osm_log_t *p_log = &p_updn->p_osm->log;
+
+  OSM_LOG_ENTER( p_log, __updn_bfs_by_node );
+
+  /* Init the list pointers */
+  p_nextList = (cl_list_t*)malloc(sizeof(cl_list_t));
+  cl_list_construct( p_nextList );
+  cl_list_init( p_nextList, 10 );
+  p_currList = p_nextList;
+
+  p_physp = osm_port_get_default_phys_ptr(p_port);
+  /* Check valid pointer */
+  if (!p_physp || !osm_physp_is_valid(p_physp ))
+  {
+    OSM_LOG_EXIT( p_log );
+    return 1;
+  }
+  /* The Root BFS - lid  */
+  root_lid = cl_ntoh16(osm_physp_get_base_lid( p_physp ));
+  /* printf ("-V- BFS through lid : 0x%x\n", root_lid); */
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "__updn_bfs_by_node:"
+           "Starting lid : 0x%x \n", root_lid );
+
+  if (p_port->p_node->sw)
+  {
+    p_self_node = p_port->p_node->sw;
+    /* Update its Min Hop Table */
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "__updn_bfs_by_node:"
+             "Update Min Hop Table of GUID 0x%" PRIx64 "\n",
+             cl_ntoh64(p_port->guid) );
+    osm_switch_set_hops(p_self_node, root_lid, 0, 0);
+  }
+  else
+  {
+    /* This is a CA or router - need to take its remote port */
+    p_remote_physp = p_physp->p_remote_physp;
+    /*
+      make sure that the following occur:
+      1. The port isn't NULL
+      2. The port is a valid port
+    */
+    if ( p_remote_physp && osm_physp_is_valid ( p_remote_physp ))
+    {
+      /* Check if the remote port is a switch, if it is update root_lid,
+         Min Hop Table */
+      if (!p_remote_physp->p_node->sw)
+      {
+        osm_log( p_log, OSM_LOG_ERROR,
+                 "__updn_bfs_by_node: ERR AA07: "
+                 "This is a non switched subnet OR non valid connection, cannot perform UPDN algorithm\n" );
+        OSM_LOG_EXIT( p_log );
+        return 1;
+      }
+      else
+      {
+        p_self_node = p_remote_physp->p_node->sw;
+        max_sw_lid = osm_switch_get_max_lid_ho(p_self_node);
+        if ((1 <= root_lid) && (root_lid <= max_sw_lid))
+          /* Update its Min Hop Table */
+        {
+          /* NOTE : Check if there is a function which prints the Min Hop Table */
+          osm_log( p_log, OSM_LOG_DEBUG,
+                   "__updn_bfs_by_node:"
+                   "Update Min Hop Table of GUID 0x%" PRIx64 "\n",
+                   cl_ntoh64(p_remote_physp->port_guid) );
+          osm_switch_set_hops(p_self_node, root_lid,
+                              p_remote_physp->port_num, 1);
+
+        }
+        else
+        {
+          osm_log( p_log, OSM_LOG_ERROR,
+                   "__updn_bfs_by_node: ERR AA09: "
+                   " Invalid lid value 0x%x for switch 0x%" PRIx64 "\n",
+                   root_lid,
+                   cl_ntoh64(p_self_node->p_node->node_info.port_guid) );
+          OSM_LOG_EXIT( p_log );
+          return 1;
+        }
+      }
+    }
+  }
+
+  CL_ASSERT(p_self_node);
+
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "__updn_bfs_by_node:"
+           "Starting from switch - port GUID 0x%" PRIx64 "\n",
+           cl_ntoh64(p_self_node->p_node->node_info.port_guid) );
+
+  /* Update list with the updn_next_step_t new element */
+  /* NOTE : When inserting an item which is a pointer to a struct, does remove
+     action also free its memory */
+  if (!(p_tmp=__updn_create_updn_next_step_t(UP, p_self_node)))
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "__updn_bfs_by_node:  ERR AA08: "
+             "Could not create updn_next_step_t\n" );
+    return 1;
+  }
+
+  cl_list_insert_tail(p_currList, p_tmp);
+
+  /* BFS the list till no next element */
+  osm_log( p_log, OSM_LOG_VERBOSE,
+           "__updn_bfs_by_node:"
+           "BFS the subnet [\n" );
+
+  while (!cl_is_list_empty(p_currList))
+  {
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "__updn_bfs_by_node:"
+             "Starting a new iteration with %zu elements in current list\n",
+             cl_list_count(p_currList) );
+    /* Init the switch directed list */
+    p_nextList = (cl_list_t*)malloc(sizeof(cl_list_t));
+    cl_list_construct( p_nextList );
+    cl_list_init( p_nextList, 10 );
+    /* Go over all current list items till it's empty */
+    /*       printf ("-V- In inner while\n"); */
+    p_updn_switch = (updn_next_step_t*)cl_list_remove_head( p_currList );
+    /* While there is a pointer to updn struct we continue to BFS */
+    while (p_updn_switch)
+    {
+      current_dir = p_updn_switch->state;
+      osm_log( p_log, OSM_LOG_DEBUG,
+               "__updn_bfs_by_node:"
+               "Visiting port GUID 0x%" PRIx64 "\n",
+               cl_ntoh64(p_updn_switch->p_sw->p_node->node_info.port_guid) );
+      /* Go over all ports of the switch and find unvisited remote nodes */
+      for ( pn = 0; pn < osm_switch_get_num_ports(p_updn_switch->p_sw); pn++ )
+      {
+        /* printf("-V- Inner for in port num 0x%X\n", pn); */
+        osm_node_t *p_remote_node;
+        cl_list_iterator_t updn_switch_iterator;
+        boolean_t HasVisited = FALSE;
+        ib_net64_t remote_guid,current_guid;
+        updn_rank_t *p_rem_rank, *p_cur_rank;
+        uint8_t current_min_hop, remote_min_hop, set_hop_return_value;
+        osm_switch_t *p_remote_sw;
+
+        current_guid = osm_node_get_node_guid(p_updn_switch->p_sw->p_node);
+        p_remote_node = osm_node_get_remote_node( p_updn_switch->p_sw->p_node
+                                                  , pn, &pn_rem );
+        /* If no remote node OR remote node is not a SWITCH
+           continue to next pn */
+        if( !p_remote_node ||
+            (osm_node_get_type(p_remote_node) != IB_NODE_TYPE_SWITCH) )
+          continue;
+        /* Fetch remote guid only after validation of remote node */
+        remote_guid = osm_node_get_node_guid(p_remote_node);
+        /* printf ("-V- Current guid : 0x%" PRIx64 " Remote guid : 0x%" PRIx64 "\n", */
+        /* cl_ntoh64(current_guid), cl_ntoh64(remote_guid)); */
+        p_remote_sw = p_remote_node->sw;
+        p_rem_rank = (updn_rank_t*)cl_qmap_get(p_guid_rank_tbl, remote_guid);
+        p_cur_rank = (updn_rank_t*)cl_qmap_get(p_guid_rank_tbl, current_guid);
+        /* Decide which direction to mark it (UP/DOWN) */
+        next_dir = __updn_get_dir (p_updn, p_cur_rank->rank, p_rem_rank->rank,
+                                   current_guid, remote_guid);
+
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__updn_bfs_by_node:"
+                 "move from 0x%016" PRIx64 " rank: %u "
+                 "to 0x%016" PRIx64" rank: %u\n",
+                 cl_ntoh64(current_guid), p_cur_rank->rank,
+                 cl_ntoh64(remote_guid), p_rem_rank->rank );
+        /* Check if this is a legal step : the only illegal step is going
+           from DOWN to UP */
+        if ((current_dir == DOWN) && (next_dir == UP))
+        {
+          osm_log( p_log, OSM_LOG_DEBUG,
+                   "__updn_bfs_by_node:"
+                   "Avoiding move from 0x%016" PRIx64 " to 0x%016" PRIx64"\n",
+                   cl_ntoh64(current_guid), cl_ntoh64(remote_guid) );
+          /* Illegal step */
+          continue;
+        }
+        /* Set MinHop value for the current lid */
+        current_min_hop = osm_switch_get_least_hops(p_updn_switch->p_sw,root_lid);
+        /* Check hop count if better insert into NextState list && update
+           the remote node Min Hop Table */
+        remote_min_hop = osm_switch_get_hop_count(p_remote_sw, root_lid, pn_rem);
+        if (current_min_hop + 1 < remote_min_hop)
+        {
+          osm_log( p_log, OSM_LOG_DEBUG,
+                   "__updn_bfs_by_node (less):"
+                   "Setting Min Hop Table of switch: 0x%" PRIx64
+                   "\n\t\tCurrent hop count is: %d, next hop count: %d"
+                   "\n\tlid to set: 0x%x"
+                   "\n\tport number: 0x%X"
+                   " \n\thops number: %d\n",
+                   cl_ntoh64(remote_guid), remote_min_hop,current_min_hop + 1,
+                   root_lid, pn_rem, current_min_hop + 1 );
+          set_hop_return_value = osm_switch_set_hops(p_remote_sw, root_lid, pn_rem, current_min_hop + 1);
+          if (set_hop_return_value)
+          {
+            osm_log( p_log, OSM_LOG_ERROR,
+                     "__updn_bfs_by_node (less) ERR AA01: "
+                     "Invalid value returned from set min hop is: %d\n",
+                     set_hop_return_value );
+          }
+          /* Check if remote port is allready has been visited */
+          updn_switch_iterator = cl_list_head(p_nextList);
+          while( updn_switch_iterator != cl_list_end(p_nextList) )
+          {
+            updn_next_step_t *p_updn;
+            p_updn = (updn_next_step_t*)cl_list_obj(updn_switch_iterator);
+            /* Mark HasVisited only if:
+               1. Same node guid
+               2. Same direction
+            */
+            if ((p_updn->p_sw->p_node == p_remote_node) && (p_updn->state == next_dir))
+              HasVisited = TRUE;
+            updn_switch_iterator = cl_list_next(updn_switch_iterator);
+          }
+          if (!HasVisited)
+          {
+            /* Insert updn_switch item into the next list */
+            if(!(p_tmp=__updn_create_updn_next_step_t(next_dir, p_remote_sw)))
+            {
+              osm_log( p_log, OSM_LOG_ERROR,
+                       "__updn_bfs_by_node: ERR AA11: "
+                       "Could not create updn_next_step_t\n" );
+              return 1;
+            }
+            osm_log( p_log, OSM_LOG_DEBUG,
+                     "__updn_bfs_by_node: "
+                     "Inserting new element to the next list: guid=0x%" PRIx64 " %s\n",
+                     cl_ntoh64(p_tmp->p_sw->p_node->node_info.port_guid),
+                     (p_tmp->state == UP ? "UP" : "DOWN")
+                     );
+            cl_list_insert_tail(p_nextList, p_tmp);
+          }
+          /* If the same value only update entry - at the min hop table */
+        } else if (current_min_hop + 1 == osm_switch_get_hop_count(p_remote_sw,
+                                                                   root_lid,
+                                                                   pn_rem))
+        {
+          osm_log( p_log, OSM_LOG_DEBUG,
+                   "__updn_bfs_by_node (equal):"
+                   "Setting Min Hop Table of switch: 0x%" PRIx64
+                   "\n\t\tCurrent hop count is: %d, next hop count: %d"
+                   "\n\tlid to set: 0x%x"
+                   "\n\tport number: 0x%X"
+                   "\n\thops number: %d\n",
+                   cl_ntoh64(remote_guid),
+                   osm_switch_get_hop_count(p_remote_sw, root_lid, pn_rem),
+                   current_min_hop + 1, root_lid, pn_rem, current_min_hop + 1 );
+          set_hop_return_value = osm_switch_set_hops(p_remote_sw, root_lid, pn_rem, current_min_hop + 1);
+
+          if (set_hop_return_value)
+          {
+            osm_log( p_log, OSM_LOG_ERROR,
+                     "__updn_bfs_by_node (less) ERR AA12: "
+                     "Invalid value returned from set min hop is: %d\n",
+                     set_hop_return_value );
+          }
+        }
+      }
+      free (p_updn_switch);
+      p_updn_switch = (updn_next_step_t*)cl_list_remove_head( p_currList );
+    }
+    /* Cleanup p_currList */
+    cl_list_destroy( p_currList );
+    free (p_currList);
+
+    /* Reassign p_currList to p_nextList */
+    p_currList = p_nextList;
+  }
+  /* Cleanup p_currList - Had the pointer to cl_list_t */
+  cl_list_destroy( p_currList );
+  free (p_currList);
+  osm_log( p_log, OSM_LOG_VERBOSE,
+           "__updn_bfs_by_node:"
+           "BFS the subnet ]\n" );
+  OSM_LOG_EXIT( p_log );
+  return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+updn_destroy(
+  IN updn_t* const p_updn )
+{
+  cl_map_item_t *p_map_item;
+  uint64_t *p_guid_list_item;
+
+  /* Destroy the updn struct */
+  p_map_item = cl_qmap_head( &p_updn->guid_rank_tbl);
+  while( p_map_item != cl_qmap_end( &p_updn->guid_rank_tbl))
+  {
+    osm_log ( &p_updn->p_osm->log, OSM_LOG_DEBUG,
+              "osm_subn_calc_up_down_min_hop_table: "
+              "guid = 0x%" PRIx64 " rank = %u\n",
+              cl_ntoh64(cl_qmap_key(p_map_item)),
+              ((updn_rank_t *)p_map_item)->rank );
+    cl_qmap_remove_item( &p_updn->guid_rank_tbl, p_map_item);
+    free( (updn_rank_t *)p_map_item);
+    p_map_item = cl_qmap_head( &p_updn->guid_rank_tbl);
+  }
+
+  /* free the array of guids */
+  if (p_updn->updn_ucast_reg_inputs.guid_list)
+    free(p_updn->updn_ucast_reg_inputs.guid_list);
+
+  /* destroy the list of root nodes */
+  while ((p_guid_list_item = cl_list_remove_head( p_updn->p_root_nodes )))
+    free( p_guid_list_item );
+
+  cl_list_remove_all( p_updn->p_root_nodes );
+  cl_list_destroy( p_updn->p_root_nodes );
+  free ( p_updn->p_root_nodes );
+  free (p_updn);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static updn_t*
+updn_construct(osm_log_t *p_log)
+{
+  updn_t* p_updn;
+
+  OSM_LOG_ENTER( p_log, updn_construct );
+  p_updn = malloc(sizeof(updn_t));
+  if (p_updn)
+    memset(p_updn, 0, sizeof(updn_t));
+  OSM_LOG_EXIT( p_log );
+  return(p_updn);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static cl_status_t
+updn_init(
+  IN updn_t* const p_updn,
+  IN osm_opensm_t *p_osm )
+{
+  cl_list_t * p_list;
+  FILE*       p_updn_guid_file;
+  char        line[MAX_UPDN_GUID_FILE_LINE_LENGTH];
+  uint64_t *  p_tmp;
+  cl_list_iterator_t guid_iterator;
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( &p_osm->log, updn_init );
+
+  p_updn->p_osm = p_osm;
+  p_updn->state = UPDN_INIT;
+  cl_qmap_init( &p_updn->guid_rank_tbl );
+  p_list = (cl_list_t*)malloc(sizeof(cl_list_t));
+  if (!p_list)
+  {
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  cl_list_construct( p_list );
+  cl_list_init( p_list, 10 );
+  p_updn->p_root_nodes = p_list;
+  p_updn->updn_ucast_reg_inputs.num_guids = 0;
+  p_updn->updn_ucast_reg_inputs.guid_list = NULL;
+  p_updn->auto_detect_root_nodes = FALSE;
+
+  /*
+     Check the source for root node list, if file parse it, otherwise
+     wait for a callback to activate auto detection
+  */
+  if (p_osm->subn.opt.updn_guid_file)
+  {
+    /* Now parse guid from file */
+    p_updn_guid_file = fopen(p_osm->subn.opt.updn_guid_file, "r");
+    if (p_updn_guid_file == NULL)
+    {
+      osm_log( &p_osm->log, OSM_LOG_ERROR,
+               "osm_opensm_init : ERR AA02: "
+               "Failed to open guid list file (%s)\n",
+               p_osm->subn.opt.updn_guid_file );
+      status = IB_NOT_FOUND;
+      goto Exit;
+    }
+
+    while ( fgets(line, MAX_UPDN_GUID_FILE_LINE_LENGTH, p_updn_guid_file) )
+    {
+      if (strcspn(line, " ,;.") == strlen(line))
+      {
+        /* Skip empty lines anywhere in the file - only one char means the Null termination */
+        if (strlen(line) > 1)
+        {
+          p_tmp = malloc(sizeof(uint64_t));
+          *p_tmp = strtoull(line, NULL, 16);
+          cl_list_insert_tail(p_updn->p_root_nodes, p_tmp);
+        }
+      }
+      else
+      {
+        osm_log( &p_osm->log, OSM_LOG_ERROR,
+                 "osm_opensm_init: ERR AA03: "
+                 "Bad formatted guid in file (%s): %s\n",
+                 p_osm->subn.opt.updn_guid_file, line );
+        status = IB_NOT_FOUND;
+        break;
+      }
+    }
+
+    /* For Debug Purposes ... */
+    osm_log( &p_osm->log, OSM_LOG_DEBUG,
+             "osm_opensm_init: "
+             "UPDN - Root nodes fetching by file %s\n",
+             p_osm->subn.opt.updn_guid_file );
+    guid_iterator = cl_list_head(p_updn->p_root_nodes);
+    while( guid_iterator != cl_list_end(p_updn->p_root_nodes) )
+    {
+      osm_log( &p_osm->log, OSM_LOG_DEBUG,
+               "osm_opensm_init: "
+               "Inserting GUID 0x%" PRIx64 " as root node\n",
+               *((uint64_t*)cl_list_obj(guid_iterator)) );
+      guid_iterator = cl_list_next(guid_iterator);
+    }
+  }
+  else
+  {
+    p_updn->auto_detect_root_nodes = TRUE;
+  }
+  /* If auto mode detection required - will be executed in main b4 the assignment of UI Ucast */
+
+Exit :
+  OSM_LOG_EXIT( &p_osm->log );
+  return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* NOTE : PLS check if we need to decide that the first */
+/*        rank is a SWITCH for BFS purpose */
+static int
+updn_subn_rank(
+  IN uint64_t root_guid,
+  IN uint8_t base_rank,
+  IN updn_t* p_updn )
+{
+  /* Init local vars */
+  osm_port_t *p_root_port = NULL;
+  uint16_t tbl_size;
+  uint8_t rank = base_rank;
+  osm_physp_t   *p_physp, *p_remote_physp, *p_physp_temp;
+  cl_list_t     *p_currList,*p_nextList;
+  cl_status_t did_cause_update;
+  uint8_t num_ports, port_num;
+  osm_log_t *p_log = &p_updn->p_osm->log;
+
+  OSM_LOG_ENTER( p_log, updn_subn_rank );
+
+  osm_log( p_log, OSM_LOG_VERBOSE,
+           "updn_subn_rank: "
+           "Ranking starts from GUID 0x%" PRIx64 "\n", root_guid );
+
+  /* Init the list pointers */
+  p_nextList = (cl_list_t*)malloc(sizeof(cl_list_t));
+  cl_list_construct( p_nextList );
+  cl_list_init( p_nextList, 10 );
+  p_currList = p_nextList;
+
+  /* Check valid subnet & guid */
+  tbl_size = (uint16_t)(cl_qmap_count(&p_updn->p_osm->subn.port_guid_tbl));
+  if (tbl_size == 0)
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "updn_subn_rank: ERR AA04: "
+             "Port guid table is empty, cannot perform ranking\n" );
+    OSM_LOG_EXIT( p_log );
+    return 1;
+  }
+
+  p_root_port = (osm_port_t*) cl_qmap_get(&p_updn->p_osm->subn.port_guid_tbl,
+                                          cl_ntoh64(root_guid));
+  if( p_root_port == (osm_port_t*)cl_qmap_end( &p_updn->p_osm->subn.port_guid_tbl ) )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "updn_subn_rank: ERR AA05: "
+             "Wrong guid value: 0x%" PRIx64 "\n", root_guid );
+    OSM_LOG_EXIT( p_log );
+    return 1;
+  }
+
+  /* Rank the first chosen guid anyway since its the base rank */
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "updn_subn_rank: "
+           "Ranking port GUID 0x%" PRIx64 "\n", root_guid );
+
+  __updn_update_rank(&p_updn->guid_rank_tbl, cl_ntoh64(root_guid), rank);
+  /*
+    HACK: We are assuming SM is running on HCA, so when getting the default
+    port we'll get the port connected to the rest of the subnet. If SM is
+    running on SWITCH - we should try to get a dr path from all switch ports.
+  */
+  p_physp = osm_port_get_default_phys_ptr( p_root_port );
+  CL_ASSERT( p_physp );
+  CL_ASSERT( osm_physp_is_valid( p_physp ) );
+  /* We can safely add the node to the list */
+  cl_list_insert_tail(p_nextList, p_physp);
+  /* Assign pointer to the list for BFS */
+  p_currList = p_nextList;
+
+  /* BFS the list till its empty */
+  osm_log( p_log, OSM_LOG_VERBOSE,
+           "updn_subn_rank: "
+           "BFS the subnet [\n" );
+
+  while (!cl_is_list_empty(p_currList))
+  {
+    rank++;
+    p_nextList = (cl_list_t*)malloc(sizeof(cl_list_t));
+    cl_list_construct( p_nextList );
+    cl_list_init( p_nextList, 10 );
+    p_physp = (osm_physp_t*)cl_list_remove_head( p_currList );
+    /* Go over all remote nodes and rank them (if not allready visited) till
+       no elemtent in the list p_currList */
+    while ( p_physp != NULL )
+    {
+      num_ports = osm_node_get_num_physp( p_physp->p_node );
+      osm_log( p_log, OSM_LOG_DEBUG,
+               "updn_subn_rank: "
+               "Handling port GUID 0x%" PRIx64 "\n",
+               cl_ntoh64(p_physp->port_guid) );
+      for (port_num = 1; port_num < num_ports; port_num++)
+      {
+        ib_net64_t port_guid;
+
+        /* Current port fetched in order to get remote side */
+        p_physp_temp = osm_node_get_physp_ptr( p_physp->p_node, port_num );
+        p_remote_physp = p_physp_temp->p_remote_physp;
+
+        /*
+          make sure that all the following occur on p_remote_physp:
+          1. The port isn't NULL
+          2. The port is a valid port
+        */
+        if ( p_remote_physp &&
+             osm_physp_is_valid ( p_remote_physp ))
+        {
+          port_guid = p_remote_physp->port_guid;
+          osm_log( p_log, OSM_LOG_DEBUG,
+                   "updn_subn_rank: "
+                   "Visiting remote port GUID 0x%" PRIx64 "\n",
+                   cl_ntoh64(port_guid) );
+          /* Was it visited ?
+             Only if the pointer equal to cl_qmap_end its not
+             found in the list */
+          osm_log( p_log, OSM_LOG_DEBUG,
+                   "updn_subn_rank: "
+                   "Ranking port GUID 0x%" PRIx64 "\n", cl_ntoh64(port_guid) );
+          did_cause_update = __updn_update_rank(&p_updn->guid_rank_tbl, port_guid, rank);
+
+          osm_log( p_log, OSM_LOG_VERBOSE,
+                   "updn_subn_rank: "
+                   "Rank of port GUID 0x%" PRIx64 " = %u\n", cl_ntoh64(port_guid),
+                   ((updn_rank_t*)cl_qmap_get(&p_updn->guid_rank_tbl, port_guid))->rank
+                   );
+
+          if (did_cause_update)
+          {
+            cl_list_insert_tail(p_nextList, p_remote_physp);
+          }
+        }
+      }
+      /* Propagte through the next item in the p_currList */
+      p_physp = (osm_physp_t*)cl_list_remove_head( p_currList );
+    }
+    /* First free the allocation of cl_list pointer then reallocate */
+    cl_list_destroy( p_currList );
+    free(p_currList);
+    /* p_currList is empty - need to assign it to p_nextList */
+    p_currList = p_nextList;
+  }
+
+  osm_log( p_log, OSM_LOG_VERBOSE,
+           "updn_subn_rank: "
+           "BFS the subnet ]\n" );
+
+  cl_list_destroy( p_currList );
+  free(p_currList);
+
+  /* Print Summary of ranking */
+  osm_log( p_log, OSM_LOG_VERBOSE,
+           "updn_subn_rank: "
+           "Rank Info :\n\t Root Guid = 0x%" PRIx64 "\n\t Max Node Rank = %d\n",
+           cl_ntoh64(p_root_port->guid), rank );
+  p_updn->state = UPDN_RANK;
+  OSM_LOG_EXIT( p_log );
+  return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static int
+__osm_subn_set_up_down_min_hop_table(
+  IN updn_t* p_updn )
+{
+  /* Init local vars */
+  osm_subn_t *p_subn = &p_updn->p_osm->subn;
+  osm_log_t *p_log = &p_updn->p_osm->log;
+  osm_switch_t *p_next_sw,*p_sw;
+  osm_port_t *p_next_port,*p_port;
+  ib_net64_t port_guid;
+
+  OSM_LOG_ENTER( p_log, __osm_subn_set_up_down_min_hop_table );
+  if (p_updn->state == UPDN_INIT)
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "__osm_subn_set_up_down_min_hop_table: ERR AA06: "
+             "Calculating Min Hop only allowed after ranking\n" );
+    OSM_LOG_EXIT( p_log );
+    return 1;
+  }
+
+  /* Check if its a non switched subnet .. */
+  if ( cl_is_qmap_empty( &p_subn->sw_guid_tbl ) )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "__osm_subn_set_up_down_min_hop_table: ERR AA10: "
+             "This is a non switched subnet, cannot perform UPDN algorithm\n" );
+    OSM_LOG_EXIT( p_log );
+    return 1;
+  }
+  /* Go over all the switches in the subnet - for each init their Min Hop
+     Table */
+  osm_log( p_log, OSM_LOG_VERBOSE,
+           "__osm_subn_set_up_down_min_hop_table: "
+           "Init Min Hop Table of all switches [\n" );
+
+  p_next_sw = (osm_switch_t*)cl_qmap_head( &p_subn->sw_guid_tbl );
+  while( p_next_sw != (osm_switch_t*)cl_qmap_end( &p_subn->sw_guid_tbl ) )
+  {
+    p_sw = p_next_sw;
+    p_next_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item );
+    /* Clear Min Hop Table */
+    osm_lid_matrix_clear(&(p_sw->lmx));
+  }
+
+  osm_log( p_log, OSM_LOG_VERBOSE,
+           "__osm_subn_set_up_down_min_hop_table: "
+           "Init Min Hop Table of all switches ]\n" );
+
+  /* Now do the BFS for each port  in the subnet */
+  osm_log( p_log, OSM_LOG_VERBOSE,
+           "__osm_subn_set_up_down_min_hop_table: "
+           "BFS through all port guids in the subnet [\n" );
+  p_next_port = (osm_port_t*)cl_qmap_head( &p_subn->port_guid_tbl );
+  while( p_next_port != (osm_port_t*)cl_qmap_end( &p_subn->port_guid_tbl ) )
+  {
+    p_port = p_next_port;
+    p_next_port = (osm_port_t*)cl_qmap_next( &p_port->map_item );
+    port_guid = cl_qmap_key(&(p_port->map_item));
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "__osm_subn_set_up_down_min_hop_table: "
+             "BFS through port GUID 0x%" PRIx64 "\n",
+             cl_ntoh64(port_guid) );
+    if(__updn_bfs_by_node(p_updn, p_subn, p_port,
+                          &p_updn->guid_rank_tbl))
+    {
+      OSM_LOG_EXIT( p_log );
+      return 1;
+    }
+  }
+
+  osm_log( p_log, OSM_LOG_VERBOSE,
+           "__osm_subn_set_up_down_min_hop_table: "
+           "BFS through all port guids in the subnet ]\n" );
+  /* Cleanup */
+  OSM_LOG_EXIT( p_log );
+  return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static int
+__osm_subn_calc_up_down_min_hop_table(
+  IN uint32_t num_guids,
+  IN uint64_t * guid_list,
+  IN updn_t* p_updn )
+{
+  uint8_t idx = 0;
+  cl_map_item_t *p_map_item;
+  int status;
+
+  OSM_LOG_ENTER( &p_updn->p_osm->log, osm_subn_calc_up_down_min_hop_table );
+  osm_log( &p_updn->p_osm->log, OSM_LOG_VERBOSE,
+           "__osm_subn_calc_up_down_min_hop_table: "
+           "Ranking all port guids in the list\n" );
+  if (num_guids == 0)
+  {
+    osm_log( &p_updn->p_osm->log, OSM_LOG_ERROR,
+             "__osm_subn_calc_up_down_min_hop_table: ERR AA0A: "
+             "No guids were given or number of guids is 0\n" );
+    return 1;
+  }
+
+  for (idx = 0; idx < num_guids; idx++)
+  {
+    /* Apply the ranking for each guid given by user  - bypass illegal ones */
+    updn_subn_rank(guid_list[idx], 0, p_updn);
+  }
+  /* After multiple ranking need to set Min Hop Table by UpDn algorithm  */
+  osm_log( &p_updn->p_osm->log, OSM_LOG_VERBOSE,
+           "__osm_subn_calc_up_down_min_hop_table: "
+           "Setting all switches' Min Hop Table\n" );
+
+  status = __osm_subn_set_up_down_min_hop_table (p_updn);
+
+  /* Cleanup updn rank tbl */
+  p_map_item = cl_qmap_head( &p_updn->guid_rank_tbl);
+  while( p_map_item != cl_qmap_end( &p_updn->guid_rank_tbl))
+  {
+    osm_log( &p_updn->p_osm->log, OSM_LOG_DEBUG,
+             "__osm_subn_calc_up_down_min_hop_table: "
+             "guid = 0x%" PRIx64 " rank = %u\n",
+             cl_ntoh64(cl_qmap_key(p_map_item)),
+             ((updn_rank_t *)p_map_item)->rank );
+    cl_qmap_remove_item( &p_updn->guid_rank_tbl, p_map_item);
+    free( (updn_rank_t *)p_map_item);
+    p_map_item = cl_qmap_head( &p_updn->guid_rank_tbl);
+  }
+
+  OSM_LOG_EXIT( &p_updn->p_osm->log );
+  return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* UPDN callback function */
+static int
+__osm_updn_call(
+  void *ctx )
+{
+  updn_t *p_updn = ctx;
+
+  OSM_LOG_ENTER( &p_updn->p_osm->log, __osm_updn_call );
+
+  /* First auto detect root nodes - if required */
+  if ( p_updn->auto_detect_root_nodes )
+  {
+    osm_ucast_mgr_build_lid_matrices( &p_updn->p_osm->sm.ucast_mgr );
+    /* printf ("-V- b4 osm_updn_find_root_nodes_by_min_hop\n"); */
+    __osm_updn_find_root_nodes_by_min_hop( p_updn );
+  }
+  /* printf ("-V- after osm_updn_find_root_nodes_by_min_hop\n"); */
+  /* Only if there are assigned root nodes do the algorithm , otherwise perform do nothing */
+  if ( p_updn->updn_ucast_reg_inputs.num_guids > 0)
+  {
+    osm_log( &(p_updn->p_osm->log), OSM_LOG_DEBUG,
+             "__osm_updn_call: "
+             "activating UPDN algorithm\n" );
+    __osm_subn_calc_up_down_min_hop_table( p_updn->updn_ucast_reg_inputs.num_guids,
+                                           p_updn->updn_ucast_reg_inputs.guid_list,
+                                           p_updn );
+  }
+  else
+    osm_log( &p_updn->p_osm->log, OSM_LOG_INFO,
+             "__osm_updn_call: "
+             "disable UPDN algorithm, no root nodes were found\n" );
+  
+  OSM_LOG_EXIT( &p_updn->p_osm->log );
+  return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* UPDN convert cl_list to guid array in updn struct */
+static void
+__osm_updn_convert_list2array(
+  IN updn_t * p_updn )
+{
+  uint32_t i = 0, max_num = 0;
+  uint64_t *p_guid;
+
+  OSM_LOG_ENTER( &p_updn->p_osm->log, __osm_updn_convert_list2array );
+
+  p_updn->updn_ucast_reg_inputs.num_guids = cl_list_count(
+    p_updn->p_root_nodes);
+  if (p_updn->updn_ucast_reg_inputs.guid_list)
+    free(p_updn->updn_ucast_reg_inputs.guid_list);
+  p_updn->updn_ucast_reg_inputs.guid_list = (uint64_t *)malloc(
+    p_updn->updn_ucast_reg_inputs.num_guids*sizeof(uint64_t));
+  if (p_updn->updn_ucast_reg_inputs.guid_list)
+    memset(p_updn->updn_ucast_reg_inputs.guid_list, 0,
+           p_updn->updn_ucast_reg_inputs.num_guids*sizeof(uint64_t));
+  if (!cl_is_list_empty(p_updn->p_root_nodes))
+  {
+    while( (p_guid = (uint64_t*)cl_list_remove_head(p_updn->p_root_nodes)) )
+    {
+      p_updn->updn_ucast_reg_inputs.guid_list[i] = *p_guid;
+      free(p_guid);
+      i++;
+    }
+    max_num = i;
+    for (i = 0; i < max_num; i++ )
+      osm_log( &p_updn->p_osm->log, OSM_LOG_DEBUG,
+               "__osm_updn_convert_list2array: "
+               "Map GUID 0x%" PRIx64 " into UPDN array\n",
+               p_updn->updn_ucast_reg_inputs.guid_list[i] );
+  }
+  /* Since we need the template list for other sweeps, we wont destroy & free it */
+  OSM_LOG_EXIT( &p_updn->p_osm->log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* Find Root nodes automatically by Min Hop Table info */
+static int
+__osm_updn_find_root_nodes_by_min_hop(
+  OUT updn_t *  p_updn )
+{
+  osm_opensm_t *p_osm = p_updn->p_osm;
+  osm_switch_t *p_next_sw, *p_sw;
+  osm_port_t   *p_next_port, *p_port;
+  osm_physp_t  *p_physp;
+  uint32_t      numCas = 0;
+  uint32_t      numSws = cl_qmap_count(&p_osm->subn.sw_guid_tbl);
+  cl_qmap_t     min_hop_hist; /* Histogram container */
+  updn_hist_t  *p_updn_hist, *p_up_ht;
+  uint8_t       maxHops = 0; /* contain the max histogram index */
+  uint64_t     *p_guid;
+  cl_list_t    *p_root_nodes_list = p_updn->p_root_nodes;
+  cl_map_t      ca_by_lid_map; /* map holding all CA lids  */
+  uint16_t self_lid_ho;
+
+  OSM_LOG_ENTER( &p_osm->log, osm_updn_find_root_nodes_by_min_hop );
+
+  osm_log( &p_osm->log, OSM_LOG_DEBUG,
+           "__osm_updn_find_root_nodes_by_min_hop: "
+           "current number of ports in the subnet is %d\n",
+           cl_qmap_count(&p_osm->subn.port_guid_tbl) );
+  /* Init the required vars */
+  cl_qmap_init( &min_hop_hist );
+  cl_map_construct( &ca_by_lid_map );
+  cl_map_init( &ca_by_lid_map, 10 );
+
+  /* EZ:
+     p_ca_list = (cl_list_t*)malloc(sizeof(cl_list_t)); 
+     cl_list_construct( p_ca_list ); 
+     cl_list_init( p_ca_list, 10 );
+  */
+
+  /* Find the Maximum number of CAs (and routers) for histogram normalization */
+  osm_log( &p_osm->log, OSM_LOG_VERBOSE,
+           "__osm_updn_find_root_nodes_by_min_hop: "
+           "Find the number of CAs and store them in cl_list\n" );
+  p_next_port = (osm_port_t*)cl_qmap_head( &p_osm->subn.port_guid_tbl );
+  while( p_next_port != (osm_port_t*)cl_qmap_end( &p_osm->subn.port_guid_tbl ) ) {
+    p_port = p_next_port;
+    p_next_port = (osm_port_t*)cl_qmap_next( &p_next_port->map_item );
+    if ( osm_node_get_type(p_port->p_node) != IB_NODE_TYPE_SWITCH )
+    {
+      p_physp = osm_port_get_default_phys_ptr(p_port);
+      self_lid_ho = cl_ntoh16( osm_physp_get_base_lid(p_physp) );
+      numCas++;
+      /* EZ:
+         self = malloc(sizeof(uint16_t));
+         *self = self_lid_ho;
+         cl_list_insert_tail(p_ca_list, self);
+      */
+      cl_map_insert( &ca_by_lid_map, self_lid_ho, (void *)0x1);
+      osm_log( &p_osm->log, OSM_LOG_DEBUG,
+               "__osm_updn_find_root_nodes_by_min_hop: "
+               "Inserting into array GUID 0x%" PRIx64 ", Lid: 0x%X\n",
+               cl_ntoh64(osm_port_get_guid(p_port)), self_lid_ho );
+    }
+  }
+  osm_log( &p_osm->log, OSM_LOG_DEBUG,
+           "__osm_updn_find_root_nodes_by_min_hop: "
+           "Found %u CA, %u SW in the subnet\n", numCas, numSws );
+  p_next_sw = (osm_switch_t*)cl_qmap_head( &p_osm->subn.sw_guid_tbl );
+  osm_log( &p_osm->log, OSM_LOG_VERBOSE,
+           "__osm_updn_find_root_nodes_by_min_hop: "
+           "Passing through all switches to collect Min Hop info\n" );
+  while( p_next_sw != (osm_switch_t*)cl_qmap_end( &p_osm->subn.sw_guid_tbl ) )
+  {
+    uint16_t max_lid_ho, lid_ho;
+    uint8_t hop_val;
+    uint16_t numHopBarsOverThd1 = 0;
+    uint16_t numHopBarsOverThd2 = 0;
+    double thd1, thd2;
+
+    p_sw = p_next_sw;
+    /* Roll to the next switch */
+    p_next_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item );
+
+    /* Clear Min Hop Table && FWD Tbls - This should caused opensm to
+       rebuild its FWD tables , post setting Min Hop Tables */
+    max_lid_ho = osm_switch_get_max_lid_ho(p_sw);
+    /* Get base lid of switch by retrieving port 0 lid of node pointer */
+    self_lid_ho = cl_ntoh16( osm_node_get_base_lid( p_sw->p_node, 0 ) );
+    osm_log( &p_osm->log, OSM_LOG_DEBUG,
+             "__osm_updn_find_root_nodes_by_min_hop: "
+             "Passing through switch lid 0x%X\n", self_lid_ho );
+    for (lid_ho = 1; lid_ho <= max_lid_ho; lid_ho++)
+    {
+      /* Skip lids which are not CAs - 
+         for the histogram purposes we care only about CAs */
+      
+      /* EZ:
+         boolean_t LidFound = FALSE;
+         cl_list_iterator_t ca_lid_iterator= cl_list_head(p_ca_list);
+         while( (ca_lid_iterator != cl_list_end(p_ca_list)) && !LidFound )
+         {
+         uint16_t *p_lid;
+         
+         p_lid = (uint16_t*)cl_list_obj(ca_lid_iterator);
+         if ( *p_lid == lid_ho )
+         LidFound = TRUE;
+         ca_lid_iterator = cl_list_next(ca_lid_iterator);
+         
+         }
+         if ( LidFound )
+      */
+      if (cl_map_get( &ca_by_lid_map, lid_ho ))
+      {
+        hop_val = osm_switch_get_least_hops( p_sw, lid_ho );
+        if (hop_val > maxHops)
+          maxHops = hop_val;
+        p_updn_hist = 
+          (updn_hist_t*)cl_qmap_get( &min_hop_hist , (uint64_t)hop_val );
+        if ( p_updn_hist == (updn_hist_t*)cl_qmap_end( &min_hop_hist))
+        {
+          /* New entry in the histogram , first create it */
+          p_updn_hist = (updn_hist_t*) malloc(sizeof(updn_hist_t));
+          CL_ASSERT (p_updn_hist);
+          p_updn_hist->bar_value = 1;
+          cl_qmap_insert(&min_hop_hist, (uint64_t)hop_val, &p_updn_hist->map_item);
+          osm_log( &p_osm->log, OSM_LOG_DEBUG,
+                   "__osm_updn_find_root_nodes_by_min_hop: "
+                   "Creating new entry in histogram %u with bar value 1\n",
+                   hop_val );
+        }
+        else
+        {
+          /* Entry exist in the table , just increment the value */
+          p_updn_hist->bar_value++;
+          osm_log( &p_osm->log, OSM_LOG_DEBUG,
+                   "__osm_updn_find_root_nodes_by_min_hop: "
+                   "Updating entry in histogram %u with bar value %d\n",
+                   hop_val, p_updn_hist->bar_value );
+        }
+      }
+    }
+
+    /* Now recognize the spines by requiring one bar to be above 90% of the
+       number of CAs */
+    thd1 = numCas * 0.9;
+    thd2 = numCas * 0.05;
+    osm_log( &p_osm->log, OSM_LOG_DEBUG,
+             "__osm_updn_find_root_nodes_by_min_hop: "
+             "Pass over the histogram value and find only one root node above "
+             "thd1 = %f && thd2 = %f\n", thd1, thd2 );
+
+    p_updn_hist = (updn_hist_t*) cl_qmap_head( &min_hop_hist );
+    while( p_updn_hist != (updn_hist_t*)cl_qmap_end( &min_hop_hist ) )
+    {
+      p_up_ht = p_updn_hist;
+      p_updn_hist = (updn_hist_t*)cl_qmap_next( &p_updn_hist->map_item ) ;
+      if ( p_up_ht->bar_value > thd1 )
+        numHopBarsOverThd1++;
+      if ( p_up_ht->bar_value > thd2 )
+        numHopBarsOverThd2++;
+      osm_log( &p_osm->log, OSM_LOG_DEBUG,
+               "__osm_updn_find_root_nodes_by_min_hop: "
+               "Passing through histogram - Hop Index %u: "
+               "numHopBarsOverThd1 = %u, numHopBarsOverThd2 = %u\n",
+               (uint16_t)cl_qmap_key((cl_map_item_t*)p_up_ht),
+               numHopBarsOverThd1, numHopBarsOverThd2 );
+    }
+
+    /* destroy the qmap table and all its content - no longer needed */
+    osm_log( &p_osm->log, OSM_LOG_DEBUG,
+             "__osm_updn_find_root_nodes_by_min_hop: "
+             "Cleanup: delete histogram "
+             "UPDN - Root nodes fetching by auto detect\n" );
+    p_updn_hist = (updn_hist_t*) cl_qmap_head( &min_hop_hist );
+    while ( p_updn_hist != (updn_hist_t*)cl_qmap_end( &min_hop_hist ) )
+    {
+      cl_qmap_remove_item( &min_hop_hist, (cl_map_item_t*)p_updn_hist );
+      free( p_updn_hist );
+      p_updn_hist = (updn_hist_t*) cl_qmap_head( &min_hop_hist );
+    }
+
+    /* If thd conditions are valid insert the root node to the list */
+    if ( (numHopBarsOverThd1 == 1) && (numHopBarsOverThd2 == 1) )
+    {
+      p_guid = malloc(sizeof(uint64_t));
+      *p_guid = cl_ntoh64(osm_node_get_node_guid(p_sw->p_node));
+      osm_log( &p_osm->log, OSM_LOG_DEBUG,
+               "__osm_updn_find_root_nodes_by_min_hop: "
+               "Inserting GUID 0x%" PRIx64 " as root node\n",
+               *p_guid );
+      cl_list_insert_tail(p_root_nodes_list, p_guid);
+    }
+  }
+
+  /* destroy the map of CA lids */
+  cl_map_remove_all( &ca_by_lid_map );
+  cl_map_destroy( &ca_by_lid_map );
+
+  /* Now convert the cl_list to array */
+  __osm_updn_convert_list2array(p_updn);
+  OSM_LOG_EXIT( &p_osm->log );
+  return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_updn_delete(
+  void *context )
+{
+       updn_t *p_updn = context;
+
+       updn_destroy(p_updn);
+}
+
+int
+osm_ucast_updn_setup(
+  osm_opensm_t *p_osm )
+{
+       updn_t *p_updn;
+
+       p_updn = updn_construct(&p_osm->log);
+       if (!p_updn)
+               return -1;
+       p_osm->routing_engine.context = p_updn;
+       p_osm->routing_engine.delete = __osm_updn_delete;
+       p_osm->routing_engine.build_lid_matrices = __osm_updn_call;
+
+       if (updn_init(p_updn, p_osm) != IB_SUCCESS)
+               return -1;
+       if (!p_updn->auto_detect_root_nodes)
+               __osm_updn_convert_list2array(p_updn);
+
+       return 0;
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_vl15intf.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_vl15intf.c
new file mode 100644 (file)
index 0000000..432db64
--- /dev/null
@@ -0,0 +1,544 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_vl15intf.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_vl15_t.
+ * This object represents the VL15 Interface object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_madw.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_helper.h>
+#include <complib/cl_thread.h>
+#include <signal.h>
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_vl15_poller(
+  IN void *p_ptr )
+{
+  ib_api_status_t status;
+  osm_madw_t *p_madw;
+  uint32_t mads_sent;
+  uint32_t unicasts_sent;
+  uint32_t mads_on_wire;
+  osm_vl15_t* const p_vl = (osm_vl15_t*)p_ptr;
+  cl_qlist_t* p_fifo;
+
+  OSM_LOG_ENTER( p_vl->p_log, __osm_vl15_poller );
+
+  if ( p_vl->thread_state == OSM_THREAD_STATE_NONE)
+  {
+    p_vl->thread_state = OSM_THREAD_STATE_RUN;
+  }
+
+  while( p_vl->thread_state == OSM_THREAD_STATE_RUN )
+  {
+    /*
+      Start servicing the FIFOs by pulling off MAD wrappers
+      and passing them to the transport interface.
+      There are lots of corner cases here so tread carefully.
+
+      The unicast FIFO has priority, since somebody is waiting
+      for a timely response.
+    */
+    cl_spinlock_acquire( &p_vl->lock );
+
+    if( cl_qlist_count( &p_vl->ufifo ) != 0 )
+      p_fifo = &p_vl->ufifo;
+    else
+      p_fifo = &p_vl->rfifo;
+
+    p_madw = (osm_madw_t*)cl_qlist_remove_head( p_fifo );
+
+    cl_spinlock_release( &p_vl->lock );
+
+    if( p_madw != (osm_madw_t*)cl_qlist_end( p_fifo ) )
+    {
+      if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) )
+      {
+        osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+                 "__osm_vl15_poller: "
+                 "Servicing p_madw = %p\n", p_madw );
+      }
+
+      if( osm_log_is_active( p_vl->p_log, OSM_LOG_FRAMES ) )
+      {
+        osm_dump_dr_smp( p_vl->p_log,
+                         osm_madw_get_smp_ptr( p_madw ), OSM_LOG_FRAMES );
+      }
+
+      /*
+        Non-response-expected mads are not throttled on the wire
+        since we can have no confirmation that they arrived
+        at their destination.
+      */
+      if( p_madw->resp_expected == TRUE )
+      {
+        /*
+          Note that other threads may not see the response MAD
+          arrive before send() even returns.
+          In that case, the wire count would temporarily go negative.
+          To avoid this confusion, preincrement the counts on the
+          assumption that send() will succeed.
+        */
+        mads_on_wire = cl_atomic_inc(
+          &p_vl->p_stats->qp0_mads_outstanding_on_wire );
+        CL_ASSERT( mads_on_wire <= p_vl->max_wire_smps );
+      }
+      else
+      {
+        unicasts_sent = cl_atomic_inc(
+          &p_vl->p_stats->qp0_unicasts_sent );
+      }
+
+      mads_sent = cl_atomic_inc( &p_vl->p_stats->qp0_mads_sent );
+
+      status = osm_vendor_send(
+        osm_madw_get_bind_handle( p_madw ),
+        p_madw, p_madw->resp_expected );
+
+      if( status != IB_SUCCESS )
+      {
+        uint32_t outstanding;
+        cl_status_t cl_status;
+
+        osm_log( p_vl->p_log, OSM_LOG_ERROR,
+                 "__osm_vl15_poller: ERR 3E03: "
+                 "MAD send failed (%s)\n",
+                 ib_get_err_str( status ) );
+
+        /*
+          The MAD was never successfully sent, so
+          fix up the pre-incremented count values.
+        */
+
+        /* Decrement qp0_mads_sent and qp0_mads_outstanding_on_wire
+           that was incremented in the code above. */
+        mads_sent = cl_atomic_dec( &p_vl->p_stats->qp0_mads_sent );
+        if( p_madw->resp_expected == TRUE )
+          cl_atomic_dec( &p_vl->p_stats->qp0_mads_outstanding_on_wire );
+
+        /*
+           The following code is similar to the code in
+           __osm_sm_mad_ctrl_retire_trans_mad. We need to decrement the
+           qp0_mads_outstanding counter, and if we reached 0 - need to call
+           the cl_disp_post with OSM_SIGNAL_NO_PENDING_TRANSACTION (in order
+           to wake up the state mgr).
+           There is one difference from the code in __osm_sm_mad_ctrl_retire_trans_mad.
+           This code is called on all mads, if osm_vendor_send() failed, unlike 
+           __osm_sm_mad_ctrl_retire_trans_mad which is called only on mads where 
+           resp_expected == TRUE. As a result, the qp0_mads_outstanding counter 
+           should be decremented and handled accordingly only if this is a mad 
+           with resp_expected == TRUE.
+        */
+        if ( p_madw->resp_expected == TRUE )
+        {
+          outstanding = cl_atomic_dec( &p_vl->p_stats->qp0_mads_outstanding );
+        
+          osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+                   "__osm_vl15_poller: "
+                   "%u QP0 MADs outstanding\n",
+                   p_vl->p_stats->qp0_mads_outstanding );
+        
+          if( outstanding == 0 )
+          {
+            /*
+              The wire is clean.
+              Signal the state manager.
+            */
+            if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+                       "__osm_vl15_poller: "
+                       "Posting Dispatcher message %s\n",
+                       osm_get_disp_msg_str( OSM_MSG_NO_SMPS_OUTSTANDING ) );
+            }
+
+            cl_status = cl_disp_post( p_vl->h_disp,
+                                      OSM_MSG_NO_SMPS_OUTSTANDING,
+                                      (void *)OSM_SIGNAL_NO_PENDING_TRANSACTIONS,
+                                      NULL,
+                                      NULL );
+
+            if( cl_status != CL_SUCCESS )
+            {
+              osm_log( p_vl->p_log, OSM_LOG_ERROR,
+                       "__osm_vl15_poller: ERR 3E06: "
+                       "Dispatcher post message failed (%s)\n",
+                       CL_STATUS_MSG( cl_status ) );
+            }
+          }
+        }
+      }
+      else
+      {
+        if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) )
+        {
+          osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+                   "__osm_vl15_poller: "
+                   "%u QP0 MADs on wire, %u outstanding, %u unicasts sent, "
+                   "%u total sent\n",
+                   p_vl->p_stats->qp0_mads_outstanding_on_wire,
+                   p_vl->p_stats->qp0_mads_outstanding,
+                   p_vl->p_stats->qp0_unicasts_sent,
+                   p_vl->p_stats->qp0_mads_sent );
+        }
+      }
+    }
+    else
+    {
+      /*
+        The VL15 FIFO is empty, so we have nothing left to do.
+      */
+      status = cl_event_wait_on( &p_vl->signal,
+                                 EVENT_NO_TIMEOUT, TRUE );
+    }
+
+    while( (p_vl->p_stats->qp0_mads_outstanding_on_wire >=
+            (int32_t)p_vl->max_wire_smps ) &&
+           (p_vl->thread_state == OSM_THREAD_STATE_RUN ) )
+    {
+      status = cl_event_wait_on( &p_vl->signal,
+                                 EVENT_NO_TIMEOUT, TRUE );
+    }
+
+    if( status != CL_SUCCESS )
+    {
+      osm_log( p_vl->p_log, OSM_LOG_ERROR,
+               "__osm_vl15_poller: ERR 3E02: "
+               "Event wait failed (%s)\n",
+               CL_STATUS_MSG( status ) );
+    }
+  }
+  
+  /*
+    since we abort immediately when the state != OSM_THREAD_STATE_RUN 
+    we might have some mads on the queues. After the thread exits
+    the vl15 destroy routine should put back these mads...
+  */
+
+  OSM_LOG_EXIT( p_vl->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vl15_construct(
+  IN osm_vl15_t* const p_vl )
+{
+  memset( p_vl, 0, sizeof(*p_vl) );
+  p_vl->state = OSM_VL15_STATE_INIT;
+  p_vl->thread_state = OSM_THREAD_STATE_NONE;
+  cl_event_construct( &p_vl->signal );
+  cl_spinlock_construct( &p_vl->lock );
+  cl_qlist_init( &p_vl->rfifo );
+  cl_qlist_init( &p_vl->ufifo );
+  cl_thread_construct( &p_vl->poller );
+  p_vl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vl15_destroy(
+  IN osm_vl15_t* const p_vl,
+  IN struct _osm_mad_pool *p_pool)
+{
+  osm_madw_t* p_madw;
+
+  OSM_LOG_ENTER( p_vl->p_log, osm_vl15_destroy );
+
+  /*
+    Signal our threads that we're leaving.
+  */
+  p_vl->thread_state = OSM_THREAD_STATE_EXIT;
+
+  /*
+    Don't trigger unless event has been initialized.
+    Destroy the thread before we tear down the other objects.
+  */
+  if( p_vl->state != OSM_VL15_STATE_INIT )
+    cl_event_signal( &p_vl->signal );
+
+  cl_thread_destroy( &p_vl->poller );
+
+  /*
+    Return the outstanding messages to the pool 
+  */ 
+  
+  cl_spinlock_acquire( &p_vl->lock );
+
+  while (!cl_is_qlist_empty( &p_vl->rfifo))
+  {
+    p_madw = (osm_madw_t*)cl_qlist_remove_head( &p_vl->rfifo);
+    osm_mad_pool_put( p_pool, p_madw );
+  }
+  while (!cl_is_qlist_empty( &p_vl->ufifo))
+  {
+    p_madw = (osm_madw_t*)cl_qlist_remove_head( &p_vl->ufifo);
+    osm_mad_pool_put( p_pool, p_madw );
+  }
+
+  cl_spinlock_release( &p_vl->lock );
+
+  cl_event_destroy( &p_vl->signal );
+  p_vl->state = OSM_VL15_STATE_INIT;
+  cl_spinlock_destroy( &p_vl->lock );
+
+  OSM_LOG_EXIT( p_vl->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_vl15_init(
+  IN osm_vl15_t* const p_vl,
+  IN osm_vendor_t* const p_vend,
+  IN osm_log_t* const p_log,
+  IN osm_stats_t* const p_stats,
+  IN const int32_t max_wire_smps,
+  IN osm_subn_t* const p_subn,
+  IN cl_dispatcher_t* const p_disp,
+  IN cl_plock_t* const p_lock
+ )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_vl15_init );
+
+  p_vl->p_vend = p_vend;
+  p_vl->p_log = p_log;
+  p_vl->p_stats = p_stats;
+  p_vl->max_wire_smps = max_wire_smps;
+  p_vl->p_subn = p_subn;
+  p_vl->p_lock = p_lock;
+
+  status = cl_event_init( &p_vl->signal, FALSE );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  p_vl->state = OSM_VL15_STATE_READY;
+
+  status = cl_spinlock_init( &p_vl->lock );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  /*
+    Initialize the thread after all other dependent objects
+    have been initialized.
+  */
+  status = cl_thread_init( &p_vl->poller, __osm_vl15_poller, p_vl,
+                           "opensm poller" );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  p_vl->h_disp = cl_disp_register(
+    p_disp,
+    CL_DISP_MSGID_NONE,
+    NULL,
+    NULL );
+
+  if( p_vl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_vl15_init: ERR 3E01: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vl15_poll(
+  IN osm_vl15_t* const p_vl )
+{
+  OSM_LOG_ENTER( p_vl->p_log, osm_vl15_poll );
+
+  CL_ASSERT( p_vl->state == OSM_VL15_STATE_READY );
+
+  /*
+    If we have room for more VL15 MADs on the wire,
+    then signal the poller thread.
+
+    This is not an airtight check, since the poller thread
+    could be just about to send another MAD as we signal
+    the event here.  To cover this rare case, the poller
+    thread checks for a spurious wake-up.
+  */
+  if( p_vl->p_stats->qp0_mads_outstanding_on_wire <
+      (int32_t)p_vl->max_wire_smps )
+  {
+    if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+               "osm_vl15_poll: "
+               "Signalling poller thread\n" );
+    }
+
+    cl_event_signal( &p_vl->signal );
+  }
+
+  OSM_LOG_EXIT( p_vl->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vl15_post(
+  IN osm_vl15_t*           const p_vl,
+  IN osm_madw_t*           const p_madw )
+{
+  OSM_LOG_ENTER( p_vl->p_log, osm_vl15_post );
+
+  CL_ASSERT( p_vl->state == OSM_VL15_STATE_READY );
+
+  if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+             "osm_vl15_post: "
+             "Posting p_madw = 0x%p\n", p_madw );
+  }
+
+  /*
+    Determine in which fifo to place the pending madw.
+  */
+  cl_spinlock_acquire( &p_vl->lock );
+  if( p_madw->resp_expected == TRUE )
+  {
+    cl_qlist_insert_tail( &p_vl->rfifo, (cl_list_item_t*)p_madw );
+    cl_atomic_inc( &p_vl->p_stats->qp0_mads_outstanding );
+  }
+  else
+  {
+    cl_qlist_insert_tail( &p_vl->ufifo, (cl_list_item_t*)p_madw );
+  }
+  cl_spinlock_release( &p_vl->lock );
+
+  if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+             "osm_vl15_post: "
+             "%u QP0 MADs on wire, %u QP0 MADs outstanding\n",
+             p_vl->p_stats->qp0_mads_outstanding_on_wire,
+             p_vl->p_stats->qp0_mads_outstanding );
+  }
+
+  osm_vl15_poll( p_vl );
+
+  OSM_LOG_EXIT( p_vl->p_log );
+}
+
+void
+osm_vl15_shutdown(
+  IN osm_vl15_t* const p_vl,
+  IN osm_mad_pool_t* const p_mad_pool)
+{
+  osm_madw_t* p_madw;
+
+  OSM_LOG_ENTER( p_vl->p_log, osm_vl15_shutdown );
+
+  /* we only should get here after the VL15 interface was initialized */
+  CL_ASSERT( p_vl->state == OSM_VL15_STATE_READY );
+
+  /* grap a lock on the object */
+  cl_spinlock_acquire( &p_vl->lock );
+
+  cl_disp_unregister( p_vl->h_disp );
+
+  /* go over all outstanding MADs and retire their transactions */
+
+  /* first we handle the list of response MADs */
+  p_madw = (osm_madw_t*)cl_qlist_remove_head( &p_vl->ufifo );
+  while ( p_madw != (osm_madw_t*)cl_qlist_end( &p_vl->ufifo ) )
+  {
+    if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+               "osm_vl15_shutdown: "
+               "Releasing Response p_madw = %p\n", p_madw );
+    }
+
+    osm_mad_pool_put( p_mad_pool, p_madw );
+
+    p_madw = (osm_madw_t*)cl_qlist_remove_head( &p_vl->ufifo );
+  }
+
+  /* Request MADs we send out */
+  p_madw = (osm_madw_t*)cl_qlist_remove_head( &p_vl->rfifo );
+  while ( p_madw != (osm_madw_t*)cl_qlist_end( &p_vl->rfifo ) )
+  {
+    if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+               "osm_vl15_shutdown: "
+               "Releasing Request p_madw = %p\n", p_madw );
+    }
+
+    osm_mad_pool_put( p_mad_pool, p_madw );
+    cl_atomic_dec( &p_vl->p_stats->qp0_mads_outstanding );
+
+    p_madw = (osm_madw_t*)cl_qlist_remove_head( &p_vl->rfifo );
+  }
+
+  /* free the lock */
+  cl_spinlock_release( &p_vl->lock );
+
+  OSM_LOG_EXIT( p_vl->p_log );
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_vl_arb_rcv.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_vl_arb_rcv.c
new file mode 100644 (file)
index 0000000..07683dd
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_vl_arb_rcv.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_vla_rcv_t.
+ * This object represents the Vl Arbitration Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_vl_arb_rcv.h>
+#include <opensm/osm_node_info_rcv.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_helper.h>
+#include <vendor/osm_vendor_api.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vla_rcv_construct(
+  IN osm_vla_rcv_t* const p_rcv )
+{
+  memset( p_rcv, 0, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vla_rcv_destroy(
+  IN osm_vla_rcv_t* const p_rcv )
+{
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_vla_rcv_destroy );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_vla_rcv_init(
+  IN osm_vla_rcv_t* const p_rcv,
+  IN osm_req_t* const p_req,
+  IN osm_subn_t* const p_subn,
+  IN osm_log_t* const p_log,
+  IN cl_plock_t* const p_lock )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_vla_rcv_init );
+
+  osm_vla_rcv_construct( p_rcv );
+
+  p_rcv->p_log = p_log;
+  p_rcv->p_subn = p_subn;
+  p_rcv->p_lock = p_lock;
+  p_rcv->p_req = p_req;
+
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ * WE MIGHT ONLY RECEIVE GET or SET responses
+ */
+void
+osm_vla_rcv_process(
+  IN const osm_vla_rcv_t* const p_rcv,
+  IN osm_madw_t* const p_madw )
+{
+  cl_qmap_t *p_guid_tbl;
+  ib_vl_arb_table_t *p_vla_tbl;
+  ib_smp_t *p_smp;
+  osm_port_t *p_port;
+  osm_physp_t *p_physp;
+  osm_node_t *p_node;
+  osm_vla_context_t *p_context;
+  ib_net64_t port_guid;
+  ib_net64_t node_guid;
+  uint8_t port_num, block_num;
+
+  CL_ASSERT( p_rcv );
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_vla_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  p_smp = osm_madw_get_smp_ptr( p_madw );
+
+  p_context = osm_madw_get_vla_context_ptr( p_madw );
+  p_vla_tbl = (ib_vl_arb_table_t*)ib_smp_get_payload_ptr( p_smp );
+
+  port_guid = p_context->port_guid;
+  node_guid = p_context->node_guid;
+
+  CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_VL_ARBITRATION );
+
+  p_guid_tbl = &p_rcv->p_subn->port_guid_tbl;
+  cl_plock_excl_acquire( p_rcv->p_lock );
+  p_port = (osm_port_t*)cl_qmap_get( p_guid_tbl, port_guid );
+
+  if( p_port == (osm_port_t*)cl_qmap_end( p_guid_tbl ) )
+  {
+    cl_plock_release( p_rcv->p_lock );
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_vla_rcv_process: ERR 3F06: "
+             "No port object for port with GUID 0x%" PRIx64
+             "\n\t\t\t\tfor parent node GUID 0x%" PRIx64
+             ", TID 0x%" PRIx64 "\n",
+             cl_ntoh64( port_guid ),
+             cl_ntoh64( node_guid ),
+             cl_ntoh64( p_smp->trans_id ) );
+    goto Exit;
+  }
+
+  p_node = osm_port_get_parent_node( p_port );
+  CL_ASSERT( p_node );
+
+  block_num = (uint8_t)(cl_ntoh32(p_smp->attr_mod) >> 16);
+  /* in case of a non switch node the attr modifier should be ignored */
+  if (osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH)
+  {
+    port_num = (uint8_t)(cl_ntoh32(p_smp->attr_mod) & 0x000000FF);
+    p_physp = osm_node_get_physp_ptr( p_node, port_num );
+  }
+  else
+  {
+    p_physp = osm_port_get_default_phys_ptr(p_port);
+    port_num = p_port->default_port_num;
+  }
+
+  CL_ASSERT( p_physp );
+
+  /*
+    We do not mind if this is a result of a set or get - all we want is to update
+    the subnet.
+  */
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "osm_vla_rcv_process: "
+             "Got GetResp(VLArb) block:%u port_num %u with GUID 0x%" PRIx64
+             " for parent node GUID 0x%" PRIx64
+             ", TID 0x%" PRIx64 "\n",
+             block_num, port_num,
+             cl_ntoh64( port_guid ),
+             cl_ntoh64( node_guid ),
+             cl_ntoh64( p_smp->trans_id ) );
+  }
+
+  /*
+    Determine if we encountered a new Physical Port.
+    If so, Ignore it.
+  */
+  if( !osm_physp_is_valid( p_physp ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_vla_rcv_process: "
+             "Got invalid port number 0x%X\n",
+             port_num );
+    goto Exit;
+  }
+
+  osm_dump_vl_arb_table( p_rcv->p_log,
+                         port_guid, block_num,
+                         port_num, p_vla_tbl,
+                         OSM_LOG_DEBUG );
+
+  if ( (block_num < 1) || (block_num > 4) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_vla_rcv_process: "
+             "Got invalid block number 0x%X\n",
+             block_num );
+    goto Exit;
+  }
+  osm_physp_set_vla_tbl( p_physp, p_vla_tbl, block_num);
+
+ Exit:
+  cl_plock_release( p_rcv->p_lock );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_vl_arb_rcv_ctrl.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/osm_vl_arb_rcv_ctrl.c
new file mode 100644 (file)
index 0000000..8e8fcc9
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osm_vl_arb_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_vla_rcv_ctrl_t.
+ * This object represents the Vl Arbitration request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_vl_arb_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_vla_rcv_ctrl_disp_callback(
+  IN  void *context,
+  IN  void *p_data )
+{
+  /* ignore return status when invoked via the dispatcher */
+  osm_vla_rcv_process( ((osm_vla_rcv_ctrl_t*)context)->p_rcv,
+                       (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vla_rcv_ctrl_construct(
+  IN osm_vla_rcv_ctrl_t* const p_ctrl )
+{
+  memset( p_ctrl, 0, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vla_rcv_ctrl_destroy(
+  IN osm_vla_rcv_ctrl_t* const p_ctrl )
+{
+  CL_ASSERT( p_ctrl );
+  cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_vla_rcv_ctrl_init(
+  IN osm_vla_rcv_ctrl_t* const p_ctrl,
+  IN osm_vla_rcv_t* const p_rcv,
+  IN osm_log_t* const p_log,
+  IN cl_dispatcher_t* const p_disp )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osm_vla_rcv_ctrl_init );
+
+  osm_vla_rcv_ctrl_construct( p_ctrl );
+  p_ctrl->p_log = p_log;
+
+  p_ctrl->p_rcv = p_rcv;
+  p_ctrl->p_disp = p_disp;
+
+  p_ctrl->h_disp = cl_disp_register(
+    p_disp,
+    OSM_MSG_MAD_VL_ARB,
+    __osm_vla_rcv_ctrl_disp_callback,
+    p_ctrl );
+
+  if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osm_vla_rcv_ctrl_init: ERR 4001: "
+             "Dispatcher registration failed\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/st.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/opensm/st.c
new file mode 100644 (file)
index 0000000..0597b9e
--- /dev/null
@@ -0,0 +1,625 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: st.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/* static   char  sccsid[] = "@(#) st.c 5.1 89/12/14 Crucible"; */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <string.h>
+#include <opensm/st.h>
+
+#ifdef _WIN32
+#include <malloc.h>
+#endif
+
+typedef struct st_table_entry st_table_entry;
+
+struct st_table_entry {
+  unsigned int hash;
+  st_data_t key;
+  st_data_t record;
+  st_table_entry *next;
+};
+
+#define ST_DEFAULT_MAX_DENSITY 5
+#define ST_DEFAULT_INIT_TABLE_SIZE 11
+
+/*
+ * DEFAULT_MAX_DENSITY is the default for the largest we allow the
+ * average number of items per bin before increasing the number of
+ * bins
+ *
+ * DEFAULT_INIT_TABLE_SIZE is the default for the number of bins
+ * allocated initially
+ *
+ */
+static int numcmp(void *, void *);
+static st_ptr_t numhash(void *);
+static struct st_hash_type type_numhash = {
+  numcmp,
+  numhash,
+};
+
+
+/* extern int strcmp(const char *, const char *); */ 
+static int strhash(const char *);
+
+static inline st_ptr_t st_strhash(void *key)
+{
+  return strhash((const char *)key);
+}
+
+static inline int st_strcmp(void *key1, void *key2)
+{
+   return strcmp((const char *)key1, (const char *)key2); 
+}
+     
+static struct st_hash_type type_strhash = {
+  st_strcmp,
+  st_strhash
+};
+
+
+#define xmalloc  malloc
+#define xcalloc  calloc
+#define xrealloc realloc
+#define xfree    free
+
+static void rehash(st_table *);
+
+#define alloc(type) (type*)xmalloc(sizeof(type))
+#define Calloc(n,s) (char*)xcalloc((n), (s))
+
+#define EQUAL(table,x,y) ((x)==(y) || (*table->type->compare)(((void*)x),((void *)y)) == 0)
+
+#define do_hash(key,table) (unsigned int)(*(table)->type->hash)(((void*)key))
+#define do_hash_bin(key,table) (do_hash(key, table)%(table)->num_bins)
+
+/*
+ * MINSIZE is the minimum size of a dictionary.
+ */
+
+#define MINSIZE 8
+
+/*
+  Table of prime numbers 2^n+a, 2<=n<=30.
+*/
+static long primes[] = {
+  8 + 3,
+  16 + 3,
+  32 + 5,
+  64 + 3,
+  128 + 3,
+  256 + 27,
+  512 + 9,
+  1024 + 9,
+  2048 + 5,
+  4096 + 3,
+  8192 + 27,
+  16384 + 43,
+  32768 + 3,
+  65536 + 45,
+  131072 + 29,
+  262144 + 3,
+  524288 + 21,
+  1048576 + 7,
+  2097152 + 17,
+  4194304 + 15,
+  8388608 + 9,
+  16777216 + 43,
+  33554432 + 35,
+  67108864 + 15,
+  134217728 + 29,
+  268435456 + 3,
+  536870912 + 11,
+  1073741824 + 85,
+  0
+};
+
+static int
+new_size(int size)
+{
+  int i;
+
+#if 0
+  for (i=3; i<31; i++) {
+    if ((1<<i) > size) return 1<<i;
+  }
+  return -1;
+#else
+  int newsize;
+
+  for (i = 0, newsize = MINSIZE;
+       i < sizeof(primes)/sizeof(primes[0]);
+       i++, newsize <<= 1)
+  {
+    if (newsize > size) return primes[i];
+  }
+  /* Ran out of polynomials */
+  return -1;         /* should raise exception */
+#endif
+}
+
+#ifdef HASH_LOG
+static int collision = 0;
+static int init_st = 0;
+
+static void
+stat_col()
+{
+  FILE *f = fopen("/var/log/osm_st_col", "w");
+  fprintf(f, "collision: %d\n", collision);
+  fclose(f);
+}
+#endif
+
+st_table*
+st_init_table_with_size(type, size)
+     struct st_hash_type *type;
+     size_t size;
+{
+  st_table *tbl;
+
+#ifdef HASH_LOG
+  if (init_st == 0)
+  {
+    init_st = 1;
+    atexit(stat_col);
+  }
+#endif
+
+  size = new_size(size);   /* round up to prime number */
+
+  tbl = alloc(st_table);
+  tbl->type = type;
+  tbl->num_entries = 0;
+  tbl->num_bins = size;
+  tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*));
+
+  return tbl;
+}
+
+st_table*
+st_init_table(type)
+     struct st_hash_type *type;
+{
+  return st_init_table_with_size(type, 0);
+}
+
+st_table*
+st_init_numtable(void)
+{
+  return st_init_table(&type_numhash);
+}
+
+st_table*
+st_init_numtable_with_size(size)
+     size_t size;
+{
+  return st_init_table_with_size(&type_numhash, size);
+}
+
+st_table*
+st_init_strtable(void)
+{
+  return st_init_table(&type_strhash);
+}
+
+st_table*
+st_init_strtable_with_size(size)
+     size_t size;
+{
+  return st_init_table_with_size(&type_strhash, size);
+}
+
+void
+st_free_table(table)
+     st_table *table;
+{
+  register st_table_entry *ptr, *next;
+  int i;
+
+  for (i = 0; i < table->num_bins; i++) {
+    ptr = table->bins[i];
+    while (ptr != 0) {
+      next = ptr->next;
+      free(ptr);
+      ptr = next;
+    }
+  }
+  free(table->bins);
+  free(table);
+}
+
+#define PTR_NOT_EQUAL(table, ptr, hash_val, key) \
+((ptr) != 0 && (ptr->hash != (hash_val) || !EQUAL((table), (key), (ptr)->key)))
+
+#ifdef HASH_LOG
+#define COLLISION collision++
+#else
+#define COLLISION
+#endif
+
+#define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\
+    bin_pos = hash_val%(table)->num_bins;\
+    ptr = (table)->bins[bin_pos];\
+    if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) \
+    {\
+      COLLISION;\
+      while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) {\
+      ptr = ptr->next;\
+    }\
+    ptr = ptr->next;\
+  }\
+} while (0)
+
+int
+st_lookup(table, key, value)
+     st_table *table;
+     register st_data_t key;
+     st_data_t *value;
+{
+  unsigned int hash_val, bin_pos;
+  register st_table_entry *ptr;
+
+  hash_val = do_hash(key, table);
+  FIND_ENTRY(table, ptr, hash_val, bin_pos);
+
+  if (ptr == 0)
+  {
+    return 0;
+  }
+  else
+  {
+    if (value != 0)
+      *value = ptr->record;
+    return 1;
+  }
+}
+
+#define ADD_DIRECT(table, key, value, hash_val, bin_pos)\
+do {\
+  st_table_entry *entry;\
+  if (table->num_entries/(table->num_bins) > ST_DEFAULT_MAX_DENSITY) \
+  {\
+    rehash(table);\
+    bin_pos = hash_val % table->num_bins;\
+  }\
+  \
+  entry = alloc(st_table_entry);\
+  \
+  entry->hash = hash_val;\
+  entry->key = key;\
+  entry->record = value;\
+  entry->next = table->bins[bin_pos];\
+  table->bins[bin_pos] = entry;\
+  table->num_entries++;\
+} while (0);
+
+
+int
+st_insert(table, key, value)
+     register st_table *table;
+     register st_data_t key;
+     st_data_t value;
+{
+  unsigned int hash_val, bin_pos;
+  register st_table_entry *ptr;
+
+  hash_val = do_hash(key, table);
+  FIND_ENTRY(table, ptr, hash_val, bin_pos);
+
+  if (ptr == 0)
+  {
+    ADD_DIRECT(table, key, value, hash_val, bin_pos);
+    return 0;
+  }
+  else
+  {
+    ptr->record = value;
+    return 1;
+  }
+}
+
+void
+st_add_direct(table, key, value)
+     st_table *table;
+     st_data_t key;
+     st_data_t value;
+{
+  unsigned int hash_val, bin_pos;
+
+  hash_val = do_hash(key, table);
+  bin_pos = hash_val % table->num_bins;
+  ADD_DIRECT(table, key, value, hash_val, bin_pos);
+}
+
+static void
+rehash(table)
+     register st_table *table;
+{
+  register st_table_entry *ptr, *next, **new_bins;
+  int i, old_num_bins = table->num_bins, new_num_bins;
+  unsigned int hash_val;
+
+  new_num_bins = new_size(old_num_bins+1);
+  new_bins = (st_table_entry**)Calloc(new_num_bins, sizeof(st_table_entry*));
+
+  for (i = 0; i < old_num_bins; i++) {
+    ptr = table->bins[i];
+    while (ptr != 0) {
+      next = ptr->next;
+      hash_val = ptr->hash % new_num_bins;
+      ptr->next = new_bins[hash_val];
+      new_bins[hash_val] = ptr;
+      ptr = next;
+    }
+  }
+  free(table->bins);
+  table->num_bins = new_num_bins;
+  table->bins = new_bins;
+}
+
+st_table*
+st_copy(old_table)
+     st_table *old_table;
+{
+  st_table *new_table;
+  st_table_entry *ptr, *entry;
+  size_t i, num_bins = old_table->num_bins;
+
+  new_table = alloc(st_table);
+  if (new_table == 0)
+  {
+    return 0;
+  }
+
+  *new_table = *old_table;
+  new_table->bins = (st_table_entry**)
+    Calloc(num_bins, sizeof(st_table_entry*));
+
+  if (new_table->bins == 0)
+  {
+    free(new_table);
+    return 0;
+  }
+
+  for (i = 0; i < num_bins; i++) {
+    new_table->bins[i] = 0;
+    ptr = old_table->bins[i];
+    while (ptr != 0) {
+      entry = alloc(st_table_entry);
+      if (entry == 0)
+      {
+        free(new_table->bins);
+        free(new_table);
+        return 0;
+      }
+      *entry = *ptr;
+      entry->next = new_table->bins[i];
+      new_table->bins[i] = entry;
+      ptr = ptr->next;
+    }
+  }
+  return new_table;
+}
+
+int
+st_delete(table, key, value)
+     register st_table *table;
+     register st_data_t *key;
+     st_data_t *value;
+{
+  unsigned int hash_val;
+  st_table_entry *tmp;
+  register st_table_entry *ptr;
+
+  hash_val = do_hash_bin(*key, table);
+  ptr = table->bins[hash_val];
+
+  if (ptr == 0)
+  {
+    if (value != 0) *value = 0;
+    return 0;
+  }
+
+  if (EQUAL(table, *key, ptr->key))
+  {
+    table->bins[hash_val] = ptr->next;
+    table->num_entries--;
+    if (value != 0) *value = ptr->record;
+    *key = ptr->key;
+    free(ptr);
+    return 1;
+  }
+
+  for (; ptr->next != 0; ptr = ptr->next) {
+    if (EQUAL(table, ptr->next->key, *key))
+    {
+      tmp = ptr->next;
+      ptr->next = ptr->next->next;
+      table->num_entries--;
+      if (value != 0) *value = tmp->record;
+      *key = tmp->key;
+      free(tmp);
+      return 1;
+    }
+  }
+
+  return 0;
+}
+
+int
+st_delete_safe(table, key, value, never)
+     register st_table *table;
+     register st_data_t *key;
+     st_data_t *value;
+     st_data_t never;
+{
+  unsigned int hash_val;
+  register st_table_entry *ptr;
+
+  hash_val = do_hash_bin(*key, table);
+  ptr = table->bins[hash_val];
+
+  if (ptr == 0)
+  {
+    if (value != 0) *value = 0;
+    return 0;
+  }
+
+  for (; ptr != 0; ptr = ptr->next) {
+    if ((ptr->key != never) && EQUAL(table, ptr->key, *key))
+    {
+      table->num_entries--;
+      *key = ptr->key;
+      if (value != 0) *value = ptr->record;
+      ptr->key = ptr->record = never;
+      return 1;
+    }
+  }
+
+  return 0;
+}
+
+static int
+delete_never(st_data_t key, st_data_t value, st_data_t never)
+{
+  if (value == never) return ST_DELETE;
+  return ST_CONTINUE;
+}
+
+void
+st_cleanup_safe(table, never)
+     st_table *table;
+     st_data_t never;
+{
+  int num_entries = table->num_entries;
+
+  st_foreach(table, delete_never, never);
+  table->num_entries = num_entries;
+}
+
+void
+st_foreach(table, func, arg)
+     st_table *table;
+     int (*func)(st_data_t key, st_data_t val, st_data_t arg);
+     st_data_t arg;
+{
+  st_table_entry *ptr, *last, *tmp;
+  enum st_retval retval;
+  int i;
+
+  for (i = 0; i < table->num_bins; i++) {
+    last = 0;
+    for (ptr = table->bins[i]; ptr != 0;) {
+      retval = (*func)(ptr->key, ptr->record, arg);
+      switch (retval) {
+      case ST_CONTINUE:
+        last = ptr;
+        ptr = ptr->next;
+        break;
+      case ST_STOP:
+        return;
+      case ST_DELETE:
+        tmp = ptr;
+        if (last == 0)
+        {
+          table->bins[i] = ptr->next;
+        }
+        else
+        {
+          last->next = ptr->next;
+        }
+        ptr = ptr->next;
+        free(tmp);
+        table->num_entries--;
+      }
+    }
+  }
+}
+
+static int
+strhash(string)
+     register const char *string;
+{
+  register int c;
+
+#ifdef HASH_ELFHASH
+  register unsigned int h = 0, g;
+
+  while ((c = *string++) != '\0') {
+    h = ( h << 4 ) + c;
+    if ( g = h & 0xF0000000 )
+      h ^= g >> 24;
+    h &= ~g;
+  }
+  return h;
+#elif HASH_PERL
+  register int val = 0;
+
+  while ((c = *string++) != '\0') {
+    val = val*33 + c;
+  }
+
+  return val + (val>>5);
+#else
+  register int val = 0;
+
+  while ((c = *string++) != '\0') {
+    val = val*997 + c;
+  }
+
+  return val + (val>>5);
+#endif
+}
+
+static int
+numcmp(x, y)
+     void *x, *y;
+{
+  return (st_ptr_t)x != (st_ptr_t)y;
+}
+
+static st_ptr_t
+numhash(n)
+     void *n;
+{
+  return (st_ptr_t)n;
+}
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/Makefile b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/Makefile
new file mode 100644 (file)
index 0000000..9c985f5
--- /dev/null
@@ -0,0 +1,7 @@
+#\r
+# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source\r
+# file to this component.  This file merely indirects to the real make file\r
+# that is shared by all the driver components of the Windows NT DDK\r
+#\r
+\r
+!INCLUDE $(NTMAKEENV)\makefile.def\r
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/SOURCES b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/SOURCES
new file mode 100644 (file)
index 0000000..3206e1e
--- /dev/null
@@ -0,0 +1,69 @@
+!if $(FREEBUILD)\r
+TARGETNAME=osmtest\r
+!else\r
+TARGETNAME=osmtestd\r
+!endif\r
+\r
+!if !defined(WINIBHOME)\r
+WINIBHOME=..\..\..\..\r
+!endif\r
+\r
+LIBPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)\r
+\r
+!if defined(OSM_TARGET)\r
+TARGETPATH=$(OSM_TARGET)\bin\user\obj$(BUILD_ALT_DIR)\r
+!else\r
+TARGETPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)\r
+!endif\r
+\r
+TARGETTYPE=PROGRAM\r
+UMTYPE=console\r
+USE_MSVCRT=1\r
+OVR_DIR=..\addon\r
+\r
+\r
+SOURCES=\\r
+       osmt_slvl_vl_arb.c \\r
+       osmt_service.c \\r
+       osmt_multicast.c \\r
+       osmt_inform.c \\r
+       osmtest.c \\r
+       main.c \r
+\r
+OSM_HOME=..\r
+\r
+TARGETLIBS=\\r
+!if $(FREEBUILD)\r
+                       $(LIBPATH)\*\ibal.lib \\r
+                       $(LIBPATH)\*\complib.lib \\r
+                       $(TARGETPATH)\*\osmv_ibal.lib \\r
+                       $(TARGETPATH)\*\opensm_ibal.lib\r
+\r
+!else\r
+                       $(LIBPATH)\*\ibald.lib \\r
+                       $(LIBPATH)\*\complibd.lib \\r
+                       $(TARGETPATH)\*\osmv_ibald.lib \\r
+                       $(TARGETPATH)\*\opensm_ibald.lib\r
+!endif\r
+\r
+#DO NOT TOUCH the order of search path , until ib_types.h merging process will be done\r
+INCLUDES= \\r
+   $(OSM_HOME)\osmtest\include; \\r
+       $(OSM_HOME)\include; \\r
+       $(OSM_HOME); \\r
+       $(WINIBHOME)\inc; \\r
+       $(WINIBHOME)\inc\user;\r
+\r
+# Could be any special flag needed for this project \r
+USER_C_FLAGS=$(USER_C_FLAGS) /MD\r
+#Add preproccessor definitions\r
+C_DEFINES=$(C_DEFINES) -DWIN32 -D__WIN__ -D__i386__ -Dinline=__inline -DMT_LITTLE_ENDIAN -DOSM_VENDOR_INTF_AL\r
+C_DEFINES=$(C_DEFINES) -I.. -DHAVE_CONFIG_H\r
+!if !$(FREEBUILD)\r
+#C_DEFINES=$(C_DEFINES) -D_DEBUG -DDEBUG -DDBG\r
+C_DEFINES=$(C_DEFINES) \r
+!endif\r
+\r
+LINKER_FLAGS= $(LINKER_FLAGS)\r
+MSC_WARNING_LEVEL= /W3\r
+\r
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/error.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/error.h
new file mode 100644 (file)
index 0000000..16e438e
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: error.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of error code ranges for the various osmtest modules.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+
+/*
+       osmtest object
+       0x0100 - 0x01FF
+
+       parser object
+       0x0200 - 0x02FF
+
+       osmtest object
+       0x0300 - 0x03FF
+
+*/
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmt_inform.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmt_inform.h
new file mode 100644 (file)
index 0000000..1f432d8
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osmt_inform.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef __OSMT_INFORM__
+#define __OSMT_INFORM__
+
+#ifdef OSM_VENDOR_INTF_MTL
+#include <vendor/osm_vendor_mlx_inout.h>
+#include <ib_mgt.h>
+#include "osmt_mtl_regular_qp.h"
+#endif
+
+typedef struct _osmt_qp_ctx
+{
+#ifdef OSM_VENDOR_INTF_MTL
+  osmt_mtl_mad_res_t qp_bind_hndl;
+#endif
+  uint8_t *p_send_buf;
+  uint8_t *p_recv_buf;
+#ifdef OSM_VENDOR_INTF_MTL
+  IB_MGT_mad_hndl_t ib_mgt_qp0_handle; 
+#endif
+}
+osmt_qp_ctx_t;
+
+ib_api_status_t
+osmt_bind_inform_qp( IN osmtest_t * const p_osmt,
+                                                       OUT osmt_qp_ctx_t *p_qp_ctx);
+
+void
+osmt_unbind_inform_qp( IN osmtest_t * const p_osmt,
+                                                         IN osmt_qp_ctx_t *p_qp_ctx);
+
+
+ib_api_status_t
+osmt_reg_unreg_inform_info( IN osmtest_t         *p_osmt,
+                                                                        IN osmt_qp_ctx_t     *p_qp_ctx,
+                                                                        IN ib_inform_info_t     *p_inform_info,
+                                                                        IN uint8_t           reg_flag
+                                                                        );
+
+ib_api_status_t
+osmt_trap_wait( IN osmtest_t * const    p_osmt,
+                IN osmt_qp_ctx_t        *p_qp_ctx
+                );
+
+ib_api_status_t
+osmt_init_inform_info(IN osmtest_t * const p_osmt,
+                                                        OUT ib_inform_info_t* p_ii);
+
+ib_api_status_t
+osmt_init_inform_info_by_trap (IN osmtest_t * const p_osmt,
+                              IN ib_net16_t trap_num,
+                              OUT ib_inform_info_t* p_ii);
+
+#endif /* __OSMT_INFORM__ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmt_mtl_regular_qp.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmt_mtl_regular_qp.h
new file mode 100644 (file)
index 0000000..787619a
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osmt_mtl_regular_qp.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ *    mad.h -
+ *      Header file for common special QP resources creation code.
+ *
+ *  Creation date:
+ *
+ *  Version: osmt_mtl_regular_qp.h,v 1.2 2003/03/20 16:05:10 eitan
+ *
+ *  Authors:
+ *    Elazar Raab
+ * 
+ *  Changes:
+ */           
+
+#ifndef H_MAD_H
+#define H_MAD_H
+
+#include <vapi.h>
+#include <evapi.h>
+#include <vapi_common.h>
+#include <ib_defs.h>
+
+
+#if defined(MAD_IN) || defined(MAD_OUT)
+#error MACROS MAD_IN and MAD_OUT are in use, do not override 
+#endif
+#define MAD_IN
+#define MAD_OUT
+   
+
+
+/* HCA Constants */
+#define HCA_ID     "mt21108_pci0" 
+#define GRH_LEN 40
+#define KNOWN_QP1_QKEY 0x80010000
+
+
+#define MAX_OUTS_SQ   2    /* Max. buffers posted for requests in SQ */
+#define MAX_OUTS_RQ   5    /* Max. buffers posted for responses in RQ */
+
+#define MAX_POLL_CNT    300
+#define POLL_SLEEP      1 /* for usleep */
+
+#define MAD_SIZE               256  /* MADs are always 256B */
+#define MAD_ATTR_OFFSET 16
+#define MAD_TID_OFFSET  8
+
+
+
+
+/* Verbs SQP resources handles */
+typedef struct {
+  VAPI_hca_id_t       hca_id;                   /*id of HCA*/             
+  u_int8_t            port_num;                 /* the port num to use */
+  VAPI_hca_hndl_t     hca_hndl;                 /*handle of HCA*/
+  VAPI_qp_hndl_t      qp_hndl;                  /*handle of QP I use*/
+  VAPI_mr_hndl_t      mr_hndl;                  /*handle of memory region*/
+  VAPI_cq_hndl_t      rq_cq_hndl, sq_cq_hndl;  /*handle of send & receive completion Queues*/
+  VAPI_pd_hndl_t      pd_hndl;                 /*handle of Partition Domain*/
+ /* VAPI_ud_av_hndl_t   av_hndl;*/
+  IB_lid_t            slid;                   /*LID*/ 
+  void               *buf_ptr;                /*mem buffer for outstanding pkts*/ 
+  MT_size_t           buf_size;               /*size of mem buffer for outstanding pkts*/
+  
+  u_int32_t           max_outs_sq;            /*max # of outstanding pkts in send queue*/ 
+  u_int32_t           max_outs_rq;            /*max # of outstanding pkts in receive queue*/ 
+
+  IB_rkey_t           l_key;                /*my l_key for memory regions*/
+  VAPI_qkey_t         qkey;                 /*my qkey*/
+
+  EVAPI_compl_handler_hndl_t  rq_cq_eventh, sq_cq_eventh; /* event handlers for polling */
+  
+  bool is_sqp;                              /* relate to union below - my QP*/
+  union {
+    VAPI_special_qp_t sqp_type;
+    VAPI_qp_num_t     qp_num;
+  } qp_id;
+   void               *wait_q;
+} osmt_mtl_mad_res_t;
+
+
+/* init an osmt_mtl_mad_res_t with all resources initialized (use functions below) */
+VAPI_ret_t osmt_mtl_init(
+      osmt_mtl_mad_res_t* res          /*pointer to res (resources) struct*/
+    ); 
+VAPI_ret_t osmt_mtl_init_opened_hca(
+      osmt_mtl_mad_res_t* res          /*pointer to res (resources) struct*/
+    ); 
+
+/* Cleanup all resources of (which are valid) in res */
+VAPI_ret_t osmt_mtl_mad_cleanup(
+    osmt_mtl_mad_res_t *res          /*pointer to res (resources) struct*/
+    );
+
+
+/* create CQs and QP as given in res->is_sqp (if TRUE, get special QP) */
+VAPI_ret_t osmt_mtl_get_qp_resources(
+    osmt_mtl_mad_res_t *res         /*pointer to res (resources) struct*/
+);
+
+
+/* move QP to RTS state */
+VAPI_ret_t osmt_mtl_mad_qp_init(
+    osmt_mtl_mad_res_t *res          /*max number of outstanding packets allowed in send queue*/
+ );
+
+
+/* create and register res->buf_ptr */
+VAPI_ret_t  osmt_mtl_mad_create_mr(
+    osmt_mtl_mad_res_t *res         /*pointer to res (resources) struct*/
+ );
+
+VAPI_ret_t osmt_mtl_create_av(
+        osmt_mtl_mad_res_t* res,  /* pointer to res (resources) struct*/
+    int16_t dlid,              /*destination lid */
+    VAPI_ud_av_hndl_t *avh_p  /* address vectr handle to update */
+);
+
+/* Send MAD to given dest QP*/
+VAPI_ret_t osmt_mtl_mad_send(
+    osmt_mtl_mad_res_t* res,         /*pointer to res (resources) struct*/
+    VAPI_wr_id_t id,        /*wqe ID*/
+    void* mad,              /*mad buffer to send*/
+    VAPI_qp_num_t dest_qp,  /*destination QP*/
+    IB_sl_t sl,             /*Service Level*/
+    u_int32_t dest_qkey,     /*Destination QP KEY*/
+        VAPI_ud_av_hndl_t avh   /* address vectr handle to use */
+);   
+
+
+/* post buffers to RQ. returns num of buffers actually posted */
+int osmt_mtl_mad_post_recv_bufs(
+    osmt_mtl_mad_res_t* res,          /*pointer to res (resources) struct*/
+    void *buf_array,         /*array of receive buffers*/
+    u_int32_t num_o_bufs,    /*number of receive buffers*/
+    u_int32_t size,          /* size of expected receive packet - MAD*/
+    VAPI_wr_id_t start_id    /* start id for receive buffers*/
+);
+
+
+/* Poll given CQ for completion max_poll times (POLL_SLEEP [usec] delays). result in wc_desc_p. */
+VAPI_ret_t osmt_mtl_mad_poll4cqe(
+    VAPI_hca_hndl_t hca,        /*handle for HCA*/
+    VAPI_cq_hndl_t cq,          /*handle for Completion Queue - Rcv/Send  */ 
+    VAPI_wc_desc_t *wc_desc_p,  /*handle of cqe */                  
+    u_int32_t max_poll,         /*number of polling iterations*/
+    u_int32_t poll_sleep,        /*timeout for each polling    */
+        VAPI_ud_av_hndl_t *avh_p   /* address vectopr handle to cleanup */
+        );
+
+
+#endif
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmtest.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmtest.h
new file mode 100644 (file)
index 0000000..d4c74e8
--- /dev/null
@@ -0,0 +1,517 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osmtest.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Declaration of osmtest_t.
+ * This object represents the OSMTest Test object.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#ifndef _OSMTEST_H_
+#define _OSMTEST_H_
+
+#include <complib/cl_qmap.h>
+#include <opensm/osm_log.h>
+#include <vendor/osm_vendor_api.h>
+#include <vendor/osm_vendor_sa_api.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_helper.h>
+#include "osmtest_base.h"
+#include "osmtest_subnet.h"
+
+/****s* OpenSM: Subnet/osmtest_opt_t
+ * NAME
+ * osmtest_opt_t
+ *
+ * DESCRIPTION
+ * Subnet options structure.  This structure contains the various
+ * site specific configuration parameters for osmtest.
+ *
+ * SYNOPSIS
+ */
+typedef struct _osmtest_opt
+{
+  uint32_t transaction_timeout;
+  boolean_t force_log_flush;
+  boolean_t create;
+  uint32_t retry_count;
+  uint32_t stress;
+  uint32_t mmode;
+  char file_name[OSMTEST_FILE_PATH_MAX];
+  uint8_t flow;
+  uint8_t wait_time;
+  char *log_file;
+  boolean_t ignore_path_records;
+} osmtest_opt_t;
+
+/*
+ * FIELDS
+ *
+ * SEE ALSO
+ *********/
+
+/****h* OSMTest/OSMTest
+ * NAME
+ * OSMTest
+ *
+ * DESCRIPTION
+ * The OSMTest object tests an SM/SA for conformance to a known
+ * set of data about an Infiniband subnet.
+ *
+ * AUTHOR
+ * Steve King, Intel
+ *
+ *********/
+
+
+/****s* OSMTest/osmtest_t
+ * NAME
+ * osmtest_t
+ *
+ * DESCRIPTION
+ * OSMTest structure.
+ *
+ * This object should be treated as opaque and should
+ * be manipulated only through the provided functions.
+ *
+ * SYNOPSIS
+ */
+typedef struct _osmtest
+{
+  osm_log_t           log;
+  struct _osm_vendor *p_vendor;
+  osm_bind_handle_t   h_bind;
+  osm_mad_pool_t      mad_pool;
+
+  osmtest_opt_t       opt;
+  ib_port_attr_t      local_port;
+  subnet_t            exp_subn;
+  cl_qpool_t          node_pool;
+  cl_qpool_t          port_pool;
+  cl_qpool_t          link_pool;
+
+  uint16_t            max_lid;
+} osmtest_t;
+
+/*
+ * FIELDS
+ * log
+ *    Log facility used by all OSMTest components.
+ *
+ * p_vendor
+ *    Pointer to the vendor transport layer.
+ *
+ *  h_bind
+ *     The bind handle obtained by osm_vendor_sa_api/osmv_bind_sa
+ *
+ *  mad_pool
+ *     The mad pool provided for teh vendor layer to allocate mad wrappers in
+ *
+ * opt
+ *    osmtest options structure
+ *
+ * local_port
+ *    Port attributes for the port over which osmtest is running.
+ *
+ * exp_subn
+ *    Subnet object representing the expected subnet
+ *
+ * node_pool
+ *    Pool of objects for use in populating the subnet databases.
+ *
+ * port_pool
+ *    Pool of objects for use in populating the subnet databases.
+ *
+ * link_pool
+ *    Pool of objects for use in populating the subnet databases.
+ *
+ * SEE ALSO
+ *********/
+
+/****s* OpenSM: Subnet/osmtest_req_context_t
+ * NAME
+ * osmtest_req_context_t
+ *
+ * DESCRIPTION
+ * Query context for ib_query callback function.
+ *
+ * SYNOPSIS
+ */
+typedef struct _osmtest_req_context
+{
+  osmtest_t *p_osmt;
+  osmv_query_res_t result;
+} osmtest_req_context_t;
+
+typedef struct _osmtest_mgrp_t
+{
+  cl_map_item_t                                map_item;
+  ib_member_rec_t                              mcmember_rec;
+} osmtest_mgrp_t;
+
+
+/*
+ * FIELDS
+ *
+ * SEE ALSO
+ *********/
+
+/****f* OSMTest/osmtest_construct
+ * NAME
+ * osmtest_construct
+ *
+ * DESCRIPTION
+ * This function constructs an OSMTest object.
+ *
+ * SYNOPSIS
+ */
+void osmtest_construct( IN osmtest_t * const p_osmt );
+
+/*
+ * PARAMETERS
+ * p_osmt
+ *    [in] Pointer to a OSMTest object to construct.
+ *
+ * RETURN VALUE
+ * This function does not return a value.
+ *
+ * NOTES
+ * Allows calling osmtest_init, osmtest_destroy.
+ *
+ * Calling osmtest_construct is a prerequisite to calling any other
+ * method except osmtest_init.
+ *
+ * SEE ALSO
+ * SM object, osmtest_init, osmtest_destroy
+ *********/
+
+/****f* OSMTest/osmtest_destroy
+ * NAME
+ * osmtest_destroy
+ *
+ * DESCRIPTION
+ * The osmtest_destroy function destroys an osmtest object, releasing
+ * all resources.
+ *
+ * SYNOPSIS
+ */
+void osmtest_destroy( IN osmtest_t * const p_osmt );
+
+/*
+ * PARAMETERS
+ * p_osmt
+ *    [in] Pointer to a OSMTest object to destroy.
+ *
+ * RETURN VALUE
+ * This function does not return a value.
+ *
+ * NOTES
+ * Performs any necessary cleanup of the specified OSMTest object.
+ * Further operations should not be attempted on the destroyed object.
+ * This function should only be called after a call to osmtest_construct or
+ * osmtest_init.
+ *
+ * SEE ALSO
+ * SM object, osmtest_construct, osmtest_init
+ *********/
+
+/****f* OSMTest/osmtest_init
+ * NAME
+ * osmtest_init
+ *
+ * DESCRIPTION
+ * The osmtest_init function initializes a OSMTest object for use.
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t osmtest_init( IN osmtest_t * const p_osmt,
+                              IN const osmtest_opt_t * const p_opt,
+                              IN const osm_log_level_t log_flags
+                              );
+
+/*
+ * PARAMETERS
+ * p_osmt
+ *    [in] Pointer to an osmtest_t object to initialize.
+ *
+ * p_opt
+ *    [in] Pointer to the options structure.
+ *
+ * log_flags
+ *    [in] Log level flags to set.
+ *
+ * RETURN VALUES
+ * IB_SUCCESS if the OSMTest object was initialized successfully.
+ *
+ * NOTES
+ * Allows calling other OSMTest methods.
+ *
+ * SEE ALSO
+ * SM object, osmtest_construct, osmtest_destroy
+ *********/
+
+/****f* OSMTest/osmtest_run
+ * NAME
+ * osmtest_run
+ *
+ * DESCRIPTION
+ * Runs the osmtest suite.
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t osmtest_run( IN osmtest_t * const p_osmt );
+
+/*
+ * PARAMETERS
+ * p_osmt
+ *    [in] Pointer to an osmtest_t object.
+ *
+ * guid
+ *    [in] Port GUID over which to run the test suite.
+ *
+ * RETURN VALUES
+ * IB_SUCCESS
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* OSMTest/osmtest_bind
+ * NAME
+ * osmtest_bind
+ *
+ * DESCRIPTION
+ * Binds osmtest to a local port.
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t osmtest_bind( IN osmtest_t * p_osmt,
+                              IN uint16_t max_lid,
+                              IN ib_net64_t guid OPTIONAL );
+
+/*
+ * PARAMETERS
+ * p_osmt
+ *    [in] Pointer to an osmtest_t object.
+ *
+ *  max_lid
+ *     [in] The maximal lid to query about (if RMPP is not supported)
+ *
+ * guid
+ *    [in] Port GUID over which to run the test suite.
+ *    If zero, the bind function will display a menu of local
+ *    port guids and wait for user input.
+ *
+ * RETURN VALUES
+ * IB_SUCCESS
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* OSMTest/osmtest_query_res_cb
+ * NAME
+ * osmtest_query_res_cb
+ *
+ * DESCRIPTION
+ * A Callback for the query to invoke on completion
+ *
+ * SYNOPSIS
+ */
+void
+osmtest_query_res_cb( IN osmv_query_res_t * p_rec );
+/*
+ * PARAMETERS
+ * p_rec
+ *    [in] Pointer to an ib_query_rec_t object used for the query.
+ *
+ * RETURN VALUES
+ * NONE
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* OSMTest/ib_get_mad_status_str
+ * NAME
+ * ib_get_mad_status_str
+ *
+ * DESCRIPTION
+ * return the string representing the given  mad status
+ *
+ * SYNOPSIS
+ */
+const char *
+ib_get_mad_status_str( IN const ib_mad_t * const p_mad );
+/*
+ * PARAMETERS
+ * p_mad
+ *    [in] Pointer to the mad payload
+ *
+ * RETURN VALUES
+ * NONE
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* OSMTest/osmt_run_service_records_flow
+ * NAME
+ * osmt_run_service_records_flow
+ *
+ * DESCRIPTION
+ * Run the service record testing flow.
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t osmt_run_service_records_flow( IN osmtest_t * const p_osmt );
+/*
+ * PARAMETERS
+ *  p_osmt
+ *    [in] Pointer to the osmtest obj
+ *
+ * RETURN VALUES
+ * IB_SUCCESS if PASS
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+ib_api_status_t
+osmt_run_inform_info_flow( IN osmtest_t * const p_osmt );
+
+/****f* OSMTest/osmt_run_slvl_and_vlarb_records_flow
+ * NAME
+ * osmt_run_slvl_and_vlarb_records_flow
+ *
+ * DESCRIPTION
+ * Run the sl2vl and vlarb tables testing flow.
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t
+osmt_run_slvl_and_vlarb_records_flow( IN osmtest_t * const p_osmt );
+/*
+ * PARAMETERS
+ *  p_osmt
+ *    [in] Pointer to the osmtest obj
+ *
+ * RETURN VALUES
+ * IB_SUCCESS if PASS
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* OSMTest/osmt_run_mcast_flow
+ * NAME
+ * osmt_run_mcast_flow
+ *
+ * DESCRIPTION
+ * Run the multicast test flow
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t
+osmt_run_mcast_flow( IN osmtest_t * const p_osmt );
+/*
+ * PARAMETERS
+ *  p_osmt
+ *    [in] Pointer to the osmtest obj
+ *
+ * RETURN VALUES
+ * IB_SUCCESS if PASS
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* OSMTest/osmt_run_trap64_65_flow
+ * NAME
+ * osmt_run_trap64_65_flow
+ *
+ * DESCRIPTION
+ * Run the trap 64/65 test flow. This test is ran with
+ * an outside tool.
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t
+osmt_run_trap64_65_flow( IN osmtest_t * const p_osmt );
+/*
+ * PARAMETERS
+ *  p_osmt
+ *    [in] Pointer to the osmtest obj
+ *
+ * RETURN VALUES
+ * IB_SUCCESS if PASS
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+ib_api_status_t
+osmtest_get_all_recs( IN osmtest_t * const p_osmt,
+                      IN ib_net16_t const attr_id,
+                      IN size_t const attr_size,
+                      IN OUT osmtest_req_context_t * const p_context );
+
+ib_api_status_t
+osmtest_get_local_port_lmc( IN osmtest_t * const p_osmt,
+                            IN ib_net16_t  lid,
+                            OUT uint8_t *  const p_lmc );
+
+
+/*
+ * A few auxiliary macros for logging
+ */
+
+#define EXPECTING_ERRORS_START "[[ ===== Expecting Errors - START ===== "
+#define EXPECTING_ERRORS_END   "   ===== Expecting Errors  -  END ===== ]]"
+
+#endif /* _OSMTEST_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmtest_base.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmtest_base.h
new file mode 100644 (file)
index 0000000..70258f1
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osmtest_base.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osmtest_t.
+ *     This object represents the OSMTest Test object.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+#ifndef _OSMTEST_BASE_H_
+#define _OSMTEST_BASE_H_
+
+#ifndef __WIN__
+#include <limits.h>
+#else
+#include <vendor/winosm_common.h>
+#endif
+
+#define OSMTEST_MAX_LINE_LEN   120
+#ifdef WIN32
+#define OSMTEST_FILE_PATH_MAX  4096
+#else
+#define OSMTEST_FILE_PATH_MAX  PATH_MAX
+#endif
+
+#define STRESS_SMALL_RMPP_THR 100000
+/* 
+    Take long times when quering big clusters (over 40 nodes) , an average of : 0.25 sec for query
+    each query receives 1000 records 
+*/
+#define STRESS_LARGE_RMPP_THR 4000
+#define STRESS_LARGE_PR_RMPP_THR 20000
+
+extern const char *const p_file;
+
+#endif /* _OSMTEST_BASE_H_ */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmtest_subnet.h b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/include/osmtest_subnet.h
new file mode 100644 (file)
index 0000000..6281503
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osmtest_subnet.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osmtest_t.
+ *     This object represents the OSMTest Test object.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+#ifndef _OSMTEST_SUBNET_H_
+#define _OSMTEST_SUBNET_H_
+
+#include <stdlib.h>
+#include <complib/cl_qmap.h>
+#include <opensm/osm_log.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_helper.h>
+
+
+/****s* Subnet Database/generic_t
+* NAME
+*      generic_t
+*
+* DESCRIPTION
+*      Subnet database object for fields common to all record types.
+*      All other database types must be castable to this type.
+*
+* SYNOPSIS
+*/
+typedef struct _generic
+{
+       cl_map_item_t map_item;         /* must be first element! */
+       uint32_t count;                         /* must be second element! */
+} generic_t;
+
+/*
+* FIELDS
+*
+* SEE ALSO
+*********/
+
+/****s* Subnet Database/node_t
+* NAME
+*      node_t
+*
+* DESCRIPTION
+*      Subnet database object for nodes.
+*      Must be castable to generic_t.
+*
+* SYNOPSIS
+*/
+typedef struct _node
+{
+       cl_map_item_t map_item;         /* must be first element! */
+       uint32_t count;                         /* must be second element! */
+       ib_node_record_t rec;
+       ib_node_record_t comp;
+} node_t;
+
+/*
+* FIELDS
+* map_item
+*      Provides linkage for the qmap container.
+*
+* rec
+*      NodeRecord for this node as read from the database file.
+*
+* comp
+*      NodeRecord indicating which fields should be compared against rec.
+*      Bits set in the comp NodeRecord indicate that bit in the rec structure
+*      should be compared against real-time data from the SA.
+*
+* count
+*      Utility counter used by the validation logic.  Typically used to
+*      to indicate the number of times a matching node was received from
+*      the SA.
+*
+* SEE ALSO
+*********/
+
+static inline node_t *
+node_new( void )
+{
+       node_t *p_obj;
+
+       p_obj = malloc( sizeof( *p_obj ) );
+       if (p_obj)
+               memset( p_obj, 0, sizeof( *p_obj ) );
+       return ( p_obj );
+}
+
+static inline void
+node_delete( IN node_t * p_obj )
+{
+       free( p_obj );
+}
+
+/****s* Subnet Database/port_t
+* NAME
+*      port_t
+*
+* DESCRIPTION
+*      Subnet database object for ports.
+*      Must be castable to generic_t.
+*
+* SYNOPSIS
+*/
+typedef struct _port
+{
+  cl_map_item_t map_item;              /* must be first element! */
+  uint32_t count;                              /* must be second element! */
+  /* Since there is no unique identifier for all ports we 
+         must be able to have such a key by the lid and port num */
+  uint64_t port_id;
+  ib_portinfo_record_t rec;
+  ib_portinfo_record_t comp;
+} port_t;
+
+/*
+* FIELDS
+*
+* map_item
+*      Provides linkage for the qmap container.
+*
+* rec
+*      PortInfoRecord for this port as read from the database file.
+*
+* comp
+*      PortInfoRecord indicating which fields should be compared against rec.
+*      Bits set in the comp NodeRecord indicate that bit in the rec structure
+*      should be compared against real-time data from the SA.
+*
+* count
+*      Utility counter used by the validation logic.  Typically used to
+*      to indicate the number of times a matching node was received from
+*      the SA.
+*
+* SEE ALSO
+*********/
+
+static inline port_t *
+port_new( void )
+{
+       port_t *p_obj;
+
+       p_obj = malloc( sizeof( *p_obj ) );
+       if (p_obj)
+               memset( p_obj, 0, sizeof( *p_obj ) );
+       return ( p_obj );
+}
+
+static inline void
+port_delete( IN port_t * p_obj )
+{
+       free( p_obj );
+}
+
+static inline uint64_t
+port_gen_id( 
+                                IN ib_net16_t const lid,
+                                IN uint8_t const port_num)
+{
+  return( lid << 8 | port_num );
+}
+
+static inline void
+port_ext_id( IN uint64_t id,
+                                IN ib_net16_t *p_lid,
+                                IN uint8_t *p_port_num)
+{
+  CL_ASSERT( (id & 0xFF) < 0x100 );
+  *p_port_num = (uint8_t)(id & 0xFF);
+  CL_ASSERT( ((id >> 8) & 0xFFFF) < 0x10000 );
+  *p_lid = (uint16_t)((id >> 8) & 0xFFFF);
+}
+
+static inline void
+port_set_id( IN port_t * p_obj,
+                                IN ib_net16_t const lid,
+                                IN uint8_t const port_num)
+{
+  p_obj->port_id = port_gen_id(lid, port_num);
+}
+
+static inline void
+port_get_id( IN port_t * p_obj,
+                                IN ib_net16_t *p_lid,
+                                IN uint8_t *p_port_num)
+{
+  port_ext_id(p_obj->port_id, p_lid, p_port_num);
+}
+
+/****s* Subnet Database/path_t
+* NAME
+*      node_t
+*
+* DESCRIPTION
+*      Subnet database object for paths.
+*      Must be castable to generic_t.
+*
+* SYNOPSIS
+*/
+typedef struct _path
+{
+       cl_map_item_t map_item;         /* must be first element! */
+       uint32_t count;                         /* must be second element! */
+       ib_path_rec_t rec;
+       ib_path_rec_t comp;
+} path_t;
+
+/*
+* FIELDS
+* map_item
+*      Provides linkage for the qmap container.
+*
+* rec
+*      PathRecord for this path as read from the database file.
+*
+* comp
+*      PathRecord indicating which fields should be compared against rec.
+*      Bits set in the comp PathRecord indicate that bit in the rec structure
+*      should be compared against real-time data from the SA.
+*
+* count
+*      Utility counter used by the validation logic.  Typically used to
+*      to indicate the number of times a matching node was received from
+*      the SA.
+*
+* SEE ALSO
+*********/
+
+static inline path_t *
+path_new( void )
+{
+       path_t *p_obj;
+
+       p_obj = malloc( sizeof( *p_obj ) );
+       if (p_obj)
+               memset( p_obj, 0, sizeof( *p_obj ) );
+       return ( p_obj );
+}
+
+static inline void
+path_delete( IN path_t * p_obj )
+{
+       free( p_obj );
+}
+
+/****s* Subnet Database/subnet_t
+* NAME
+*      subnet_t
+*
+* DESCRIPTION
+*      Subnet database object.
+*
+* SYNOPSIS
+*/
+typedef struct _subnet
+{
+  cl_qmap_t node_lid_tbl;
+  cl_qmap_t node_guid_tbl;
+  cl_qmap_t    mgrp_mlid_tbl;
+  /* cl_qmap_t port_lid_tbl; */
+  /* cl_qmap_t port_guid_tbl; */
+  cl_qmap_t port_key_tbl;
+  cl_qmap_t link_tbl;
+  cl_qmap_t path_tbl;
+} subnet_t;
+
+/*
+* FIELDS
+*
+* SEE ALSO
+*********/
+
+/****f* Subnet Database/subnet_construct
+* NAME
+*      subnet_construct
+*
+* DESCRIPTION
+*      This function constructs an subnet database object.
+*      This function cannot fail.
+*
+* SYNOPSIS
+*/
+void subnet_construct( IN subnet_t * const p_subn );
+
+/*
+* FIELDS
+*
+* SEE ALSO
+*********/
+
+/****f* Subnet Database/subnet_init
+* NAME
+*      subnet_init
+*
+* DESCRIPTION
+*      This function initializes an subnet database object.
+*
+* SYNOPSIS
+*/
+cl_status_t subnet_init( IN subnet_t * const p_subn );
+
+/*
+* FIELDS
+*
+* SEE ALSO
+*********/
+
+#endif
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/main.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/main.c
new file mode 100644 (file)
index 0000000..c8168eb
--- /dev/null
@@ -0,0 +1,678 @@
+/*
+ * Copyright (c) 2004,2005 Voltaire, Inc. All rights reserved.   
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.   
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.   
+ *  
+ * This software is available to you under the OpenIB.org BSD license  
+ * below:  
+ *  
+ *     Redistribution and use in source and binary forms, with or  
+ *     without modification, are permitted provided that the following  
+ *     conditions are met:  
+ *  
+ *      - Redistributions of source code must retain the above  
+ *        copyright notice, this list of conditions and the following  
+ *        disclaimer.  
+ *  
+ *      - Redistributions in binary form must reproduce the above  
+ *        copyright notice, this list of conditions and the following  
+ *        disclaimer in the documentation and/or other materials  
+ *        provided with the distribution.  
+ *  
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,  
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF   
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND           
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS  
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN  
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN  
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  
+ * SOFTWARE.  
+ *  
+ * $Id: main.c 1940 2009-02-11 10:14:39Z tzachid $
+ */
+
+/*
+ * Abstract:
+ *     Command line interface for osmtest.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <complib/cl_debug.h>
+#include "osmtest.h"
+
+/********************************************************************
+       D E F I N E    G L O B A L    V A R I A B L E S
+*********************************************************************/
+
+/*
+       This is the global osmtest object.
+       One osmtest object is required per subnet.
+       Future versions could support multiple subents by
+       instantiating more than one osmtest object.
+*/
+#define GUID_ARRAY_SIZE 64
+#define OSMT_DEFAULT_RETRY_COUNT 3
+#define OSMT_DEFAULT_TRANS_TIMEOUT_MILLISEC 1000
+#define OSMT_DEFAULT_TRAP_WAIT_TIMEOUT_SEC 10
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osmt_is_debug(void)
+{
+#if defined( _DEBUG_ )
+  return TRUE;
+#else
+  return FALSE;
+#endif /* defined( _DEBUG_ ) */
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_net64_t
+get_port_guid(
+  IN osmtest_t *p_osm, uint64_t port_guid,
+  IN boolean_t is_service)
+{
+  uint32_t i;
+  uint32_t choice = 0;
+  char junk[128];
+  boolean_t done_flag = FALSE;
+  ib_api_status_t status;
+  uint32_t num_ports = GUID_ARRAY_SIZE;
+  ib_port_attr_t attr_array[GUID_ARRAY_SIZE];
+  
+  /*
+    Call the transport layer for a list of local port
+    GUID values.
+  */
+  status = osm_vendor_get_all_port_attr( p_osm->p_vendor, attr_array, &num_ports );
+  if( status != IB_SUCCESS )
+  {
+    printf( "\nError from osm_vendor_get_all_port_attr (%x)\n", status);
+    return( 0 );
+  }
+
+  /* if num_ports is 0 - return 0 */
+  if( num_ports == 0 )
+  {
+    printf( "\nNo local ports detected!\n" );
+    return( 0 );
+  }
+  /* If num_ports is 1, then there is only one possible port to use. Use it. */
+  if ( num_ports == 1 )
+  {
+    printf("Using default GUID 0x%" PRIx64 "\n", cl_hton64(attr_array[0].port_guid));
+    return( attr_array[0].port_guid );
+  }
+
+#if defined ( OSM_VENDOR_INTF_OPENIB )
+  /* If port_guid is 0, and this is gen2 - use the default port whose info is in attr_array[0] */
+  if ( port_guid == 0 )
+  {
+    printf("Using default GUID 0x%" PRIx64 "\n", cl_hton64(attr_array[0].port_guid));
+    return( attr_array[0].port_guid );
+  }
+#endif /* OSM_VENDOR_INTF_OPENIB */
+
+  /* If port_guid is 0, and we are in windows - find the first port with link_state != DOWN and
+     use it as default port. */
+  if ( port_guid == 0 )
+  {
+    for ( i = 0; i < num_ports; i++ )
+    {
+      if (attr_array[i].link_state > IB_LINK_DOWN)
+      {
+        /* Use this port */
+        printf("Using default guid 0x%" PRIx64 "\n", cl_hton64(attr_array[i].port_guid));
+        return( attr_array[i].port_guid );
+      }
+    }
+    /* If we are running as a service, and all ports are down we return the 
+       first port (we can't open a window, as a service)*/
+       if (is_service) {
+         return( attr_array[0].port_guid );
+       }
+  }
+
+  /* More than one possible port - list all ports and let the user to choose. */
+  while( done_flag == FALSE )
+  {
+    printf( "\nChoose a local port number with which to bind:\n\n" );
+    /* If this is gen2 code - then port 0 has details of the default port used. 
+       no need to print it.
+       If this is not gen2 code - need to print details of all ports. */
+#if defined ( OSM_VENDOR_INTF_OPENIB )
+    for( i = 1; i < num_ports; i++ )
+    {
+      printf("\t%u: GUID = 0x%8" PRIx64 ", lid = 0x%04X, state = %s\n",
+             i, cl_ntoh64( attr_array[i].port_guid ),
+             attr_array[i].lid,
+             ib_get_port_state_str( attr_array[i].link_state ) );
+    }
+    printf( "\nEnter choice (1-%u): ", i-1 );
+# else
+    for( i = 0; i < num_ports; i++ )
+    {
+      /*
+        Print the index + 1 since by convention, port numbers
+        start with 1 on host channel adapters.
+      */
+
+      printf("\t%u: GUID = 0x%8" PRIx64 ", lid = 0x%04X, state = %s\n",
+             i+1, cl_ntoh64( attr_array[i].port_guid ),
+             attr_array[i].lid,
+             ib_get_port_state_str( attr_array[i].link_state ) );
+    }
+    printf( "\nEnter choice (1-%u): ", i );
+#endif /* OSM_VENDOR_INTF_OPENIB */
+
+    fflush( stdout );
+    if (scanf( "%u", &choice ))
+    {
+      /* If gen2 code - choice can be between 1 to num_ports-1
+         if not gen2 code - choice can be between 1 to num_ports */
+#if defined ( OSM_VENDOR_INTF_OPENIB )
+      if( choice >= num_ports )
+# else
+      if( choice > num_ports || choice < 1 )
+#endif /* OSM_VENDOR_INTF_OPENIB */
+      {
+        printf("\nError: Lame choice!\n");
+        fflush( stdin );
+      }
+      else
+      {
+        done_flag = TRUE;
+      }
+    }
+    else
+    {
+      /* get rid of the junk in the selection line */
+      scanf( "%s", junk );
+      printf("\nError: Lame choice!\n"); 
+      fflush( stdin );
+    }
+  }
+#if defined ( OSM_VENDOR_INTF_OPENIB )
+  printf("Choice guid=0x%8" PRIx64 "\n", cl_ntoh64( attr_array[choice].port_guid ));       
+  return( attr_array[choice].port_guid );
+# else
+  return( attr_array[choice - 1].port_guid );
+#endif /* OSM_VENDOR_INTF_OPENIB */
+}
+/**********************************************************************
+ **********************************************************************/
+void show_usage(void);
+
+void
+show_usage(  )
+{
+       printf
+               ( "\n------- osmtest - Usage and options ----------------------\n" );
+       printf( "Usage:   osmtest [options]\n" );
+       printf( "Options:\n" );
+       printf( "-f <c|a|v|s|e|f|m|q|t>\n"
+                       "--flow <c|a|v|s|e|f|m|q|t>\n"
+                       "          This option directs osmtest to run a specific flow:\n"
+                       "          FLOW  DESCRIPTION\n"
+                       "          c = create an inventory file with all nodes, ports and paths.\n"
+                       "          a = run all validation tests (expecting an input inventory)\n"
+                       "          v = only validate the given inventory file.\n"
+                       "          s = run service registration, un-registration and lease.\n"
+                       "          e = run event forwarding test.\n"
+                       "          f = flood the SA with queries accoring to the stress mode.\n"
+                       "          m = multicast flow.\n"
+                       "          q = QoS info - VLArb and SLtoVL tables.\n"
+         "          t = run trap 64/65 flow. This flow requires running of external tool.\n"
+                       "          (default is all but QoS).\n\n" );
+       printf( "-w <trap_wait_time>\n"
+               "--wait <trap_wait_time>\n"
+               "          This option specifies the wait time for trap 64/65 in seconds.\n"
+               "          It is used only when running -f t - the trap 64/65 flow\n"
+               "          (default to 10 sec).\n" );
+       printf( "-d <number>\n"
+                       "--debug <number>\n"
+                       "          This option specifies a debug option.\n"
+                       "          These options are not normally needed.\n"
+                       "          The number following -d selects the debug\n"
+                       "          option to enable as follows:\n"
+                       "          OPT   Description\n"
+                       "          ---    -----------------\n"
+                       "          -d0  - Unused.\n"
+                       "          -d1  - Do not scan/compare path records.\n"
+                       "          -d2  - Force log flushing after each log message.\n"
+                       "          -d3  - Use mem tracking.\n"
+                       "          Without -d, no debug options are enabled.\n\n" );
+       printf( "-m <LID in hex>\n"
+                       "--max_lid <LID in hex>\n"
+                       "          This option specifies the maximal LID number to be searched\n"
+                  "          for during inventory file build (default to 100).\n");
+       printf( "-g <GUID in hex>\n"
+                       "--guid <GUID in hex>\n"
+                       "          This option specifies the local port GUID value\n"
+                       "          with which osmtest should bind.  osmtest may be\n"
+                       "          bound to 1 port at a time.\n"
+                       "          Without -g, osmtest displays a menu of possible\n"
+                       "          port GUIDs and waits for user input.\n\n" );
+       printf( "-h\n"
+                       "--help\n" "          Display this usage info then exit.\n\n" );
+       printf( "-i <filename>\n"
+                       "--inventory <filename>\n"
+                       "          This option specifies the name of the inventory file.\n"
+                       "          Normally, osmtest expects to find an inventory file,\n"
+                       "          which osmtest uses to validate real-time information\n"
+                       "          received from the SA during testing.\n"
+                       "          If -i is not specified, osmtest defaults to the file\n"
+                       "          'osmtest.dat'.\n"
+                       "          See the -c option for related information.\n\n" );
+       printf( "-s\n"
+                       "--stress\n"
+                       "          This option runs the specified stress test instead\n"
+                       "          of the normal test suite.\n"
+                       "          Stress test options are as follows:\n"
+                       "          OPT    Description\n"
+                       "          ---    -----------------\n"
+                       "          -s1  - Single-MAD response SA queries .\n"
+                       "          -s2  - Multi-MAD (RMPP) response SA queries.\n"
+                       "          -s3  - Multi-MAD (RMPP) Path Record SA queries.\n"
+                       "          Without -s, stress testing is not performed.\n\n" );
+    printf( "-M\n"
+            "--Multicast_Mode\n"
+            "          This option specify length of Multicast test :\n"
+            "          OPT    Description\n"
+            "          ---    -----------------\n"
+            "          -M1  - Short Multicast Flow (default) - single mode.\n"
+            "          -M2  - Short Multicast Flow  - multiple mode.\n"
+            "          -M3  - Long Multicast Flow - single mode.\n"
+            "          -M4  - Long Multicast Flow - multiple mode.\n"
+            " Single mode - Osmtest is tested alone , with no other  \n"
+            "   apps that interact vs. OpenSM MC.\n"
+            " Multiple mode - Could be run with other apps using MC vs.\n"
+            "   OpenSM."
+            " Without -M, default flow testing is performed.\n\n" );
+
+    printf( "-t <milliseconds>\n"
+                       "          This option specifies the time in milliseconds\n"
+                       "          used for transaction timeouts.\n"
+                       "          Specifying -t 0 disables timeouts.\n"
+                       "          Without -t, osmtest defaults to a timeout value of\n"
+                       "          1 second.\n\n" );
+       printf( "-l\n"
+                         "--log_file\n"
+                         "          This option defines the log to be the given file.\n"
+                         "          By default the log goes to stdout.\n\n");
+       printf( "-v\n"
+                       "          This option increases the log verbosity level.\n"
+                       "          The -v option may be specified multiple times\n"
+                       "          to further increase the verbosity level.\n"
+                       "          See the -vf option for more information about.\n"
+                       "          log verbosity.\n\n" );
+       printf( "-V\n"
+                       "          This option sets the maximum verbosity level and\n"
+                       "          forces log flushing.\n"
+                       "          The -V is equivalent to '-vf 0xFF -d 2'.\n"
+                       "          See the -vf option for more information about.\n"
+                       "          log verbosity.\n\n" );
+       printf( "-vf <flags>\n"
+                       "          This option sets the log verbosity level.\n"
+                       "          A flags field must follow the -vf option.\n"
+                       "          A bit set/clear in the flags enables/disables a\n"
+                       "          specific log level as follows:\n"
+                       "          BIT    LOG LEVEL ENABLED\n"
+                       "          ----   -----------------\n"
+                       "          0x01 - ERROR (error messages)\n"
+                       "          0x02 - INFO (basic messages, low volume)\n"
+                       "          0x04 - VERBOSE (interesting stuff, moderate volume)\n"
+                       "          0x08 - DEBUG (diagnostic, high volume)\n"
+                       "          0x10 - FUNCS (function entry/exit, very high volume)\n"
+                       "          0x20 - FRAMES (dumps all SMP and GMP frames)\n"
+                       "          0x40 - currently unused.\n"
+                       "          0x80 - currently unused.\n"
+                       "          Without -vf, osmtest defaults to ERROR + INFO (0x3).\n"
+                       "          Specifying -vf 0 disables all messages.\n"
+                       "          Specifying -vf 0xFF enables all messages (see -V).\n"
+                       "          High verbosity levels may require increasing\n"
+                       "          the transaction timeout with the -t option.\n\n" );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void show_menu(void);
+
+void
+show_menu(  )
+{
+       printf( "\n------- Interactive Menu -------\n" );
+       printf( "X - Exit.\n\n" );
+}
+void OsmReportState(IN const char *p_str)
+{
+}
+
+/**********************************************************************
+ **********************************************************************/
+int OSM_CDECL
+main( int argc,
+         char *argv[] )
+{
+       static osmtest_t osm_test;
+       osmtest_opt_t opt = { 0 };
+       ib_net64_t guid = 0;
+       int max_lid = 100;
+       ib_api_status_t status;
+       uint32_t log_flags = OSM_LOG_ERROR | OSM_LOG_INFO;
+       char flow_name[64];
+    boolean_t mem_track = FALSE;
+       uint32_t next_option;
+       const char *const short_option = "f:l:m:M:d:g:s:t:i:cvVh";
+
+    /*
+        * In the array below, the 2nd parameter specified the number
+        * of arguments as follows:
+        * 0: no arguments
+        * 1: argument
+        * 2: optional
+        */
+       const struct option long_option[] = {
+               {"create",    0, NULL, 'c'},
+               {"debug",     1, NULL, 'd'},
+               {"flow",      1, NULL, 'f'},
+               {"wait",      1, NULL, 'w'},
+               {"inventory", 1, NULL, 'i'},
+               {"max_lid",   1, NULL, 'm'},
+               {"guid",      1, NULL, 'g'},
+               {"help",      0, NULL, 'h'},
+               {"stress",    1, NULL, 's'},
+               {"Multicast_Mode",    1, NULL, 'M'},
+               {"timeout",   1, NULL, 't'},
+               {"verbose",   0, NULL, 'v'},
+               {"log_file",  1, NULL, 'l'},
+               {"vf",        1, NULL, 'x'},
+               {"V",         0, NULL, 'V'},
+
+               {NULL, 0, NULL, 0}              /* Required at end of array */
+       };
+
+       opt.transaction_timeout = OSMT_DEFAULT_TRANS_TIMEOUT_MILLISEC;
+       opt.wait_time = OSMT_DEFAULT_TRAP_WAIT_TIMEOUT_SEC;
+       opt.retry_count = OSMT_DEFAULT_RETRY_COUNT;
+       opt.force_log_flush = FALSE;
+       opt.stress = 0;
+       opt.log_file = NULL;
+       opt.create = FALSE;
+    opt.mmode = 1;
+       opt.ignore_path_records = FALSE; /*  Do path Records too. */
+       opt.flow = 0; /*  run all validation tests */
+       strcpy(flow_name, "All Validations");
+       strcpy( opt.file_name, "osmtest.dat" );
+
+       printf( "\nCommand Line Arguments\n" );
+       do
+       {
+               next_option = getopt_long_only( argc, argv, short_option,
+                                                                               long_option, NULL );
+               switch ( next_option )
+               {
+               case 'c':
+                       /*
+                        * Create the inventory file.
+                        */
+                       opt.create = TRUE;
+                       printf( "\tCreating inventory file\n" );
+                       break;
+
+               case 'i':
+                       /*
+                        * Specifies inventory file name.
+                        */
+                       if( strlen( optarg ) > OSMTEST_FILE_PATH_MAX )
+                               printf( "\nError: path name too long (ignored).\n" );
+                       else
+                               strcpy( opt.file_name, optarg );
+
+                       printf( "\tFile = %s\n", opt.file_name );
+                       break;
+
+               case 'f':
+                       /*
+                        * Specifies Flow .
+                        */
+                 if( strlen( optarg ) > OSMTEST_FILE_PATH_MAX )
+                               printf( "\nError: path name too long (ignored).\n" );
+                       else
+                               strcpy( flow_name, optarg );
+
+                 if (!strcmp("c",optarg)) {
+                        strcpy(flow_name, "Create Inventory");
+                        opt.flow = 1;
+                 } else if (!strcmp("v",optarg)) {
+                        strcpy(flow_name, "Validate Inventory");
+                        opt.flow = 2;
+                 } else if (!strcmp("s",optarg)) {
+                        strcpy(flow_name, "Services Registration");
+                        opt.flow = 3;
+                 } else if (!strcmp("e",optarg)) {
+                        strcpy(flow_name, "Event Forwarding");
+                        opt.flow = 4;
+                 } else if (!strcmp("f",optarg)) {
+                        strcpy(flow_name, "Stress SA");
+                        opt.flow = 5;
+                 } else if (!strcmp("m",optarg)) {
+                        strcpy(flow_name, "Multicast");
+                        opt.flow = 6;
+                 } else if (!strcmp("q",optarg)) {
+                        strcpy(flow_name, "QoS: VLArb and SLtoVL");
+                        opt.flow = 7;
+                 } else if (!strcmp("t", optarg)) {
+                   strcpy(flow_name, "Trap 64/65");
+                   opt.flow = 8;
+                 } else if (!strcmp("a",optarg)) {
+                        strcpy(flow_name, "All Validations");
+                        opt.flow = 0;
+                 } else {
+                        printf( "\nError: un-known flow %s.\n",flow_name);
+                        exit(2);
+                 }
+                 break;
+
+               case 'w':
+                       /*
+                        * Specifies trap 64/65 wait time
+                        */
+        CL_ASSERT( strtol( optarg, NULL, 0 ) < 0x100 );
+                 opt.wait_time = (uint8_t)strtol( optarg, NULL, 0 );
+                 printf( "\tTrap 64/65 wait time = %d\n", opt.wait_time );
+                 break;
+
+               case 'm':
+                       /*
+                        * Specifies the max LID to search for during exploration.
+                        */
+                       max_lid = atoi( optarg );
+                       printf( "\tMAX-LID %u\n", max_lid );
+                       break;
+
+               case 'g':
+                       /*
+                        * Specifies port guid with which to bind.
+                        */
+                 guid = cl_hton64( strtoull( optarg, NULL, 16 ));
+                 printf( "\tGUID 0x%016" PRIx64 "\n", guid );
+                 break;
+               case 't':
+                       /*
+                        * Specifies transaction timeout.
+                        */
+                 opt.transaction_timeout = strtol( optarg, NULL, 0 );
+                 printf( "\tTransaction timeout = %d\n", opt.transaction_timeout );
+                 break;
+
+               case 'l':
+                 opt.log_file = optarg;
+                 printf("\tLog File:%s\n", opt.log_file );
+                 break;
+
+               case 'v':
+                       /*
+                        * Increases log verbosity.
+                        */
+                       log_flags = ( log_flags << 1 ) | 1;
+                       printf( "\tVerbose option -v (log flags = 0x%X)\n", log_flags );
+                       break;
+
+               case 'V':
+                       /*
+                        * Specifies maximum log verbosity.
+                        */
+                       log_flags = 0xFFFFFFFF;
+                       opt.force_log_flush = TRUE;
+                       printf( "\tEnabling maximum log verbosity\n" );
+                       break;
+
+               case 's':
+                       /*
+                        * Perform stress test.
+                        */
+                       opt.stress = strtol( optarg, NULL, 0 );
+                       printf( "\tStress test enabled: " );
+                       switch ( opt.stress )
+                       {
+                       case 1:
+                               printf( "Small SA queries\n" );
+                               break;
+                       case 2:
+                               printf( "Large SA queries\n" );
+                               break;
+            case 3:
+                printf( "Large Path Record SA queries\n" );
+                break;
+                       default:
+                               printf( "Unknown value %u (ignored)\n", opt.stress );
+                               opt.stress = 0;
+                               break;
+                       }
+                       break;
+
+        case 'M':
+            /*
+             * Perform stress test.
+             */
+            opt.mmode = strtol( optarg, NULL, 0 );
+            printf( "\tMulticast test enabled: " );
+            switch ( opt.mmode )
+            {
+            case 1:
+                printf( "Short MC Flow - single mode (default)\n" );
+                break;
+            case 2:
+                printf( "Short MC Flow - multiple mode\n" );
+                break;
+            case 3:
+                printf( "Long MC Flow - single mode\n" );
+                break;
+            case 4:
+                printf( "Long MC Flow - multiple mode\n" );
+                break;
+            default:
+                printf( "Unknown value %u (ignored)\n", opt.stress );
+                opt.mmode = 0;
+                break;
+            }
+            break;
+
+               case 'd':
+                       /*
+                        * Debug Options
+                        */
+                       printf( "\tDebug Option: " );
+                       switch ( strtol( optarg, NULL, 0 ) )
+                       {
+                       case 1:
+                               printf( "Ignore Path Records.\n" );
+                               opt.ignore_path_records = TRUE;
+                               break;
+                       case 2:
+                               printf( "Force Log Flush.\n" );
+                               opt.force_log_flush = TRUE;
+                               break;
+                       case 3:
+                               printf( "Use Mem Tracking.\n" );
+                               mem_track = TRUE;
+                               break;
+                       default:
+                               printf( "Unknown value %ld (ignored)\n", strtol( optarg, NULL, 0 ) );
+                               break;
+                       }
+                       break;
+
+               case 'h':
+                       show_usage(  );
+                       return 0;
+
+               case 'x':
+                       log_flags = strtol( optarg, NULL, 0 );
+                       printf( "\t\t\t\tVerbose option -vf (log flags = 0x%X)\n",
+                                       log_flags );
+                       break;
+
+               case -1:
+                       printf( "Done with args\n" );
+                       break;
+
+               default:                                /* something wrong */
+                       abort(  );
+               }
+
+       }
+       while( next_option != -1 );
+
+       printf( "\tFlow = %s\n", flow_name );
+
+   if (mem_track) __cl_mem_track(TRUE);
+
+
+       status = osmtest_init( &osm_test, &opt, ( osm_log_level_t ) log_flags );
+       if( status != IB_SUCCESS )
+       {
+               printf( "\nError from osmtest_init: %s.\n",
+                               ib_get_err_str( status ) );
+               goto Exit;
+       }
+
+       /*
+          If the user didn't specify a GUID on the command line,
+          then get a port GUID value with which to bind.
+        */
+       if (guid == 0 && !(guid = get_port_guid(&osm_test, guid,1))) {
+               printf("\nError: port guid 0x%" PRIx64 " not found\n", guid);
+               goto Exit;
+       }
+
+       /*
+        * Guid may be zero going into this function if the user
+        * hasn't specified a binding port on the command line.
+        */
+        
+       status = osmtest_bind( &osm_test, (uint16_t)max_lid, guid );
+       if (status != IB_SUCCESS) exit(status);
+
+       status = osmtest_run( &osm_test );
+       if (status != IB_SUCCESS) {
+         printf("OSMTEST: TEST \"%s\" FAIL\n", flow_name);
+       } else {
+         printf("OSMTEST: TEST \"%s\" PASS\n", flow_name);
+       }
+       osmtest_destroy( &osm_test );
+
+   if (mem_track) cl_mem_display();
+
+  Exit:
+       return ( status );
+}
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_inform.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_inform.c
new file mode 100644 (file)
index 0000000..dab8981
--- /dev/null
@@ -0,0 +1,961 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osmt_inform.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifdef OSM_VENDOR_INTF_MTL
+/*
+ * Abstract:
+ *    Implementation of InformInfo testing flow..
+ *    Top level is osmt_run_inform_info_flow:
+ *     osmt_bind_inform_qp
+ *     osmt_reg_unreg_inform_info
+ *     osmt_send_trap_wait_for_forward
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <vendor/osm_vendor_mlx_hca.h>
+#include "osmtest.h"
+#include "osmt_inform.h"
+
+/*
+ * Prepare an asynchronous QP (rcv) for sending inform info and
+ * handling the incoming reports.
+ *
+ */
+ib_api_status_t
+osmt_bind_inform_qp( IN osmtest_t * const p_osmt,
+                     OUT osmt_qp_ctx_t *p_qp_ctx) {
+  ib_net64_t port_guid;
+  VAPI_hca_hndl_t hca_hndl;
+  VAPI_hca_id_t hca_id;
+  uint32_t port_num;
+  VAPI_ret_t vapi_ret;
+  IB_MGT_ret_t mgt_ret;
+  uint8_t hca_index;
+  osm_log_t *p_log = &p_osmt->log;
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osmt_bind_inform_qp );
+
+  port_guid = p_osmt->local_port.port_guid;
+
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "osmt_bind_inform_qp: "
+           "Binding to port 0x%" PRIx64 "\n", cl_ntoh64( port_guid ) );
+
+  /* obtain the hca name and port num from the guid */
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "osmt_bind_inform_qp: "
+           "Finding CA and Port that owns port guid 0x%" PRIx64 "\n",
+           port_guid );
+
+  mgt_ret =
+    osm_vendor_get_guid_ca_and_port(
+      p_osmt->p_vendor,
+      port_guid,
+      &hca_hndl,
+      &hca_id[0],
+      &hca_index,
+      &port_num );
+  if( mgt_ret != IB_MGT_OK )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osmt_bind_inform_qp: ERR 0109: "
+             "Unable to obtain CA and port (%d).\n" );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+#define OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY 0x80010000
+
+  strncpy(p_qp_ctx->qp_bind_hndl.hca_id, hca_id, sizeof(hca_id));
+  p_qp_ctx->qp_bind_hndl.hca_hndl = hca_hndl;
+  p_qp_ctx->qp_bind_hndl.port_num = port_num;
+  p_qp_ctx->qp_bind_hndl.max_outs_sq = 10;
+  p_qp_ctx->qp_bind_hndl.max_outs_rq = 10;
+  p_qp_ctx->qp_bind_hndl.qkey = OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY;
+
+  vapi_ret = osmt_mtl_init_opened_hca(&p_qp_ctx->qp_bind_hndl);
+  if (vapi_ret != VAPI_OK)
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osmt_bind_inform_qp: ERR 0114: "
+             "Error initializing QP.\n" );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* we use the pre-allocated buffers for send and receive :
+     send from buf[0]
+     receive from buf[2]
+  */
+  p_qp_ctx->p_send_buf = (uint8_t *)p_qp_ctx->qp_bind_hndl.buf_ptr + GRH_LEN;
+  p_qp_ctx->p_recv_buf = (uint8_t *)p_qp_ctx->qp_bind_hndl.buf_ptr + 2 * (GRH_LEN + MAD_BLOCK_SIZE);
+
+  /* Need to clear assigned memory of p_send_buf - before using it to send any data */
+  memset(p_qp_ctx->p_send_buf, 0, MAD_BLOCK_SIZE);
+
+  status = IB_SUCCESS;
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "osmt_bind_inform_qp: "
+           "Initialized QP:0x%X in VAPI Mode\n",
+           p_qp_ctx->qp_bind_hndl.qp_id
+           );
+
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "osmt_bind_inform_qp: " "Binding to IB_MGT SMI\n" );
+
+  /* we also need a QP0 handle for sending packets */
+  mgt_ret = IB_MGT_get_handle( hca_id, port_num, IB_MGT_SMI,
+                               &( p_qp_ctx->ib_mgt_qp0_handle ) );
+  if( IB_MGT_OK != mgt_ret )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osmt_bind_inform_qp: ERR 0115: "
+             "Error obtaining IB_MGT handle to SMI\n" );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return status;
+}
+
+/*
+ * Close the QP
+ */
+void
+osmt_unbind_inform_qp( IN osmtest_t * const p_osmt,
+                       IN osmt_qp_ctx_t *p_qp_ctx) {
+  osm_log_t *p_log = &p_osmt->log;
+
+  OSM_LOG_ENTER( p_log, osmt_unbind_inform_qp );
+
+  osmt_mtl_mad_cleanup(&p_qp_ctx->qp_bind_hndl);
+
+  IB_MGT_release_handle(p_qp_ctx->ib_mgt_qp0_handle);
+
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "osmt_unbind_inform_qp: "
+           "Unbind QP handles\n" );
+  OSM_LOG_EXIT( &p_osmt->log );
+}
+
+/*
+ * Register/Unregister to receive the given InformInfo
+ *
+ * Uses the qp context to send the inform info mad.
+ * Wait for GetResp(InformInfoResp)
+ *
+ */
+ib_api_status_t
+osmt_reg_unreg_inform_info( IN osmtest_t         *p_osmt,
+                            IN osmt_qp_ctx_t     *p_qp_ctx,
+                            IN ib_inform_info_t  *p_inform_info,
+                            IN uint8_t           reg_flag
+                            )
+{
+  ib_sa_mad_t         *p_sa_mad = (ib_sa_mad_t *)(p_qp_ctx->p_send_buf);
+  ib_inform_info_t    *p_ii = ib_sa_mad_get_payload_ptr(p_sa_mad); /*  SA Payload */
+  VAPI_ret_t vapi_ret;
+  VAPI_wc_desc_t wc_desc;
+  VAPI_ud_av_hndl_t avh;
+  static VAPI_wr_id_t wrid = 16198;
+  osm_log_t *p_log = &p_osmt->log;
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmt_reg_unreg_inform_info );
+
+  /* init the MAD */
+  ib_mad_init_new( (ib_mad_t*)p_sa_mad,
+                   IB_MCLASS_SUBN_ADM,
+                   ( uint8_t ) 2,
+                   IB_MAD_METHOD_SET,
+                   cl_hton64( wrid ),
+                   ( ib_net16_t ) 0,
+                   0 );
+  wrid++;
+  p_sa_mad->attr_id = IB_MAD_ATTR_INFORM_INFO;
+
+  /* copy the reference inform info */
+  memcpy(p_ii, p_inform_info, sizeof(ib_inform_info_t));
+
+  if (reg_flag)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_INFO,
+             "osmt_reg_unreg_inform_info: "
+             "Subscribing InformInfo: Traps from lid:0x%X to 0x%X, trap num :0x%X\n",
+             p_ii->lid_range_begin,p_ii->lid_range_end,p_ii->g_or_v.generic.trap_num);
+  }
+  else
+  {
+    osm_log( &p_osmt->log, OSM_LOG_INFO,
+             "osmt_reg_unreg_inform_info: "
+             "UnSubscribing InformInfo: Traps from lid:0x%X to 0x%X\n",
+             p_ii->lid_range_begin, p_ii->lid_range_end);
+  }
+
+  /* set the subscribe bit */
+  if (reg_flag)
+  {
+    p_ii->subscribe = 1;
+  }
+  else
+  {
+    p_ii->subscribe = 0;
+    /*
+     * we need to set the QPN on the mad if we unsubscribe:
+     * o13-2.1.1 - QPN Field need to be set when unsubscribing.
+     */
+    ib_inform_info_set_qpn(p_ii,
+                           cl_hton32(p_qp_ctx->qp_bind_hndl.qp_id.qp_num));
+  }
+
+  osm_dump_inform_info( &p_osmt->log,
+                        p_ii,
+                        OSM_LOG_DEBUG );
+
+  /* --------------------- PREP ------------------------- */
+  if (osmt_mtl_mad_post_recv_bufs(&p_qp_ctx->qp_bind_hndl,
+                                  p_qp_ctx->p_recv_buf,
+                                  1, /*  but we need only one mad at a time */
+                                  GRH_LEN + MAD_BLOCK_SIZE,
+                                  wrid) != 1) {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osmt_reg_unreg_inform_info: ERR 0120: "
+             "Error posting recv bufs\n");
+    status = IB_ERROR;
+    goto Exit;
+  }
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "osmt_reg_unreg_inform_info: "
+           "Posted recv bufs\n");
+
+  vapi_ret = osmt_mtl_create_av(&p_qp_ctx->qp_bind_hndl, p_osmt->local_port.sm_lid, &avh);
+  if (vapi_ret != VAPI_OK)
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osmt_reg_unreg_inform_info: ERR 0121: "
+             "Error Preparing AVH (%s)\n",
+             VAPI_strerror_sym(vapi_ret)   );
+    status = IB_ERROR;
+    goto Exit;
+  }
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "osmt_reg_unreg_inform_info: "
+           "Prepared AVH\n");
+
+  if( osm_log_is_active( p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_dump_sa_mad( p_log, (ib_sa_mad_t *)(p_qp_ctx->p_send_buf), OSM_LOG_DEBUG);
+#if 0
+    for (i = 56; i < 253; i++) {
+      if ( i % 8 == 0 ) { printf("\n %d : ", i); }
+      printf("0x%02X ", p_qp_ctx->p_send_buf[i]);
+    }
+#endif
+    printf("\n");
+  }
+
+  /* --------------------- SEND ------------------------- */
+  vapi_ret = osmt_mtl_mad_send(&p_qp_ctx->qp_bind_hndl,
+                               wrid,
+                               p_qp_ctx->p_send_buf,
+                               1, /*  SA is QP1 */
+                               0, /*  SL is 0 */
+                               OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY,
+                               avh
+                               );
+  if (vapi_ret != VAPI_OK)
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osmt_reg_unreg_inform_info: ERR 0122: "
+             "Error sending mad (%s)\n",
+             VAPI_strerror_sym(vapi_ret)   );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
+                                   p_qp_ctx->qp_bind_hndl.sq_cq_hndl,
+                                   &wc_desc,
+                                   20,
+                                   10000,
+                                   NULL);
+  if (vapi_ret != VAPI_OK)
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osmt_reg_unreg_inform_info: ERR 0123: "
+             "Error getting send completion (%s)\n",
+             VAPI_strerror_sym(vapi_ret)   );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  if (wc_desc.status != VAPI_SUCCESS)
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osmt_reg_unreg_inform_info: ERR 0124: "
+             "Error on send completion (%s) (%d)\n",
+             VAPI_strerror_sym(wc_desc.status), wc_desc.status  );
+    status = IB_ERROR;
+    goto Exit;
+  }
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "osmt_reg_unreg_inform_info: "
+           "Sent MAD\n");
+
+  /* --------------------- RECV ------------------------- */
+  vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
+                                   p_qp_ctx->qp_bind_hndl.rq_cq_hndl,
+                                   &wc_desc,
+                                   20,
+                                   10000,
+                                   &avh);
+  if (vapi_ret != VAPI_SUCCESS)
+  {
+    if (vapi_ret == VAPI_CQ_EMPTY)
+    {
+      status = IB_TIMEOUT;
+    }
+    else
+    {
+      osm_log( p_log, OSM_LOG_ERROR,
+               "osmt_reg_unreg_inform_info: ERR 0125: "
+               "Error receiving mad (%s)\n",
+               VAPI_strerror_sym(vapi_ret) );
+      status = IB_ERROR;
+    }
+    goto Exit;
+  }
+
+  /* check to see if successful - by examination of the subscribe bit */
+  p_sa_mad = (ib_sa_mad_t *)(p_qp_ctx->p_recv_buf + GRH_LEN);
+
+  if (p_sa_mad->status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_reg_unreg_inform_info: "
+             "Remote error = %s\n",
+             ib_get_mad_status_str( (ib_mad_t *)p_sa_mad ));
+    status = IB_REMOTE_ERROR;
+    goto Exit;
+  }
+
+  if (p_sa_mad->method != IB_MAD_METHOD_GET_RESP)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_reg_unreg_inform_info: "
+             "Expected IB_MAD_METHOD_GET_RESP but got:(%X)\n",
+             p_sa_mad->method);
+    status = IB_REMOTE_ERROR;
+    goto Exit;
+  }
+
+  if (p_sa_mad->attr_id != IB_MAD_ATTR_INFORM_INFO)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_reg_unreg_inform_info: "
+             "Expected IB_MAD_ATTR_INFORM_INFO but got:(%X)\n",
+             cl_ntoh16(p_sa_mad->attr_id));
+    status = IB_REMOTE_ERROR;
+    goto Exit;
+  }
+
+  p_ii = ib_sa_mad_get_payload_ptr(p_sa_mad);
+  if (!p_ii->subscribe)
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osmt_reg_unreg_inform_info: ERR 0126: "
+             "Subscribe/Unsubscribe Failed\n");
+    status = IB_REMOTE_ERROR;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return status;
+}
+
+/*
+ * Send a trap (Subn LID Route) Trap(Notice) through the regular
+ * connection QP connection (targeted at QP0)
+ *
+ * Wait for the trap repress
+ */
+ib_api_status_t
+osmt_send_trap_wait_for_forward( IN osmtest_t * const    p_osmt,
+                                 IN osmt_qp_ctx_t        *p_qp_ctx
+                                 )
+{
+  ib_smp_t  *p_smp = (ib_smp_t *)(p_qp_ctx->p_send_buf);
+  ib_mad_notice_attr_t  *p_ntc = ib_smp_get_payload_ptr(p_smp);
+  ib_sa_mad_t * p_sa_mad;
+  IB_MGT_ret_t mgt_res;
+  VAPI_ret_t vapi_ret;
+  VAPI_wc_desc_t wc_desc;
+  VAPI_ud_av_hndl_t avh;
+  IB_ud_av_t av;
+  static VAPI_wr_id_t wrid = 2222;
+  osm_log_t *p_log = &p_osmt->log;
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osmt_send_trap_wait_for_forward );
+
+  osm_log( p_log, OSM_LOG_INFO,
+           "osmt_send_trap_wait_for_forward: "
+           "Sending Traps to QP0 of SA LID:0x%X\n",
+           p_osmt->local_port.sm_lid);
+
+  /* init the MAD */
+  memset(p_smp, 0, sizeof(ib_smp_t));
+  ib_mad_init_new( (ib_mad_t*)p_smp,
+                   IB_MCLASS_SUBN_LID,
+                   ( uint8_t ) 2,
+                   IB_MAD_METHOD_TRAP,
+                   cl_hton64( wrid),
+                   ( ib_net16_t ) 0,
+                   0 );
+
+  wrid++;
+  p_smp->attr_id = IB_MAD_ATTR_NOTICE;
+
+  /* prepare the notice */
+  p_ntc->generic_type = 0x82;/*  generic, type = 2 */
+  ib_notice_set_prod_type_ho(p_ntc, 1);
+  p_ntc->g_or_v.generic.trap_num = cl_hton16(0x26);
+  p_ntc->issuer_lid = cl_hton16(2);
+
+  /* --------------------- PREP ------------------------- */
+  if (osmt_mtl_mad_post_recv_bufs(&p_qp_ctx->qp_bind_hndl,
+                                  p_qp_ctx->p_recv_buf,
+                                  1, /*  we need to receive both trap repress and report */
+                                  GRH_LEN + MAD_BLOCK_SIZE,
+                                  wrid) != 1) {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osmt_send_trap_wait_for_forward: ERR 0127: "
+             "Error posting recv bufs\n");
+    status = IB_ERROR;
+    goto Exit;
+  }
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "osmt_send_trap_wait_for_forward: "
+           "Posted recv bufs\n");
+
+  av.dlid = p_osmt->local_port.sm_lid;
+  av.grh_flag = FALSE;
+
+  /*  EZ: returned in HACK: use constants */
+  av.static_rate = 0; /*  p_mad_addr->static_rate; */
+  av.src_path_bits = 1 ; /*  p_mad_addr->path_bits; */
+  av.sl = 0 ; /*  p_mad_addr->addr_type.gsi.service_level; */
+
+  if( osm_log_is_active( p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "osmt_send_trap_wait_for_forward: "
+             "av.dlid 0x%X, "
+             "av.static_rate %d, "
+             "av.path_bits %d\n",
+             cl_ntoh16( av.dlid ), av.static_rate, av.src_path_bits );
+  }
+
+  /* send it */
+  mgt_res = IB_MGT_send_mad( p_qp_ctx->ib_mgt_qp0_handle, p_smp,  /*  actual payload */
+                             &av,   /*  address vector */
+                             wrid,  /*  casting the mad wrapper pointer for err cb */
+                             p_osmt->opt.transaction_timeout );
+  if( mgt_res != IB_MGT_OK )
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osmt_send_trap_wait_for_forward: ERR 0128: "
+             "Error sending mad (%d)\n", mgt_res );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  vapi_ret = osmt_mtl_create_av(&p_qp_ctx->qp_bind_hndl, p_osmt->local_port.sm_lid, &avh);
+  if (vapi_ret != VAPI_OK)
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osmt_send_trap_wait_for_forward: ERR 0129: "
+             "Error Preparing AVH (%s)\n",
+             VAPI_strerror_sym(vapi_ret)   );
+    status = IB_ERROR;
+    goto Exit;
+  }
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "osmt_send_trap_wait_for_forward: "
+           "Prepared AVH\n");
+
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "osmt_send_trap_wait_for_forward: "
+           "Trap MAD Sent\n");
+
+  /* --------------------- RECV ------------------------- */
+  vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
+                                   p_qp_ctx->qp_bind_hndl.rq_cq_hndl,
+                                   &wc_desc,
+                                   200,
+                                   10000,
+                                   &avh);
+  if (vapi_ret != VAPI_SUCCESS)
+  {
+    if (vapi_ret == VAPI_CQ_EMPTY)
+    {
+      osm_log( p_log, OSM_LOG_ERROR,
+               "osmt_send_trap_wait_for_forward: ERR 0130: "
+               "Timeout receiving mad (%s)\n",
+               VAPI_strerror_sym(vapi_ret) );
+      status = IB_TIMEOUT;
+    }
+    else
+    {
+      osm_log( p_log, OSM_LOG_ERROR,
+               "osmt_send_trap_wait_for_forward: ERR 0131: "
+               "Error receiving mad (%s)\n",
+               VAPI_strerror_sym(vapi_ret) );
+      status = IB_ERROR;
+    }
+    goto Exit;
+  }
+
+  /* check to see if successful - by examination of the subscribe bit */
+  p_sa_mad = (ib_sa_mad_t *)(p_qp_ctx->p_recv_buf + GRH_LEN);
+
+  if (p_sa_mad->method == IB_MAD_METHOD_REPORT)
+  {
+    if (p_sa_mad->attr_id == IB_MAD_ATTR_NOTICE)
+    {
+      osm_log( p_log, OSM_LOG_INFO,
+               "osmt_send_trap_wait_for_forward: "
+               "Received the Report!\n");
+      status = IB_SUCCESS;
+    }
+    else
+    {
+      osm_log( p_log, OSM_LOG_ERROR,
+               "osmt_send_trap_wait_for_forward: ERR 1020"
+               "Did not receive a Report(Notice) but attr:%d\n",
+               cl_ntoh16(p_sa_mad->attr_id)
+               );
+      status = IB_ERROR;
+    }
+  }
+  else
+  {
+    osm_log( p_log, OSM_LOG_ERROR,
+             "osmt_send_trap_wait_for_forward: ERR 1020"
+             "Received an Unexpected Method:%d\n",
+             p_smp->method
+             );
+    status = IB_ERROR;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return status;
+}
+
+/*
+ * Wait for a trap on QPn
+ *
+ */
+ib_api_status_t
+osmt_trap_wait( IN osmtest_t * const    p_osmt,
+                IN osmt_qp_ctx_t        *p_qp_ctx
+                )
+{
+  ib_smp_t  *p_smp = (ib_smp_t *)(p_qp_ctx->p_send_buf);
+  ib_sa_mad_t * p_sa_mad;
+  VAPI_ret_t vapi_ret;
+  VAPI_wc_desc_t wc_desc;
+  osm_log_t *p_log = &p_osmt->log;
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( p_log, osmt_trap_wait );
+
+  osm_log( p_log, OSM_LOG_INFO,
+           "osmt_trap_wait: "
+           "Waiting for Traps under QP:0x%X of SA LID:0x%X\n",
+           cl_ntoh16(p_osmt->local_port.sm_lid));
+
+  /* --------------------- RECV ------------------------- */
+  vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
+                                   p_qp_ctx->qp_bind_hndl.rq_cq_hndl,
+                                   &wc_desc,
+                                   // 200,
+                                   p_osmt->opt.wait_time * 100,
+                                   10000,
+                                   NULL);
+  if (vapi_ret != VAPI_SUCCESS)
+  {
+    if (vapi_ret == VAPI_CQ_EMPTY)
+    {
+      osm_log( p_log, OSM_LOG_ERROR,
+               "osmt_trap_wait: ERR 0130: "
+               "Timeout receiving mad (%s)\n",
+               VAPI_strerror_sym(vapi_ret) );
+      status = IB_TIMEOUT;
+    }
+    else
+    {
+      osm_log( p_log, OSM_LOG_ERROR,
+               "osmt_trap_wait: ERR 0131: "
+               "Error receiving mad (%s)\n",
+               VAPI_strerror_sym(vapi_ret) );
+      status = IB_ERROR;
+    }
+    goto Exit;
+  }
+
+  /* check to see if successful - by examination of the subscribe bit */
+  p_sa_mad = (ib_sa_mad_t *)(p_qp_ctx->p_recv_buf + GRH_LEN);
+
+  if (p_sa_mad->method == IB_MAD_METHOD_REPORT)
+  {
+    if (p_sa_mad->attr_id == IB_MAD_ATTR_NOTICE)
+    {
+      osm_log( &p_osmt->log, OSM_LOG_INFO,
+               "osmt_trap_wait: "
+               "Received the Report!\n");
+      status = IB_SUCCESS;
+    }
+    else
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_trap_wait: ERR 1020"
+               "Did not receive a Report(Notice) but attr:%d\n",
+               cl_ntoh16(p_sa_mad->attr_id)
+               );
+      status = IB_ERROR;
+    }
+  }
+  else
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_trap_wait: ERR 1020"
+             "Received an Unexpected Method:%d\n",
+             p_smp->method
+             );
+    status = IB_ERROR;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return status;
+}
+
+/*
+ * Initialize an inform info attribute:
+ * Catch all traps in the lid range of the p_osmt
+ *
+ */
+ib_api_status_t
+osmt_init_inform_info(IN osmtest_t * const p_osmt,
+                      OUT ib_inform_info_t* p_ii) {
+
+  memset(p_ii, 0, sizeof(ib_inform_info_t));
+  /*  p_ii->lid_range_begin = cl_hton16(1); */
+  p_ii->lid_range_begin = 0xFFFF;
+  p_ii->lid_range_end = cl_hton16(p_osmt->max_lid);
+  p_ii->is_generic = 1; /*  have to choose */
+  p_ii->trap_type = 0xFFFF; /*  ALL */
+  p_ii->g_or_v.generic.trap_num = 0xFFFF; /*  ALL */
+  p_ii->g_or_v.generic.node_type_lsb = 0xFFFF; /*  ALL */
+  p_ii->g_or_v.generic.node_type_msb = 0xFF; /*  ALL */
+  return IB_SUCCESS;
+}
+
+ib_api_status_t
+osmt_init_inform_info_by_trap (IN osmtest_t * const p_osmt,
+                              IN ib_net16_t trap_num,
+                              OUT ib_inform_info_t* p_ii) {
+
+  memset(p_ii, 0, sizeof(ib_inform_info_t));
+  /*  p_ii->lid_range_begin = cl_hton16(1); */
+  p_ii->lid_range_begin = 0xFFFF;
+  p_ii->lid_range_end = cl_hton16(p_osmt->max_lid);
+  p_ii->is_generic = 1; /*  have to choose */
+  p_ii->trap_type = 0xFFFF; /*  ALL */
+  p_ii->g_or_v.generic.trap_num = trap_num; /*  ALL */
+  p_ii->g_or_v.generic.node_type_lsb = 0xFFFF; /*  ALL */
+  p_ii->g_or_v.generic.node_type_msb = 0xFF; /*  ALL */
+  return IB_SUCCESS;
+}
+
+/*
+ * Run a complete inform info test flow:
+ * - try to unregister inform info (should fail)
+ * - register an inform info
+ * - try to unregister inform info (should succeed)
+ * - register an inform info
+ * - send a trap - sleep
+ * - check that a Report(Notice) arrived that match the sent one
+ *
+ */
+ib_api_status_t
+osmt_run_inform_info_flow( IN osmtest_t * const p_osmt ) {
+  ib_inform_info_t         inform_info;
+  ib_api_status_t status;
+  osmt_qp_ctx_t  qp_ctx;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmt_run_inform_info_flow);
+
+  /* bind the QP */
+  status = osmt_bind_inform_qp( p_osmt, &qp_ctx);
+  if (status != IB_SUCCESS)
+  {
+    goto Exit;
+  }
+
+  /* init the inform info */
+  osmt_init_inform_info(p_osmt, &inform_info);
+
+  /* first try to unsubscribe */
+  status = osmt_reg_unreg_inform_info(p_osmt,
+                                      &qp_ctx,
+                                      &inform_info,
+                                      0);
+  /* WAS IB_REMOTE_ERROR */
+  if (status != IB_REMOTE_ERROR)
+  {
+    if (status != IB_SUCCESS)
+    {
+      osm_log( &p_osmt->log, OSM_LOG_INFO,
+               "osmt_run_inform_info_flow:"
+               "Error during UnSubscribe: (%s)\n",
+               ib_get_err_str( status ));
+      goto Exit;
+    }
+    else
+    {
+      osm_log( &p_osmt->log, OSM_LOG_INFO,
+               "osmt_run_inform_info_flow:"
+               "Expected Failure to UnSubscribe non existing InformInfo\n");
+      status = IB_ERROR;
+      goto Exit;
+    }
+  }
+
+  /* send the inform info registration */
+  status = osmt_reg_unreg_inform_info(p_osmt,
+                                      &qp_ctx,
+                                      &inform_info,
+                                      1);
+  if (status != IB_SUCCESS)
+  {
+    goto Exit;
+  }
+
+  /* send a trap through QP0 and wait on QPN */
+  status = osmt_send_trap_wait_for_forward(p_osmt, &qp_ctx);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_INFO,
+             "osmt_run_inform_info_flow:"
+             "Error during Send Trap and Wait For Report: (%s)\n",
+             ib_get_err_str( status ));
+    goto Exit;
+  }
+
+  /* try to unsubscribe for cleanup */
+  status = osmt_reg_unreg_inform_info(p_osmt,
+                                      &qp_ctx,
+                                      &inform_info,
+                                      0);
+
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_INFO,
+             "osmt_run_inform_info_flow:"
+             "Error during UnSubscribe: (%s)\n",
+             ib_get_err_str( status ));
+    goto Exit;
+  }
+  else
+  {
+    if (status == IB_REMOTE_ERROR)
+    {
+      osm_log( &p_osmt->log, OSM_LOG_INFO,
+               "osmt_run_inform_info_flow:"
+               "Remote Error during UnSubscribe\n");
+      status = IB_ERROR;
+      goto Exit;
+    }
+  }
+
+ Exit:
+  osmt_unbind_inform_qp( p_osmt, &qp_ctx);
+  OSM_LOG_EXIT( &p_osmt->log );
+  return status;
+}
+
+/*
+ * Run a complete inform info test flow:
+ * - try to unregister inform info (should fail)
+ * - register an inform info
+ * - try to unregister inform info (should succeed)
+ * - register an inform info
+ * - send a trap - sleep
+ * - check that a Report(Notice) arrived that match the sent one
+ *
+ */
+ib_api_status_t
+osmt_run_trap64_65_flow( IN osmtest_t * const p_osmt) {
+  ib_inform_info_t         inform_info;
+  ib_api_status_t status;
+  osmt_qp_ctx_t  qp_ctx;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmt_run_trap64_65_flow);
+
+  /* bind the QP */
+  status = osmt_bind_inform_qp( p_osmt, &qp_ctx);
+  if (status != IB_SUCCESS)
+  {
+    goto Exit;
+  }
+
+  /* init the inform info */
+  osmt_init_inform_info_by_trap(p_osmt, 
+                                cl_hton16(64),
+                                &inform_info);
+
+  /* send the inform info registration */
+  status = osmt_reg_unreg_inform_info(p_osmt,
+                                      &qp_ctx,
+                                      &inform_info,
+                                      1);
+  if (status != IB_SUCCESS)
+  {
+    goto Exit;
+  }
+
+  /*--------------------- PREP -------------------------*/
+  if (osmt_mtl_mad_post_recv_bufs(
+        &qp_ctx.qp_bind_hndl,
+        qp_ctx.p_recv_buf,
+        1,   /* we need to receive the report */
+        GRH_LEN + MAD_BLOCK_SIZE,
+        1) != 1) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_trap64_65_flow: ERR 0127: "
+             "Error posting recv bufs for trap 64\n");
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+           "osmt_run_trap64_65_flow: "
+           "Posted recv bufs for trap 64\n");
+
+  /* init the inform info */
+  osmt_init_inform_info_by_trap(p_osmt, 
+                                cl_hton16(65), 
+                                &inform_info);
+
+  /* send the inform info registration */
+  status = osmt_reg_unreg_inform_info(p_osmt,
+                                      &qp_ctx,
+                                      &inform_info,
+                                      1);
+  if (status != IB_SUCCESS)
+  {
+    goto Exit;
+  }
+
+  /*--------------------- PREP -------------------------*/
+  if (osmt_mtl_mad_post_recv_bufs(
+        &qp_ctx.qp_bind_hndl,
+        qp_ctx.p_recv_buf,
+        1,   /* we need to reveive the report */
+        GRH_LEN + MAD_BLOCK_SIZE,
+        1) != 1) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_trap64_65_flow: ERR 0127: "
+             "Error posting recv bufs for trap 65\n");
+    status = IB_ERROR;
+    goto Exit;
+  }
+  osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+           "osmt_run_trap64_65_flow: "
+           "Posted recv bufs for trap 65\n");
+
+  /* Sleep for x seconds in order to allow external script trap generation */
+#if 0
+  sleep (p_osmt->opt.wait_time);
+#endif
+
+  /* wait for a trap on QPN */
+  status = osmt_trap_wait(p_osmt, &qp_ctx);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_INFO,
+             "osmt_run_trap64_65_flow:"
+             "Error during Send Trap and Wait For Report: (%s)\n",
+             ib_get_err_str( status ));
+    goto Exit;
+  }
+
+  /* try to unsubscribe for cleanup */
+  status = osmt_reg_unreg_inform_info(p_osmt,
+                                      &qp_ctx,
+                                      &inform_info,
+                                      0);
+
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_INFO,
+             "osmt_run_trap64_65_flow:"
+             "Error during UnSubscribe: (%s)\n",
+             ib_get_err_str( status ));
+    goto Exit;
+  }
+
+ Exit:
+  osmt_unbind_inform_qp( p_osmt, &qp_ctx);
+  OSM_LOG_EXIT( &p_osmt->log );
+  return status;
+}
+
+#endif /*  OSM_VENDOR_INTF_MTL */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_mtl_regular_qp.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_mtl_regular_qp.c
new file mode 100644 (file)
index 0000000..1df7e3b
--- /dev/null
@@ -0,0 +1,447 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osmt_mtl_regular_qp.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifdef OSM_VENDOR_INTF_MTL
+
+/*                  - Mellanox Confidential and Proprietary -
+ *
+ *  Copyright (C) Jul. 2001, Mellanox Technologies Ltd.  ALL RIGHTS RESERVED.
+ *
+ *  Except as specifically permitted herein, no portion of the information,
+ *  including but not limited to object code and source code, may be reproduced,
+ *  modified, distributed, republished or otherwise exploited in any form or by
+ *  any means for any purpose without the prior written permission of Mellanox
+ *  Technologies Ltd. Use of software subject to the terms and conditions
+ *  detailed in the file "LICENSE.txt".
+ *
+ *  End of legal section ......................................................
+ *
+ *  osmt_mtl_regular_qp.c - 
+ *    Provide Simple Interface for Sending and Receiving MADS through a regular QP
+ *
+ *  Creation date:
+ *
+ *  Version: $Id: osmt_mtl_regular_qp.c 571 2007-01-25 12:58:44Z sleybo $
+ *
+ *  Authors:
+ *    Eitan Zahavi
+ * 
+ *  Changes:
+ */           
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include <mtl_common.h>
+#include <vapi.h>
+#include <evapi.h>
+#include <vapi_common.h>
+#include <ib_defs.h>
+#include <osmt_mtl_regular_qp.h>
+#include <complib/cl_types.h>
+/*
+ * Initialize the QP etc.
+ * Given in res: port_num, max_outs_sq, max_outs_rq
+ */
+VAPI_ret_t osmt_mtl_get_qp_resources(IN OUT osmt_mtl_mad_res_t *res)
+{
+  VAPI_ret_t ret;
+  VAPI_hca_port_t     hca_port_info;
+  VAPI_qp_init_attr_t qp_init_attr;
+  VAPI_qp_prop_t      qp_prop;
+  VAPI_cqe_num_t      act_num;
+
+  /* Get HCA LID */
+  ret = VAPI_query_hca_port_prop(res->hca_hndl, res->port_num, &hca_port_info); VAPI_CHECK_RET;
+  res->slid =  hca_port_info.lid;
+
+  /* Get a PD */
+  ret = VAPI_alloc_pd(res->hca_hndl, &(res->pd_hndl)); VAPI_CHECK_RET;
+
+  /* Create CQ for RQ and SQ*/  /* TBD - Check we have enough act nums */
+  ret = VAPI_create_cq(res->hca_hndl, res->max_outs_sq + 1, &(res->sq_cq_hndl), &act_num);
+  VAPI_CHECK_RET;
+  ret = VAPI_create_cq(res->hca_hndl, res->max_outs_rq + 1, &(res->rq_cq_hndl), &act_num);
+  VAPI_CHECK_RET;
+
+
+  /* register event handlers for polling(block mode) internal use*/
+  /* ret= EVAPI_set_comp_eventh(res->hca_hndl,res->rq_cq_hndl, */
+  /*                            EVAPI_POLL_CQ_UNBLOCK_HANDLER,NULL,&(res->rq_cq_eventh)); */
+  /* VAPI_CHECK_RET; */
+  /* ret= EVAPI_set_comp_eventh(res->hca_hndl,res->sq_cq_hndl, */
+  /*                            EVAPI_POLL_CQ_UNBLOCK_HANDLER,NULL,&(res->sq_cq_eventh)); */
+  /* VAPI_CHECK_RET; */
+
+  /* Create QP */
+  qp_init_attr.cap.max_oust_wr_sq = res->max_outs_sq + 1;
+  qp_init_attr.cap.max_oust_wr_rq = res->max_outs_rq + 1;
+  qp_init_attr.cap.max_sg_size_sq = 4;
+  qp_init_attr.cap.max_sg_size_rq = 4;
+
+  qp_init_attr.pd_hndl            = res->pd_hndl;
+  qp_init_attr.rdd_hndl           = 0;
+  qp_init_attr.rq_cq_hndl         = res->rq_cq_hndl;
+  qp_init_attr.rq_sig_type        = VAPI_SIGNAL_ALL_WR; /* That's default for IB */
+  qp_init_attr.sq_cq_hndl         = res->sq_cq_hndl;
+  qp_init_attr.sq_sig_type        = VAPI_SIGNAL_REQ_WR;
+  qp_init_attr.ts_type            = VAPI_TS_UD;
+
+  ret= VAPI_create_qp(res->hca_hndl,&qp_init_attr,&(res->qp_hndl),&qp_prop);
+  VAPI_CHECK_RET;
+  res->qp_id.qp_num= qp_prop.qp_num;
+
+  return(VAPI_OK);
+}
+
+VAPI_ret_t osmt_mtl_qp_init(osmt_mtl_mad_res_t *res)
+{
+  VAPI_ret_t ret;
+
+  VAPI_qp_attr_t      qp_attr;
+  VAPI_qp_attr_mask_t qp_attr_mask;
+  VAPI_qp_cap_t       qp_cap;
+
+
+  /* 
+   * Change QP to INIT
+   *
+   */
+  QP_ATTR_MASK_CLR_ALL(qp_attr_mask);
+  qp_attr.qp_state = VAPI_INIT;
+  QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_QP_STATE);
+  qp_attr.pkey_ix  = 0;
+  QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_PKEY_IX);
+  qp_attr.port     = res->port_num;
+  QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_PORT);
+  qp_attr.qkey = res->qkey;
+  QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_QKEY);
+
+  /* If I do not set this mask, I get an error from HH. QPM should catch it */
+  ret = VAPI_modify_qp(res->hca_hndl, res->qp_hndl, &qp_attr, &qp_attr_mask, &qp_cap); VAPI_CHECK_RET;
+
+  return(ret);
+
+}
+
+VAPI_ret_t osmt_mtl_qp_2_rtr_rts(osmt_mtl_mad_res_t *res)
+{
+  VAPI_ret_t ret;
+
+  VAPI_qp_attr_t      qp_attr;
+  VAPI_qp_attr_mask_t qp_attr_mask;
+  VAPI_qp_cap_t       qp_cap;
+
+  /*
+   *  Change QP to RTR
+   *
+   */
+  QP_ATTR_MASK_CLR_ALL(qp_attr_mask);
+  qp_attr.qp_state = VAPI_RTR;
+  QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_QP_STATE);
+  /*   qp_attr.rq_psn   = 0;                */
+  /*   QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_RQ_PSN); */
+
+  ret = VAPI_modify_qp(res->hca_hndl, res->qp_hndl, &qp_attr, &qp_attr_mask, &qp_cap); VAPI_CHECK_RET;
+
+  /* 
+   * Change QP to RTS
+   *
+   */
+  QP_ATTR_MASK_CLR_ALL(qp_attr_mask);
+  qp_attr.qp_state   = VAPI_RTS;
+  QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_QP_STATE);
+  qp_attr.sq_psn   = 0;
+  QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_SQ_PSN);
+
+  ret = VAPI_modify_qp(res->hca_hndl,res->qp_hndl,&qp_attr,&qp_attr_mask,&qp_cap); VAPI_CHECK_RET;
+
+  return(ret);
+}
+
+VAPI_ret_t  osmt_mtl_mad_create_mr(osmt_mtl_mad_res_t *res)
+{
+
+  VAPI_ret_t  ret;
+
+  VAPI_mrw_t mr_in, mr_out;
+
+
+  res->buf_size = (MAD_SIZE + GRH_LEN) * (res->max_outs_sq + res->max_outs_rq + 1);
+
+  /* Register single memory address region for all buffers */
+  res->buf_ptr = VMALLOC(res->buf_size);
+
+  if (res->buf_ptr == ((VAPI_virt_addr_t)NULL)) {
+    ret = VAPI_EAGAIN;
+    VAPI_CHECK_RET;
+  }
+
+  /* Enable local and remote access to memory region */
+  mr_in.acl = VAPI_EN_LOCAL_WRITE | VAPI_EN_REMOTE_WRITE;
+  mr_in.l_key =0;
+  mr_in.pd_hndl = res->pd_hndl;
+  mr_in.r_key =0;
+  mr_in.size = res->buf_size;
+  ASSERT_VOIDP2UINTN(res->buf_ptr);
+  mr_in.start = (VAPI_virt_addr_t)(uintn_t)(res->buf_ptr);
+  mr_in.type = VAPI_MR;
+
+  ret = VAPI_register_mr(res->hca_hndl, &mr_in, &(res->mr_hndl), &mr_out); VAPI_CHECK_RET;
+
+  res->l_key = mr_out.l_key;
+
+  return(ret);
+}
+
+VAPI_ret_t osmt_mtl_init_opened_hca(osmt_mtl_mad_res_t* res)
+{
+  VAPI_ret_t  ret;
+
+  res->pd_hndl= VAPI_INVAL_HNDL;
+  res->rq_cq_hndl= VAPI_INVAL_HNDL;
+  res->sq_cq_hndl= VAPI_INVAL_HNDL;
+  res->sq_cq_eventh= VAPI_INVAL_HNDL;
+  res->rq_cq_eventh= VAPI_INVAL_HNDL;
+  res->qp_hndl= VAPI_INVAL_HNDL;
+  res->mr_hndl= VAPI_INVAL_HNDL;
+
+  /*
+   * Create QP
+   *
+   */
+  ret = osmt_mtl_get_qp_resources(res);
+  if (ret != VAPI_OK) {
+    return ret;
+  }
+
+  /*
+   * Move to init
+   *
+   */
+  ret = osmt_mtl_qp_init(res);
+  if (ret != VAPI_OK) {
+    return ret;
+  }
+
+
+  /*
+   * Initialize memory regions
+   *
+   */
+  ret = osmt_mtl_mad_create_mr(res);
+  if (ret != VAPI_OK) {
+    return ret;
+  }
+
+  /* only now move to RTR and RTS */
+  ret = osmt_mtl_qp_2_rtr_rts(res);
+  if (ret != VAPI_OK) {
+    return ret;
+  }
+
+  return VAPI_OK;
+}
+
+
+
+VAPI_ret_t osmt_mtl_mad_cleanup(osmt_mtl_mad_res_t *res)
+{
+  if (res->qp_hndl != VAPI_INVAL_HNDL) {
+    VAPI_destroy_qp(res->hca_hndl,res->qp_hndl);
+  }
+  if (res->sq_cq_eventh != VAPI_INVAL_HNDL) {
+    EVAPI_clear_comp_eventh(res->hca_hndl,res->sq_cq_eventh);
+  }
+  if (res->rq_cq_eventh != VAPI_INVAL_HNDL) {
+    EVAPI_clear_comp_eventh(res->hca_hndl,res->rq_cq_eventh);
+  }
+  if (res->rq_cq_hndl != VAPI_INVAL_HNDL) {
+    VAPI_destroy_cq(res->hca_hndl,res->rq_cq_hndl);
+  }
+  if (res->sq_cq_hndl != VAPI_INVAL_HNDL) {
+    VAPI_destroy_cq(res->hca_hndl,res->sq_cq_hndl);
+  }
+  if (res->mr_hndl != VAPI_INVAL_HNDL) {
+    VAPI_deregister_mr(res->hca_hndl,res->mr_hndl);
+  }
+  if (res->pd_hndl != VAPI_INVAL_HNDL) {
+    VAPI_dealloc_pd(res->hca_hndl,res->pd_hndl);
+  }
+#if 0
+  /* open/close of HCA should be done system wide - not per application */
+  if (res->hca_hndl != VAPI_INVAL_HNDL) {
+    VAPI_close_hca(res->hca_hndl);  /* TBD: HCA_open/close should be done on a system wide basis */
+  }
+#endif
+  return VAPI_OK;
+}
+
+VAPI_ret_t osmt_mtl_create_av(osmt_mtl_mad_res_t* res, int16_t dlid, VAPI_ud_av_hndl_t *avh_p)
+{
+  VAPI_ud_av_t av;
+  VAPI_ret_t ret;
+
+  av.dlid= dlid;
+  av.port= res->port_num;
+  av.sl = 0; /* dest->sl; */
+  av.src_path_bits= 0; /*  dest->ee_dlid.dst_path_bits; */
+  av.static_rate = 0;
+  /* GRH ? */
+  av.grh_flag= 0;
+
+  ret= VAPI_create_addr_hndl(res->hca_hndl,res->pd_hndl, &av,avh_p);
+  if (ret != VAPI_OK) {
+    MTL_ERROR1("%s: failed VAPI_create_addr_hndl (%s)\n", __func__,
+               VAPI_strerror_sym(ret));
+    return ret;
+  }
+  return VAPI_OK;
+}
+
+VAPI_ret_t osmt_mtl_mad_send(osmt_mtl_mad_res_t* res, VAPI_wr_id_t id, void* mad,
+                                                                         VAPI_qp_num_t dest_qp, IB_sl_t sl,u_int32_t dest_qkey, VAPI_ud_av_hndl_t avh)
+{
+  VAPI_sr_desc_t sr;
+  VAPI_sg_lst_entry_t sg_entry;
+  VAPI_ret_t ret;
+
+  /* building SEND request */
+  sr.opcode= VAPI_SEND;
+  sr.remote_ah= avh;
+  sr.remote_qp= dest_qp;
+  sr.remote_qkey= dest_qkey;
+
+  sr.id = id;
+  sr.set_se= FALSE;
+  sr.fence= FALSE;
+  sr.comp_type= VAPI_SIGNALED;
+  sr.sg_lst_len= 1;
+  sr.sg_lst_p= &sg_entry;
+  ASSERT_VOIDP2UINTN(mad);
+  sg_entry.addr= (VAPI_virt_addr_t)(uintn_t)(mad);
+  sg_entry.len= MAD_SIZE;
+  sg_entry.lkey= res->l_key;
+
+  ret= VAPI_post_sr(res->hca_hndl,res->qp_hndl,&sr);
+  if (ret != VAPI_OK) {
+    MTL_ERROR1(__FUNCTION__ ": failed VAPI_post_sr (%s)\n",
+               VAPI_strerror_sym(ret));
+    return ret;
+  }
+
+  return VAPI_OK;
+}
+
+int osmt_mtl_mad_post_recv_bufs(osmt_mtl_mad_res_t* res, void *buf_array,
+                                                                                 u_int32_t num_o_bufs,u_int32_t size, VAPI_wr_id_t start_id)
+{
+  uint32_t i;
+  void* cur_buf;
+  VAPI_rr_desc_t rr;
+  VAPI_sg_lst_entry_t sg_entry;
+  VAPI_ret_t ret;
+
+  rr.opcode= VAPI_RECEIVE;
+  rr.comp_type= VAPI_SIGNALED;  /* All with CQE (IB compliant) */
+  rr.sg_lst_len= 1; /* single buffers */
+  rr.sg_lst_p= &sg_entry;
+  sg_entry.lkey= res->l_key;
+  cur_buf = buf_array;
+  for (i= 0; i < num_o_bufs  ; i++ ) {
+    rr.id= start_id+i; /* WQE id used is the index to buffers ptr array */
+    ASSERT_VOIDP2UINTN(cur_buf);
+    sg_entry.addr= (VAPI_virt_addr_t)(uintn_t)cur_buf;
+    sg_entry.len= size;
+    memset(cur_buf,0x00,size);  /* fill with 0 */
+    ret= VAPI_post_rr(res->hca_hndl,res->qp_hndl,&rr);
+    if (ret != VAPI_OK) {
+      MTL_ERROR1(__FUNCTION__ ": failed posting RQ WQE (%s)\n",VAPI_strerror_sym(ret));
+      return i;
+    }
+    MTL_DEBUG4(__FUNCTION__ ": posted buf at %p\n",cur_buf);
+    cur_buf += size;
+  }
+
+  return i; /* num of buffers posted */
+}
+
+
+VAPI_ret_t osmt_mtl_mad_poll4cqe(VAPI_hca_hndl_t hca,VAPI_cq_hndl_t cq,
+                                                                                       VAPI_wc_desc_t *wc_desc_p,
+                                                                                       u_int32_t max_poll, u_int32_t poll_sleep,
+                                                                                       VAPI_ud_av_hndl_t *avh_p)
+{
+  VAPI_ret_t ret = VAPI_CQ_EMPTY;
+  u_int32_t poll_cnt= 0;
+
+
+  /* wait for something to arrive */
+  while ((ret == VAPI_CQ_EMPTY) && (poll_cnt < max_poll)) {
+    ret= VAPI_poll_cq(hca,cq,wc_desc_p);
+    /* don't sleep if we already succeeded) */
+    if (ret != VAPI_CQ_EMPTY) {
+      break;
+    }
+    usleep(poll_sleep);
+    poll_cnt++;
+  }
+
+  /* if passed an AVH to destory - do it */
+  if (avh_p != NULL) {
+        VAPI_destroy_addr_hndl(hca,*avh_p);
+  }
+
+  if ((poll_cnt == max_poll) && (ret == VAPI_CQ_EMPTY)) {
+    MTL_DEBUG1(__FUNCTION__ ": Failed to get completion on wq after %d polls.\n",max_poll);
+    return VAPI_CQ_EMPTY;
+  }
+
+  if (ret != VAPI_OK) {
+    MTL_DEBUG1(__FUNCTION__ ": VAPI_poll_cq failed with ret=%s on sq_cq\n",mtl_strerror_sym(ret));
+    return ret;
+  }
+
+  if (wc_desc_p->status != VAPI_SUCCESS) {
+    MTL_DEBUG1(__FUNCTION__ ": completion error (%d) detected\n",wc_desc_p->status);
+  }
+
+  return VAPI_OK;
+}
+
+#endif /*  OSM_VENDOR_INTF_MTL */
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_multicast.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_multicast.c
new file mode 100644 (file)
index 0000000..a393a42
--- /dev/null
@@ -0,0 +1,3500 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osmt_multicast.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *     Implementation of Multicast Member testing flow..
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+#ifndef __WIN__
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_map.h>
+#include "osmtest.h"
+
+/**********************************************************************
+ **********************************************************************/
+
+static void
+__osmt_print_all_multicast_records(
+  IN  osmtest_t * const p_osmt )
+{
+   uint32_t                i;
+   ib_api_status_t         status;
+   osmv_query_req_t        req;
+   osmv_user_query_t       user;
+   osmtest_req_context_t   context;
+   ib_member_rec_t        *mcast_record;
+
+   memset( &context, 0, sizeof( context ) );
+   memset( &req, 0, sizeof( req ) );
+   memset( &user, 0, sizeof( user ) );
+
+   user.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
+   user.attr_offset = ib_get_attr_offset(sizeof(*mcast_record));
+
+   req.query_type = OSMV_QUERY_USER_DEFINED;
+   req.timeout_ms = p_osmt->opt.transaction_timeout;
+   req.retry_cnt = 1;
+   req.flags = OSM_SA_FLAGS_SYNC;
+   context.p_osmt = p_osmt;
+   req.query_context = &context;
+   req.pfn_query_cb = osmtest_query_res_cb;
+   req.p_query_input = &user;
+
+   /* UnTrusted (SMKey of 0)  - get the multicast groups */
+   status = osmv_query_sa(p_osmt->h_bind, &req);
+
+   if (status != IB_SUCCESS || context.result.status != IB_SUCCESS) 
+   {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "__osmt_print_all_multicast_records: ERR 02B5: "
+               "Failed getting the multicast groups records - %s/%s\n", 
+               ib_get_err_str(status), 
+               ib_get_err_str(context.result.status) );
+      return;
+   }
+
+   osm_log( &p_osmt->log, OSM_LOG_INFO,
+            "\n                    |------------------------------------------|"
+            "\n                    |        Remaining Multicast Groups        |"
+            "\n                    |------------------------------------------|\n" );
+
+   for (i = 0; i < context.result.result_cnt; i++) {
+      mcast_record = osmv_get_query_mc_rec(context.result.p_result_madw, i);
+      osm_dump_mc_record(&p_osmt->log, mcast_record,OSM_LOG_INFO);
+    }
+
+   /* Trusted - now get the multicast group members */
+   req.sm_key = OSM_DEFAULT_SM_KEY;
+   status = osmv_query_sa(p_osmt->h_bind, &req);
+
+   if (status != IB_SUCCESS || context.result.status != IB_SUCCESS) 
+   {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "__osmt_print_all_multicast_records: ERR 02B6: "
+               "Failed getting the multicast group members records - %s/%s\n", 
+               ib_get_err_str(status), 
+               ib_get_err_str(context.result.status) );
+      return;
+   }
+
+   osm_log( &p_osmt->log, OSM_LOG_INFO,
+            "\n                    |--------------------------------------------------|"
+            "\n                    |        Remaining Multicast Group Members        |"
+            "\n                    |--------------------------------------------------|\n" );
+
+   for (i = 0; i < context.result.result_cnt; i++) {
+      mcast_record = osmv_get_query_mc_rec(context.result.p_result_madw, i);
+      osm_dump_mc_record(&p_osmt->log, mcast_record,OSM_LOG_INFO);
+   }
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static cl_status_t
+__match_mgids(
+  IN  const void* const   p_object,
+  IN  void*               context )
+{
+  ib_gid_t* p_mgid_context = (ib_gid_t  *)context;
+  ib_gid_t* p_mgid_list_item = (ib_gid_t*)p_object;
+  int32_t count;
+
+  count = memcmp(p_mgid_context, p_mgid_list_item, sizeof(ib_gid_t));
+  if(count == 0)
+    return CL_SUCCESS;
+  else
+    return CL_NOT_FOUND;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+osmt_query_mcast( IN osmtest_t * const p_osmt ) {
+  ib_api_status_t status = IB_SUCCESS;
+  osmv_user_query_t user;
+  osmv_query_req_t req;
+  osmtest_req_context_t context;
+  ib_member_rec_t *p_rec;
+  uint32_t i,num_recs = 0;
+  cl_list_t   mgids_list;
+  cl_list_t*  p_mgids_list;
+  cl_list_iterator_t  p_mgids_res;
+  cl_status_t cl_status;
+  cl_map_item_t *p_item,*p_next_item;
+  osmtest_mgrp_t *p_mgrp;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmt_query_mcast );
+
+  /*
+   * Do a blocking query for all Multicast Records in the subnet.
+   * The result is returned in the result field of the caller's
+   * context structure.
+   *
+   * The query structures are locals.
+   */
+
+  memset( &req, 0, sizeof( req ) );
+  memset( &user, 0, sizeof( user ) );
+
+  context.p_osmt = p_osmt;
+  user.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
+  user.attr_offset = ib_get_attr_offset( sizeof( ib_member_rec_t ) );
+
+  req.query_type = OSMV_QUERY_USER_DEFINED;
+  req.timeout_ms = p_osmt->opt.transaction_timeout;
+  req.retry_cnt = p_osmt->opt.retry_count;
+  req.flags = OSM_SA_FLAGS_SYNC;
+  req.query_context = &context;
+  req.pfn_query_cb = osmtest_query_res_cb;
+  req.p_query_input = &user;
+
+  status = osmv_query_sa( p_osmt->h_bind, &req );
+
+  if( status != IB_SUCCESS )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_query_mcast: ERR 0203: "
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  status = context.result.status;
+
+  if( status != IB_SUCCESS )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_query_mcast: ERR 0264: "
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );
+    if( status == IB_REMOTE_ERROR )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_query_mcast: "
+               "Remote error = %s.\n",
+               ib_get_mad_status_str( osm_madw_get_mad_ptr
+                                      ( context.result.
+                                        p_result_madw ) ) );
+    }
+    goto Exit;
+  }
+
+  /* ok we have got something */
+  /* First Delete the old MGID Table */
+  p_next_item = cl_qmap_head( &p_osmt->exp_subn.mgrp_mlid_tbl );
+  while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.mgrp_mlid_tbl ) )
+  {
+    p_item = p_next_item;
+    p_next_item = cl_qmap_next( p_item );
+    cl_qmap_remove_item(&p_osmt->exp_subn.mgrp_mlid_tbl,p_item);
+    free( p_item );
+
+  }
+
+  cl_list_construct(&mgids_list);
+  cl_list_init( &mgids_list, num_recs );
+  p_mgids_list = &mgids_list;
+  num_recs = context.result.result_cnt;
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_query_mcast: "
+           "Received %u records\n", num_recs );
+
+  for( i = 0; i < num_recs; i++ )
+  {
+    p_rec = osmv_get_query_result( context.result.p_result_madw, i );
+    p_mgids_res = cl_list_find_from_head ( p_mgids_list,__match_mgids,&(p_rec->mgid));
+    /* If returns iterator other than end of list, same mgid exists already */
+    if( p_mgids_res != cl_list_end( p_mgids_list ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_query_mcast: ERR 0265: "
+               "MCG MGIDs are the same - invalid MGID : 0x%016" PRIx64 " 0x%016"
+               PRIx64 "\n",
+               cl_ntoh64(p_rec->mgid.unicast.prefix),
+               cl_ntoh64(p_rec->mgid.unicast.interface_id));
+      status = IB_ERROR;
+      goto Exit;
+
+    }
+    osm_dump_mc_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );
+    cl_status = cl_list_insert_head(p_mgids_list,&(p_rec->mgid));
+    if (cl_status)
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_query_mcast: ERR 0205: "
+               "Could not add MGID to cl_list\n" );
+      status = IB_ERROR;
+      goto Exit;
+    }
+    p_mgrp = (osmtest_mgrp_t*)malloc( sizeof(*p_mgrp) );
+    if (!p_mgrp)
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_query_mcast: ERR 0204: "
+               "Could not allocate new MCG\n" );
+      status = IB_ERROR;
+      goto Exit;
+    }
+    memcpy(&p_mgrp->mcmember_rec,p_rec,sizeof(p_mgrp->mcmember_rec));
+    cl_qmap_insert(&p_osmt->exp_subn.mgrp_mlid_tbl,
+                   cl_ntoh16(p_rec->mlid),&p_mgrp->map_item);
+  }
+
+ Exit:
+  if( context.result.p_result_madw != NULL )
+  {
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+    context.result.p_result_madw = NULL;
+  }
+
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+/* given a multicast request send and wait for response. */
+ib_api_status_t
+osmt_send_mcast_request( IN osmtest_t * const p_osmt,
+                         IN uint8_t           is_set,
+                         IN ib_member_rec_t   *p_mc_req,
+                         IN uint64_t          comp_mask,
+                         OUT ib_sa_mad_t      *p_res
+                         ) {
+  osmtest_req_context_t context;
+  ib_api_status_t status = IB_SUCCESS;
+  osmv_user_query_t user;
+  osmv_query_req_t req;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmt_send_mcast_request );
+
+  /*
+   * Do a blocking query for this record in the subnet.
+   *
+   * The query structures are locals.
+   */
+  memset( &req, 0, sizeof( req ) );
+  memset( &user, 0, sizeof( user ) );
+  memset( &context, 0, sizeof( context ) );
+  memset( p_res, 0, sizeof( ib_sa_mad_t ) );
+
+  context.p_osmt = p_osmt;
+
+  user.p_attr = p_mc_req;
+  user.comp_mask = comp_mask;
+
+  if (is_set == 1)
+  {
+    req.query_type = OSMV_QUERY_UD_MULTICAST_SET;
+  } else if (is_set == 0) {
+    req.query_type = OSMV_QUERY_UD_MULTICAST_DELETE;
+  } else if (is_set == 0xee) {
+
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+             "osmt_send_mcast_request: Set USER DEFINED QUERY\n" );
+    req.query_type = OSMV_QUERY_USER_DEFINED;
+    user.method = IB_MAD_METHOD_GET;
+    user.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
+    user.attr_offset = ib_get_attr_offset( sizeof( ib_member_rec_t ) );
+  } else if (is_set == 0xff)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+             "osmt_send_mcast_request: Set USER DEFINED QUERY\n" );
+    req.query_type = OSMV_QUERY_USER_DEFINED;
+    user.method = IB_MAD_METHOD_SET;
+    user.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
+    user.attr_offset = ib_get_attr_offset( sizeof( ib_member_rec_t ) );
+  }
+
+  /* TODO : Check the validity of all user fields in order to use
+     OSMV_QUERY_USER_DEFINED
+     p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input;
+     if (p_user_query->method) sa_mad_data.method = p_user_query->method;
+     sa_mad_data.attr_offset = p_user_query->attr_offset;
+     sa_mad_data.attr_id = p_user_query->attr_id;
+     sa_mad_data.comp_mask = p_user_query->comp_mask;
+     sa_mad_data.p_attr = p_user_query->p_attr;
+  */
+
+  req.timeout_ms = p_osmt->opt.transaction_timeout;
+  req.retry_cnt = p_osmt->opt.retry_count;
+  req.flags = OSM_SA_FLAGS_SYNC;
+  req.query_context = &context;
+  req.pfn_query_cb = osmtest_query_res_cb;
+  req.p_query_input = &user;
+
+  status = osmv_query_sa( p_osmt->h_bind, &req );
+
+  if ( status != IB_SUCCESS )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_send_mcast_request: ERR 0206: "
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  /* ok it worked */
+  memcpy(p_res,
+         osm_madw_get_mad_ptr(context.result.p_result_madw),
+         sizeof(ib_sa_mad_t));
+
+  status = context.result.status;
+
+  if( status != IB_SUCCESS )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_send_mcast_request: ERR 0224: "
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );
+    if( status == IB_REMOTE_ERROR )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_send_mcast_request: "
+               "Remote error = %s\n",
+               ib_get_mad_status_str( osm_madw_get_mad_ptr
+                                      ( context.result.p_result_madw ) ) );
+    }
+  }
+
+ Exit:
+  /*
+   * Return the IB query MAD to the pool as necessary.
+   */
+  if( context.result.p_result_madw != NULL )
+  {
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+    context.result.p_result_madw = NULL;
+  }
+
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+void
+osmt_init_mc_query_rec(IN  osmtest_t * const p_osmt,
+                       IN OUT ib_member_rec_t  *p_mc_req) {
+  /* use default values so we can change only what we want later */
+  memset(p_mc_req, 0, sizeof(ib_member_rec_t));
+
+  /* we leave the MGID to the user */
+  memcpy(&p_mc_req->port_gid.unicast.interface_id,
+         &p_osmt->local_port.port_guid,
+         sizeof(p_osmt->local_port.port_guid)
+         );
+
+  /*  use our own subnet prefix: */
+  p_mc_req->port_gid.unicast.prefix = CL_HTON64(0xFE80000000000000ULL);
+
+  /*  ib_net32_t  qkey; */
+  /*  ib_net16_t  mlid; - we keep it zero for upper level to decide. */
+  /*  uint8_t     mtu; - keep it zero means - anything you have please. */
+  /*  uint8_t     tclass; can leave as zero for now (between subnets) */
+  /*  ib_net16_t  pkey; leave as zero */
+  p_mc_req->rate = IB_LINK_WIDTH_ACTIVE_4X;
+  /*  uint8_t     pkt_life; zero means greater than zero ... */
+  /*  ib_net32_t  sl_flow_hop; keep it all zeros */
+  /*  we want to use a link local scope: 0x02 */
+  p_mc_req->scope_state = ib_member_set_scope_state(0x02, 0);
+}
+
+/***********************************************************************
+ * UD Multicast testing flow:
+ * o15.0.1.3:
+ * - Request new MCG with not enough components in comp_mask :
+ *   ERR_INSUFFICIENT_COMPONENTS
+ * o15.0.1.8:
+ * - Request a join with irrelevant RATE and get a ERR_INVALID_REQ
+ * o15.0.1.4:
+ * - Create an MGID by asking for a join with MGID = 0
+ *   providing P_Key, Q_Key, SL, FlowLabel, Tclass.
+ * o15.0.1.5:
+ * - Check the returned MGID is valid. (p 804)
+ * o15.0.1.6:
+ * - Create a new MCG with valid requested MGID.
+ * - Try to create a new MCG with invalid MGID : get back ERR_REQ_INVALID
+ * - Try again with MGID prefix = 0xA01B (maybe 0x1BA0 little or big ?)
+ * - Try to create again the already created group: ERR_REQ_INVALID
+ * o15.0.1.7 - implicitlly checked during the prev steps.
+ * o15.0.1.9
+ * - Create MCG with Invalid JoinState.FullMember != 1 : get ERR_REQ_INVALID
+ * o15.0.1.10 - can't check on a single client .
+ * o15.0.1.11:
+ * - Try to join into a MGID that exists with JoinState=SendOnlyMember -
+ *   see that it updates JoinState. What is the routing change?
+ * - We can not check simple join since we have only one tester (for now)
+ * o15.0.1.12:
+ * - The last join should have a special treatment in the SA (sender only)
+ *   but what is it ?
+ * o15.0.1.13:
+ * - Try joining with wrong rate - ERR_REQ_INVALID
+ * o15.0.1.14:
+ * - Try partial delete - actually updating the join state. check it.
+ * - Register by InformInfo flow to receive trap 67 on MCG delete.
+ * - Try full delete (JoinState and should be 0)
+ * - Wait for trap 67.
+ * - Try joining (not full mem) again to see the group was deleted.
+ *   (should fail - o15.0.1.13)
+ * o15.0.1.15:
+ * - Try deletion of the IPoIB MCG and get: ERR_REQ_INVALID
+ * o15.0.1.16:
+ * - Try GetTable with PortGUID wildcarded and get back some groups.
+ ***********************************************************************/
+
+/* The following macro can be used only within the osmt_run_mcast_flow() function */
+#define IS_IPOIB_MGID(p_mgid) \
+           ( !memcmp(&osm_ipoib_good_mgid,    (p_mgid), sizeof(osm_ipoib_good_mgid)) || \
+             !memcmp(&osm_ts_ipoib_good_mgid, (p_mgid), sizeof(osm_ts_ipoib_good_mgid)) )
+
+ib_api_status_t
+osmt_run_mcast_flow( IN osmtest_t * const p_osmt ) {
+  ib_api_status_t status;
+  ib_member_rec_t mc_req_rec;
+  ib_member_rec_t *p_mc_res;
+  ib_sa_mad_t res_sa_mad;
+  uint64_t comp_mask = 0;
+  ib_net64_t remote_port_guid = 0x0;
+  cl_qmap_t *p_mgrp_mlid_tbl;
+  osmtest_mgrp_t *p_mgrp;
+  ib_gid_t special_mgid, tmp_mgid, proxy_mgid;
+  ib_net16_t invalid_mlid = 0x0;
+  ib_net16_t max_mlid = cl_hton16(0xFFFE), tmp_mlid;
+  boolean_t ReachedMlidLimit = FALSE;
+  int start_cnt = 0, cnt, middle_cnt = 0, end_cnt = 0;
+  int start_ipoib_cnt = 0, end_ipoib_cnt = 0;
+  int mcg_outside_test_cnt = 0, fail_to_delete_mcg = 0;
+  osmtest_req_context_t context;
+  ib_node_record_t *p_rec;
+  uint32_t num_recs = 0, i;
+  uint8_t mtu_phys = 0, rate_phys = 0;
+  cl_map_t test_created_mlids; /* List of all mlids created in this test */
+  ib_member_rec_t* p_recvd_rec;
+  boolean_t got_error = FALSE;
+
+  static ib_gid_t good_mgid = {
+    {
+      0xFF, 0x12, 0xA0, 0x1C,
+      0xFE, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00,
+      0x12, 0x34, 0x56, 0x78
+    }
+  };
+  static ib_gid_t osm_ipoib_mgid = {
+    {
+      0xff,                         /* multicast field */
+      0x12,                         /* scope */
+      0x40, 0x1b,                   /* IPv4 signature */
+      0xff, 0xff,                   /* 16 bits of P_Key (to be filled in) */
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 bits of zeros */
+      0xff, 0xff, 0xff, 0xee,          /* 32 bit IPv4 broadcast address */
+    },
+  };
+  static ib_gid_t osm_ts_ipoib_good_mgid = {
+    {
+      0xff,                           /* multicast field */
+      0x12,                           /* non-permanent bit,scope */
+      0x40, 0x1b,                     /* IPv4 signature */
+      0xff, 0xff,                     /* 16 bits of P_Key (to be filled in) */
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   /* 48 bits of zeros */
+      0x00, 0x00, 0x00, 0x01,            /* 32 bit IPv4 broadcast address */
+    },
+  };
+  static ib_gid_t osm_ipoib_good_mgid = {
+    {
+      0xff,                           /* multicast field */
+      0x12,                           /* non-permanent bit,scope */
+      0x40, 0x1b,                     /* IPv4 signature */
+      0xff, 0xff,                     /* 16 bits of P_Key (to be filled in) */
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   /* 48 bits of zeros */
+      0xff, 0xff, 0xff, 0xff,            /* 32 bit IPv4 broadcast address */
+    },
+  };
+  static ib_gid_t osm_link_local_mgid = {
+    {
+      0xFF, 0x02, 0x00, 0x00, 
+      0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x01
+    },
+  };
+
+  OSM_LOG_ENTER( &p_osmt->log, osmt_run_mcast_flow );
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "GetTable of all current MCGs...\n"
+           );
+  status = osmt_query_mcast( p_osmt );
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 2FF "
+             "GetTable of all records has failed!\n" );
+    goto Exit;
+  }
+
+  /* Initialize the test_created_mgrps map */
+  cl_map_construct(&test_created_mlids);
+  cl_map_init(&test_created_mlids, 1000);
+
+  p_mgrp_mlid_tbl = &p_osmt->exp_subn.mgrp_mlid_tbl;
+  osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+  p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+  /* Only when we are on single mode check flow - do the count comparison, otherwise skip */
+  if (p_osmt->opt.mmode == 1 || p_osmt->opt.mmode == 3)
+  {
+      start_cnt = cl_qmap_count(p_mgrp_mlid_tbl);
+      osm_log( &p_osmt->log, OSM_LOG_INFO,
+               "osmt_run_mcast_flow (start): "
+               "Number of MC Records found in SA DB is %d\n", start_cnt);
+  }
+
+  /* This flow is being added due to bug discovered using SilverStorm stack -
+     The bug was initializing MCast with MTU & RATE min values that do
+     not match the subnet capability, even though that OpenSM
+     reponds with the correct value it does not store it in the MCG.
+     We want the check a join request to already existing group (ipoib)
+     without using MTU or RATE then getting response from OpenSM with
+     the correct values then join again with them and get IB_SUCCESS
+     all the way
+  */
+
+  /* First validate IPoIB exist in the SA DB */
+  p_mgrp = (osmtest_mgrp_t*)cl_qmap_head( p_mgrp_mlid_tbl );
+  /* scan all available multicast groups in the DB and fill in the table */
+  while( p_mgrp != (osmtest_mgrp_t*)cl_qmap_end( p_mgrp_mlid_tbl ) )
+  {
+    /* search for ipoib mgid */
+    if (IS_IPOIB_MGID(&p_mgrp->mcmember_rec.mgid))
+    {
+      start_ipoib_cnt++;
+    }
+    else
+    {
+      osm_log( &p_osmt->log, OSM_LOG_INFO,
+               "osmt_run_mcast_flow: "
+               "Non-IPoIB MC Groups exist: mgid=0x%016" PRIx64 ":0x%016" PRIx64 "\n",
+               cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix),
+               cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id) );
+       mcg_outside_test_cnt++;
+    }
+
+    p_mgrp = (osmtest_mgrp_t*)cl_qmap_next( &p_mgrp->map_item );
+  }
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Found %d non-IPoIB MC Groups\n", mcg_outside_test_cnt );
+
+  if (start_ipoib_cnt)
+  {
+    /* o15-0.2.4 - Check a join request to already created MCG */
+    osm_log( &p_osmt->log, OSM_LOG_INFO,
+             "osmt_run_mcast_flow: "
+             "Found IPoIB MC Group, so we run SilverStorm Bug Flow...\n" );
+    /* Try to join first like IPoIB of SilverStorm */
+    memcpy(&mc_req_rec.mgid,&osm_ipoib_good_mgid,sizeof(ib_gid_t));
+    /* Request Join */
+    ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+    comp_mask =
+      IB_MCR_COMPMASK_MGID |
+      IB_MCR_COMPMASK_PORT_GID |
+      IB_MCR_COMPMASK_JOIN_STATE;
+
+    status = osmt_send_mcast_request(
+      p_osmt, 0xff, /* User Defined query Set */
+      &mc_req_rec,
+      comp_mask,
+      &res_sa_mad );
+
+    osm_log(&p_osmt->log, OSM_LOG_INFO,
+            "osmt_run_mcast_flow: "
+            "Joining an existing IPoIB multicast group\n");
+    osm_log(&p_osmt->log, OSM_LOG_INFO,
+            "osmt_run_mcast_flow: "
+            "Sent Join request with :\n\t\tport_gid=0x%016"PRIx64
+            ":0x%016" PRIx64 ", mgid=0x%016" PRIx64 ":0x%016" PRIx64
+            "\n\t\tjoin state= 0x%x, response is : %s\n",
+            cl_ntoh64(mc_req_rec.port_gid.unicast.prefix),
+            cl_ntoh64(mc_req_rec.port_gid.unicast.interface_id),
+            cl_ntoh64(mc_req_rec.mgid.unicast.prefix),
+            cl_ntoh64(mc_req_rec.mgid.unicast.interface_id),
+            (mc_req_rec.scope_state & 0x0F),
+            ib_get_err_str(status));
+    if (status != IB_SUCCESS)
+    {
+       osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                "osmt_run_mcast_flow: ERR 02B3: "
+                "Failed joining existing IPoIB MCGroup - got %s\n",
+                ib_get_err_str(status));
+       goto Exit;
+    }
+    /* Check MTU & Rate Value and resend with SA suggested values */
+    p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+    /* Prepare the mc_req_rec for the rest of the flow */
+    osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+    /*
+      We simulate the same situation as in SilverStorm - a response with the
+      exact RATE & MTU as the SA responded with. Actually the query
+      has included some more fields but we know that problem was
+      genereated by the RATE
+    */
+    osm_log(&p_osmt->log, OSM_LOG_INFO,
+            "osmt_run_mcast_flow: "
+            "Received attributes of MCG : \n\t\tMTU=0x%02X, RATE=0x%02X\n"
+            , p_mc_res->mtu,p_mc_res->rate);
+
+    mc_req_rec.mtu = p_mc_res->mtu;
+    mc_req_rec.rate = p_mc_res->rate;
+    /* Set feasible mtu & rate that will allow check the 
+        exact statement of OpenSM */
+    mtu_phys = p_mc_res->mtu;
+    rate_phys = p_mc_res->rate;
+
+    memcpy(&mc_req_rec.mgid, &osm_ipoib_good_mgid, sizeof(ib_gid_t));
+    /* Request Join */
+    ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+    comp_mask =
+      IB_MCR_COMPMASK_MGID |
+      IB_MCR_COMPMASK_PORT_GID |
+      IB_MCR_COMPMASK_JOIN_STATE |
+      IB_MCR_COMPMASK_MTU_SEL |
+      IB_MCR_COMPMASK_MTU |
+      IB_MCR_COMPMASK_RATE_SEL |
+      IB_MCR_COMPMASK_RATE;
+
+    osm_log(&p_osmt->log, OSM_LOG_INFO,
+            "osmt_run_mcast_flow: "
+            "Sending attributes of MCG : \n\t\tMTU=0x%02X, RATE=0x%02X\n"
+            , mc_req_rec.mtu, mc_req_rec.rate);
+    status = osmt_send_mcast_request( p_osmt, 0xff, /* User Defined query */
+                                      &mc_req_rec,
+                                      comp_mask,
+                                      &res_sa_mad );
+    osm_log(&p_osmt->log, OSM_LOG_INFO,
+            "osmt_run_mcast_flow: "
+            "Sent Join request using response values, response is : %s\n"
+            , ib_get_err_str(status));
+    if (status != IB_SUCCESS)
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_run_mcast_flow: ERR 02EF: "
+               "Query as Full Member of already existing ipoib group 0x%016"
+               PRIx64 ":0x%016" PRIx64 " has failed\n",
+               cl_ntoh64(mc_req_rec.mgid.unicast.prefix),
+               cl_ntoh64(mc_req_rec.mgid.unicast.interface_id));
+
+      goto Exit;
+    }
+    /* We do not want to leave the MCG since its IPoIB */
+  }
+
+  /**************************************************************************/
+  /* Check Get with invalid mlid */
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Get with invalid mlid...\n"
+           );
+  /* Request Get */
+  ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+  mc_req_rec.mlid = invalid_mlid;
+  comp_mask = IB_MCR_COMPMASK_MLID;
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+  status = osmt_send_mcast_request( p_osmt, 0xee, /* User Defined query Get */
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+  if (status == IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow : ERR 2E0 "
+             "SubnAdmGet with invalid mlid 0x%x succeeded\n",
+             cl_ntoh16(mc_req_rec.mlid));
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Prepare the mc_req_rec for the rest of the flow */
+  osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+  /**************************************************************************/
+  /* Check Get with invalid port guid */
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Get with invalid port guid (0x0) but valid interface ID : 0x%"
+            PRIx64 "...\n",
+           cl_ntoh64(mc_req_rec.port_gid.unicast.interface_id));
+
+  /* Request Get */
+  ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+  memset(&mc_req_rec.port_gid.unicast.interface_id, 0, sizeof(ib_net64_t));
+  comp_mask = IB_MCR_COMPMASK_GID;
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+  status = osmt_send_mcast_request( p_osmt, 0xee, /* User Defined query Get */
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+  if (status == IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow : ERR 2E4 "
+             "SubnAdmGet with invalid port guid succeeded\n" );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Prepare the mc_req_rec for the rest of the flow */
+  osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+  /**************************************************************************/
+
+  /* o15.0.1.3:  */
+  /* - Request Join with insufficient comp_mask */
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Join with insufficient comp mask qkey & pkey (o15.0.1.3)...\n"
+           );
+
+  /* no MGID */
+  memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t));
+  /* Request Join */
+  ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+
+  comp_mask =
+    IB_MCR_COMPMASK_MGID |
+    IB_MCR_COMPMASK_PORT_GID |
+    /* IB_MCR_COMPMASK_QKEY |  */
+    /* IB_MCR_COMPMASK_PKEY | intentionaly missed to raise the error */
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_RATE_SEL |
+    IB_MCR_COMPMASK_RATE;
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+           
+  if (status != IB_REMOTE_ERROR ||
+      (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+      IB_SA_MAD_STATUS_INSUF_COMPS) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02EE: "
+             "Expectedd REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Join with insufficient comp mask - sl (15.0.1.3)...\n"
+           );
+
+  /* no MGID */
+  memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t));
+  /* Request Join */
+  ib_member_set_join_state(&mc_req_rec,IB_MC_REC_STATE_FULL_MEMBER );
+
+  comp_mask =
+    IB_MCR_COMPMASK_MGID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    /* IB_MCR_COMPMASK_SL |  */
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_RATE_SEL |
+    IB_MCR_COMPMASK_RATE;
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+           
+  if (status != IB_REMOTE_ERROR ||
+      (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+      IB_SA_MAD_STATUS_INSUF_COMPS) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02ED: "
+             "Expectedd REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+  /* no MGID */
+  memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t));
+
+  mc_req_rec.mgid.raw[15] = 0x01;
+
+  p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Join with insufficient comp mask - flow label (o15.0.1.3)...\n"
+           );
+
+  /* Request Join */
+  ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+
+  comp_mask =
+    IB_MCR_COMPMASK_MGID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    /* IB_MCR_COMPMASK_FLOW | intentionaly missed to raise the error */
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_RATE_SEL |
+    IB_MCR_COMPMASK_RATE;
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+  if (status != IB_REMOTE_ERROR ||
+      (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+      IB_SA_MAD_STATUS_INSUF_COMPS) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02EC: "
+             "Expected REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+  p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Join with insufficient comp mask - tclass (o15.0.1.3)...\n"
+           );
+
+  /* Request Join */
+  ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER) ;
+
+  comp_mask =
+    IB_MCR_COMPMASK_MGID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    /* IB_MCR_COMPMASK_TCLASS |  Intentionally missed to raise an error */
+    IB_MCR_COMPMASK_RATE_SEL |
+    IB_MCR_COMPMASK_RATE;
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+  if (status != IB_REMOTE_ERROR ||
+      (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+      IB_SA_MAD_STATUS_INSUF_COMPS) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02EA: "
+             "Expected REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+  p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Join with insufficient comp mask - tclass qkey (o15.0.1.3)...\n"
+           );
+
+  /* no MGID */
+  /* memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t)); */
+  /* Request Join */
+  ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+
+  comp_mask =
+    IB_MCR_COMPMASK_MGID |
+    IB_MCR_COMPMASK_PORT_GID |
+    /* IB_MCR_COMPMASK_QKEY | intentionaly missed to raise the error */
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    /* IB_MCR_COMPMASK_TCLASS |  intentionaly missed to raise the error */
+    IB_MCR_COMPMASK_RATE_SEL |
+    IB_MCR_COMPMASK_RATE;
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+  if (status != IB_REMOTE_ERROR ||
+      (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+      IB_SA_MAD_STATUS_INSUF_COMPS) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02E9: "
+             "Expected REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* o15.0.1.8: */
+  /* - Request join with irrelevant RATE : get a ERR_INSUFFICIENT_COMPONENTS */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Join with unrealistic rate (o15.0.1.8)...\n"
+           );
+
+  /* impossible requested rate */
+  mc_req_rec.rate =
+    IB_LINK_WIDTH_ACTIVE_12X |
+    IB_PATH_SELECTOR_GREATER_THAN << 6;
+
+  comp_mask =
+    IB_MCR_COMPMASK_GID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_RATE_SEL |
+    IB_MCR_COMPMASK_RATE;
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+  if (status != IB_REMOTE_ERROR ||
+      res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0207: "
+             "Expected REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Check Valid value which is unreasonable now */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Join with unrealistic rate 120GB (o15.0.1.8)...\n"
+           );
+
+  /* impossible requested rate */
+  mc_req_rec.rate =
+    IB_PATH_RECORD_RATE_120_GBS |
+    IB_PATH_SELECTOR_GREATER_THAN << 6;
+
+  comp_mask =
+    IB_MCR_COMPMASK_GID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_RATE_SEL |
+    IB_MCR_COMPMASK_RATE;
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+  if (status != IB_REMOTE_ERROR ||
+      res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0208: "
+             "Expected REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Check Valid value which is unreasonable now */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Join with less than min rate 2.5GB (o15.0.1.8)...\n"
+           );
+
+  /* impossible requested rate */
+  mc_req_rec.rate =
+    IB_PATH_RECORD_RATE_2_5_GBS |
+    IB_PATH_SELECTOR_LESS_THAN << 6;
+
+  comp_mask =
+    IB_MCR_COMPMASK_GID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_RATE_SEL |
+    IB_MCR_COMPMASK_RATE;
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+  if (status != IB_REMOTE_ERROR ||
+      res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02AB: "
+             "Expected REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Checking above max value of MTU which is impossible */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Join with unrealistic mtu : \n\t\tmore than 4096 -"
+           " max (o15.0.1.8)...\n"
+           );
+
+  /* impossible requested mtu */
+  mc_req_rec.mtu = IB_MTU_LEN_4096 | IB_PATH_SELECTOR_GREATER_THAN << 6;
+
+  comp_mask =
+    IB_MCR_COMPMASK_GID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_MTU_SEL |
+    IB_MCR_COMPMASK_MTU;
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+  if (status != IB_REMOTE_ERROR ||
+      res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02AC: "
+             "Expected REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Checking below min value of MTU which is impossible */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Join with unrealistic mtu : \n\t\tless than 256 -"
+           " min (o15.0.1.8)...\n"
+           );
+
+  /* impossible requested mtu */
+  mc_req_rec.mtu = IB_MTU_LEN_256 | IB_PATH_SELECTOR_LESS_THAN << 6;
+
+  comp_mask =
+    IB_MCR_COMPMASK_GID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_MTU_SEL |
+    IB_MCR_COMPMASK_MTU;
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+  if (status != IB_REMOTE_ERROR ||
+      res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02AD: "
+             "Expected REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Join with unrealistic mtu (o15.0.1.8)...\n"
+           );
+
+  /* impossible requested mtu */
+  mc_req_rec.mtu = 0x6 | IB_PATH_SELECTOR_GREATER_THAN << 6;
+
+  comp_mask =
+    IB_MCR_COMPMASK_GID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_MTU_SEL |
+    IB_MCR_COMPMASK_MTU;
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+  if (status != IB_REMOTE_ERROR ||
+      res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02AE: "
+             "Expected REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+#if 0
+  /* Currently PacketLifeTime isn't checked in opensm */
+  /* Check PacketLifeTime as 0 */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Create with unrealistic packet life value less than 0 (o15.0.1.8)...\n"
+           );
+
+  /* impossible requested packet life */
+  mc_req_rec.pkt_life = 0 | IB_PATH_SELECTOR_LESS_THAN << 6;
+
+  comp_mask =
+    IB_MCR_COMPMASK_GID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_LIFE |
+    IB_MCR_COMPMASK_LIFE_SEL;
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+  if (status != IB_REMOTE_ERROR ||
+      res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02AF: "
+             "Expected REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+#endif
+
+  /* o15.0.1.4:  */
+  /* - Create an MGID by asking for a join with MGID = 0 */
+  /*   providing P_Key, Q_Key, SL, FlowLabel, Tclass. */
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Create given MGID=0 skip service level (o15.0.1.4)...\n"
+           );
+
+  osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+  p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+  /* no MGID */
+  memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t));
+  /* Request Join */
+  ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+
+  comp_mask =
+    IB_MCR_COMPMASK_MGID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    /* IB_MCR_COMPMASK_SL | Intentionally missed */
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_RATE_SEL |
+    IB_MCR_COMPMASK_RATE;
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+  if (status != IB_REMOTE_ERROR ||
+      (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+      IB_SA_MAD_STATUS_INSUF_COMPS) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02A8: "
+             "Expected REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Check that no same MCG in the SMDB */
+  status = osmt_query_mcast( p_osmt);
+
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02AA: "
+             "Could not get all MC Records in subnet, got:%s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+  /* Only when we are on single mode check flow - do the count comparison, otherwise skip */
+  if (p_osmt->opt.mmode == 1 || p_osmt->opt.mmode == 3)
+  {
+    middle_cnt = cl_qmap_count(&p_osmt->exp_subn.mgrp_mlid_tbl);
+    osm_log( &p_osmt->log, OSM_LOG_INFO,
+             "osmt_run_mcast_flow (post false create): "
+             "Number of MC Records found in SA DB is %d\n", middle_cnt);
+    if (middle_cnt != start_cnt)
+    {
+      osm_log( &p_osmt->log, OSM_LOG_INFO,
+               "osmt_run_mcast_flow: "
+               "Got different number of records stored in SA DB (before any creation)\n"
+               "Instead of %d got %d\n", start_cnt, middle_cnt);
+    }
+  }
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Create given MGID=0 skip Qkey and Pkey (o15.0.1.4)...\n"
+           );
+
+  osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+  p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+  /* no MGID */
+  memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t));
+  /* Request Join */
+  ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+
+  comp_mask =
+    IB_MCR_COMPMASK_MGID |
+    IB_MCR_COMPMASK_PORT_GID |
+    /* IB_MCR_COMPMASK_QKEY | */
+    /* IB_MCR_COMPMASK_PKEY | Intentionally missed */
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_RATE_SEL |
+    IB_MCR_COMPMASK_RATE;
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+  if (status != IB_REMOTE_ERROR ||
+      (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+      IB_SA_MAD_STATUS_INSUF_COMPS) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02A7: "
+             "Expected REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Bad Query o15.0.1.4 */
+
+  status = osmt_query_mcast( p_osmt);
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Create given MGID=0 skip TClass (o15.0.1.4)...\n"
+           );
+
+  osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+  p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+  /* no MGID */
+  memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t));
+  /* Request Join */
+  ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+
+  comp_mask =
+    IB_MCR_COMPMASK_MGID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    /* IB_MCR_COMPMASK_TCLASS |  Intentionally missed */
+    /* all above are required */
+    IB_MCR_COMPMASK_RATE_SEL |
+    IB_MCR_COMPMASK_RATE;
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+  if (status != IB_REMOTE_ERROR ||
+      (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+      IB_SA_MAD_STATUS_INSUF_COMPS) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02A6: "
+             "Expected REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Create given MGID=0 valid Set several options :\n\t\t"
+           "First above min RATE, Second less than max RATE\n\t\t"
+           "Third above min MTU, Second less than max MTU\n\t\t"
+           "Fifth exact MTU & RATE feasible, Sixth exact RATE feasible\n\t\t"
+           "Seventh exact MTU feasible (o15.0.1.4)...\n"
+           );
+
+  /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */
+
+  mc_req_rec.rate =
+    IB_LINK_WIDTH_ACTIVE_1X |
+    IB_PATH_SELECTOR_GREATER_THAN << 6;
+
+  comp_mask =
+    IB_MCR_COMPMASK_MGID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_RATE_SEL |
+    IB_MCR_COMPMASK_RATE;
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02A5: "
+             "Failed to create MCG for MGID=0 with higher than minimum RATE - got %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+  /* Save the mlid created in test_created_mlids map */
+  p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_run_mcast_flow: "
+           "created MGID:0x%016" PRIx64 " : "
+           "0x%016" PRIx64 " MLID:0x%04X\n",
+           cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+           cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+           cl_ntoh16( p_recvd_rec->mlid ));
+  cl_map_insert(&test_created_mlids,
+                cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+  /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */
+
+  mc_req_rec.rate =
+    IB_LINK_WIDTH_ACTIVE_12X |
+    IB_PATH_SELECTOR_LESS_THAN << 6;
+
+  comp_mask =
+    IB_MCR_COMPMASK_MGID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_RATE_SEL |
+    IB_MCR_COMPMASK_RATE;
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0211: "
+             "Failed to create MCG for MGID=0 with less than highest RATE - got %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+  /* Save the mlid created in test_created_mlids map */
+  p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_run_mcast_flow: "
+           "Created MGID:0x%016" PRIx64 " : "
+           "0x%016" PRIx64 " MLID:0x%04X\n",
+           cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+           cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+           cl_ntoh16( p_recvd_rec->mlid ));
+  cl_map_insert(&test_created_mlids,
+                cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+  /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */
+
+  mc_req_rec.mtu =  IB_MTU_LEN_4096 |
+    IB_PATH_SELECTOR_LESS_THAN << 6;
+
+  comp_mask =
+    IB_MCR_COMPMASK_MGID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_MTU_SEL |
+    IB_MCR_COMPMASK_MTU;
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0238: "
+             "Failed to create MCG for MGID=0 with less than highest MTU - got %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+  /* Save the mlid created in test_created_mlids map */
+  p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_run_mcast_flow: "
+           "Created MGID:0x%016" PRIx64 " : "
+           "0x%016" PRIx64 " MLID:0x%04X\n",
+           cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+           cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+           cl_ntoh16( p_recvd_rec->mlid ));
+  cl_map_insert(&test_created_mlids,
+                cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+  /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */
+  mc_req_rec.mtu =  IB_MTU_LEN_256 |
+    IB_PATH_SELECTOR_GREATER_THAN << 6;
+
+  comp_mask =
+    IB_MCR_COMPMASK_MGID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_MTU_SEL |
+    IB_MCR_COMPMASK_MTU;
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0239: "
+             "Failed to create MCG for MGID=0 with higher than lowest MTU - got %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+  /* Save the mlid created in test_created_mlids map */
+  p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_run_mcast_flow: "
+           "Created MGID:0x%016" PRIx64 " : "
+           "0x%016" PRIx64 " MLID:0x%04X\n",
+           cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+           cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+           cl_ntoh16( p_recvd_rec->mlid ));
+  cl_map_insert( &test_created_mlids,
+                 cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+  /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */
+  /* Using Exact feasible MTU & RATE */
+
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_run_mcast_flow: "
+           "Using Exact feasible MTU & RATE: "
+           "MTU = 0x%02X, RATE = 0x%02X\n",
+           mtu_phys, rate_phys );
+
+  mc_req_rec.mtu =  mtu_phys;
+  mc_req_rec.rate = rate_phys;
+
+  comp_mask =
+    IB_MCR_COMPMASK_MGID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_MTU_SEL |
+    IB_MCR_COMPMASK_MTU |
+    IB_MCR_COMPMASK_RATE_SEL |
+    IB_MCR_COMPMASK_RATE;
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0240: "
+             "Failed to create MCG for MGID=0 with exact MTU & RATE - got %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+  /* Save the mlid created in test_created_mlids map */
+  p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_run_mcast_flow: "
+           "Created MGID:0x%016" PRIx64 " : "
+           "0x%016" PRIx64 " MLID:0x%04X\n",
+           cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+           cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+           cl_ntoh16( p_recvd_rec->mlid ));
+  cl_map_insert(&test_created_mlids,
+                cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+  /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */
+  /* Using Exact feasible RATE */
+
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_run_mcast_flow: "
+           "Using Exact feasible RATE: 0x%02X\n",
+           rate_phys );
+
+  mc_req_rec.rate = rate_phys;
+
+  comp_mask =
+    IB_MCR_COMPMASK_MGID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_RATE_SEL |
+    IB_MCR_COMPMASK_RATE;
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0241: "
+             "Failed to create MCG for MGID=0 with exact RATE - got %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+  /* Save the mlid created in test_created_mlids map */
+  p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_run_mcast_flow: "
+           "Created MGID:0x%016" PRIx64 " : "
+           "0x%016" PRIx64 " MLID:0x%04X\n",
+           cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+           cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+           cl_ntoh16( p_recvd_rec->mlid ));
+           cl_map_insert(&test_created_mlids,
+           cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+   /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */
+   /* Using Exact feasible MTU */
+
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_run_mcast_flow: "
+           "Using Exact feasible MTU: 0x%02X\n",
+           mtu_phys );
+
+  mc_req_rec.mtu = mtu_phys;
+
+  comp_mask =
+    IB_MCR_COMPMASK_MGID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_MTU_SEL |
+    IB_MCR_COMPMASK_MTU;
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0242: "
+             "Failed to create MCG for MGID=0 with exact MTU - got %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+  /* Save the mlid created in test_created_mlids map */
+  p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_run_mcast_flow: "
+           "Created MGID:0x%016" PRIx64 " : "
+           "0x%016" PRIx64 " MLID:0x%04X\n",
+           cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+           cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+           cl_ntoh16( p_recvd_rec->mlid ));
+  cl_map_insert(&test_created_mlids,
+                cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+  /* o15.0.1.5: */
+  /* - Check the returned MGID is valid. (p 804) */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Validating resulting MGID (o15.0.1.5)...\n"
+           );
+  /* prefix 0xFF1 Scope 0xA01B */
+  /* Since we did not directly specified SCOPE in comp mask
+     we should get the comp mask that is link-local scope */
+  if ( (p_mc_res->mgid.multicast.header[0] != 0xFF) ||
+       (p_mc_res->mgid.multicast.header[1] != 0x12) ||
+       (p_mc_res->mgid.multicast.raw_group_id[0] != 0xA0) ||
+       (p_mc_res->mgid.multicast.raw_group_id[1] != 0x1B) )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0209: "
+             "Validating MGID failed. MGID:0x%016" PRIx64 ":%016" PRIx64 "\n",
+             cl_ntoh64( p_mc_res->mgid.unicast.prefix ),
+             cl_ntoh64( p_mc_res->mgid.unicast.interface_id )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */
+  /* Using feasible GREATER_THAN 0 packet lifitime */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Create given MGID=0 (o15.0.1.4)...\n"
+           );
+
+  status = osmt_query_mcast(p_osmt);
+
+  osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+  p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+  /* no MGID */
+  memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t));
+  /* Request Join */
+  ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+
+  mc_req_rec.pkt_life = 0 | IB_PATH_SELECTOR_GREATER_THAN << 6;
+
+  comp_mask =
+    IB_MCR_COMPMASK_MGID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_LIFE |
+    IB_MCR_COMPMASK_LIFE_SEL;
+
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0210: "
+             "Failed to create MCG for MGID=0 - got %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+  /* Save the mlid created in test_created_mlids map */
+  p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_run_mcast_flow: "
+           "Created MGID:0x%016" PRIx64 " : "
+           "0x%016" PRIx64 " MLID:0x%04X\n",
+           cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+           cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+           cl_ntoh16( p_recvd_rec->mlid ));
+  cl_map_insert(&test_created_mlids,
+                cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+  /* o15.0.1.6: */
+  /* - Create a new MCG with valid requested MGID. */
+  osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+  mc_req_rec.mgid = good_mgid;
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Create given valid MGID=0x%016" PRIx64 " : "
+           "0x%016" PRIx64 " (o15.0.1.6)...\n",
+           cl_ntoh64(mc_req_rec.mgid.unicast.prefix),
+           cl_ntoh64(mc_req_rec.mgid.unicast.interface_id));
+
+  /* Before creation, need to check that this group doesn't exist */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Verifying that MCGroup with this MGID doesn't exist by trying to Join it (o15.0.1.13)...\n" );
+
+  ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_NON_MEMBER);
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+  status = osmt_send_mcast_request( p_osmt, 1, /* join */
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+  if ((status != IB_REMOTE_ERROR) ||
+      (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID))
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0301: "
+             "Tried joining group that shouldn't have existed - got %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Set State to full member to allow group creation */
+  ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Now creating group with given valid MGID=0x%016" PRIx64 " : "
+           "0x%016" PRIx64 " (o15.0.1.6)...\n",
+           cl_ntoh64(mc_req_rec.mgid.unicast.prefix),
+           cl_ntoh64(mc_req_rec.mgid.unicast.interface_id));
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0211: "
+             "Failed to create MCG for MGID=0x%016" PRIx64 " : "
+             "0x%016" PRIx64 " (o15.0.1.6) - got %s/%s\n",
+             cl_ntoh64(good_mgid.unicast.prefix),
+             cl_ntoh64(good_mgid.unicast.interface_id),
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad)) );
+    goto Exit;
+  }
+
+  /* Save the mlid created in test_created_mlids map */
+  p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_run_mcast_flow: "
+           "Created MGID:0x%016" PRIx64 " : "
+           "0x%016" PRIx64 " MLID:0x%04X\n",
+           cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+           cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+           cl_ntoh16( p_recvd_rec->mlid ));
+  cl_map_insert(&test_created_mlids,
+                cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Validating resulting MGID (o15.0.1.6)...\n"
+           );
+  /* prefix 0xFF1 Scope 0xA01B */
+  if ( (p_mc_res->mgid.multicast.header[0] != 0xFF) ||
+       (p_mc_res->mgid.multicast.header[1] != 0x12) ||  /* HACK hardcoded scope = 0x02 */
+       (p_mc_res->mgid.multicast.raw_group_id[0] != 0xA0) ||
+       (p_mc_res->mgid.multicast.raw_group_id[1] != 0x1C) )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0212: "
+             "Validating MGID failed. MGID:0x%016" PRIx64 ":%016" PRIx64 "\n",
+             cl_ntoh64( p_mc_res->mgid.unicast.prefix ),
+             cl_ntoh64( p_mc_res->mgid.unicast.interface_id )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* - Try to create a new MCG with invalid MGID : get back ERR_REQ_INVALID */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking BAD MGID=0xFA..... (o15.0.1.6)...\n"
+           );
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+  
+  mc_req_rec.mgid.raw[0] = 0xFA;
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+  if ((status != IB_REMOTE_ERROR) ||
+      (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0213: "
+             "Failed to recognize MGID error for MGID=0xFA - got %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* - Try again with MGID prefix = 0xA01B (maybe 0x1BA0 little or big ?) */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking BAD MGID=0xFF12A01B..... with link-local scope (o15.0.1.6)...\n"
+           );
+
+  mc_req_rec.mgid.raw[0] = 0xFF;
+  mc_req_rec.mgid.raw[3] = 0x1B;
+  comp_mask = comp_mask | IB_MCR_COMPMASK_SCOPE;
+  mc_req_rec.scope_state = mc_req_rec.scope_state & 0x2F; /* local scope */
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+  
+  if ((status != IB_REMOTE_ERROR) ||
+      (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0214: "
+             "Failed to recognize MGID error for A01B with link-local bit (status %s) (rem status %s)\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Change the mgid prefix - get back ERR_REQ_INVALID */
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking BAD MGID PREFIX=0xEF... (o15.0.1.6)...\n"
+           );
+
+  mc_req_rec.mgid = good_mgid;
+
+  mc_req_rec.mgid.raw[0] = 0xEF;
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+           
+  if ((status != IB_REMOTE_ERROR) ||
+      (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0215: "
+             "Failed to recognize MGID PREFIX error for MGID=0xEF - got %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Change the scope to reserved - get back VALID REQ */
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking local scope with full member \n\t\tand valid mgid 0x%016"
+           PRIx64 ":0x%016" PRIx64 "  ... (o15.0.1.6)...\n",
+           cl_ntoh64(mc_req_rec.mgid.unicast.prefix),
+           cl_ntoh64(mc_req_rec.mgid.unicast.interface_id));
+
+  mc_req_rec.mgid = good_mgid;
+
+  mc_req_rec.mgid.raw[1] = 0x1F;
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0216: "
+             "Failed to create MCG for MGID=0x%016" PRIx64 " : "
+             "0x%016" PRIx64 " - got %s/%s\n",
+             cl_ntoh64(good_mgid.unicast.prefix),
+             cl_ntoh64(good_mgid.unicast.interface_id),
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) );
+    goto Exit;
+  }
+
+  /* Save the mlid created in test_created_mlids map */
+  p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_run_mcast_flow: "
+           "Created MGID:0x%016" PRIx64 " : "
+           "0x%016" PRIx64 " MLID:0x%04X\n",
+           cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+           cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+           cl_ntoh16( p_recvd_rec->mlid ));
+           cl_map_insert(&test_created_mlids,
+           cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+  /* Change the flags to invalid value 0x2 - get back INVALID REQ */
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking invalid flags=0xFF 22  ... (o15.0.1.6)...\n"
+           );
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+
+  mc_req_rec.mgid = good_mgid;
+
+  mc_req_rec.mgid.raw[1] = 0x22;
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+  if ((status != IB_REMOTE_ERROR) ||
+      (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0217: "
+             "Failed to recognize create with invalid flags value 0x2 - got %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Change the MGID to link local MGID  - get back VALID REQ */
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking link local MGID 0xFF02:0:0:0:0:0:0:1 (o15.0.1.6)...\n"
+           );
+
+  mc_req_rec.mgid = osm_link_local_mgid;
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0218: "
+             "Failed to create MCG for MGID=0xFF02:0:0:0:0:0:0:1 - got %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+  /* Save the mlid created in test_created_mlids map */
+  p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_run_mcast_flow: "
+           "Created MGID:0x%016" PRIx64 " : "
+           "0x%016" PRIx64 " MLID:0x%04X\n",
+           cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+           cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+           cl_ntoh16( p_recvd_rec->mlid ));
+           cl_map_insert(&test_created_mlids,
+           cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+  /* o15.0.1.7 - implicitlly checked during the prev steps. */
+  /* o15.0.1.8 - implicitlly checked during the prev steps. */
+
+  /* o15.0.1.9 */
+  /* - Create MCG with Invalid JoinState.FullMember != 1 : get ERR_REQ_INVALID */
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking new MGID with invalid join state (o15.0.1.9)...\n"
+           );
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+
+  mc_req_rec.mgid = good_mgid;
+  mc_req_rec.mgid.raw[12] = 0xFF;
+  mc_req_rec.scope_state = 0x22; /* link-local scope, non-member state */
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+           
+  if ((status != IB_REMOTE_ERROR) ||
+      (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0219: "
+             "Failed to recognize create with JoinState != FullMember - got %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Lets try a valid join scope state */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking new MGID with valid join state (o15.0.1.9)...\n"
+           );
+
+  mc_req_rec.mgid = good_mgid;
+  mc_req_rec.scope_state = 0x23; /* link-local scope, non member and full member */
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0220: "
+             "Failed to create MCG with valid join state 0x3 - got %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+  /* Save the mlid created in test_created_mlids map */
+  p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_run_mcast_flow: "
+           "Created MGID:0x%016" PRIx64 " : "
+           "0x%016" PRIx64 " MLID:0x%04X\n",
+           cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+           cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+           cl_ntoh16( p_recvd_rec->mlid ) );
+           cl_map_insert( &test_created_mlids,
+           cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+  /* Lets try another invalid join scope state */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking new MGID with invalid join state (o15.0.1.9)...\n"
+           );
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+
+  /* We have created a new MCG so now we need different mgid when cresting group otherwise it will be counted as join request .*/
+  mc_req_rec.mgid = good_mgid;
+  mc_req_rec.mgid.raw[12] = 0xFC;
+
+  mc_req_rec.scope_state = 0x24; /* link-local scope, send only member */
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+           
+  if ((status != IB_REMOTE_ERROR) ||
+      (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0221: "
+             "Failed to recognize create with JoinState != FullMember - got %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Lets try another valid join scope state */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking new MGID creation with valid join state (o15.0.1.9)...\n"
+           );
+
+  mc_req_rec.mgid = good_mgid;
+  mc_req_rec.mgid.raw[12] = 0xFB;
+  memcpy(&special_mgid, &mc_req_rec.mgid, sizeof(ib_gid_t));
+  mc_req_rec.scope_state = 0x2F; /* link-local scope, Full member with all other bits turned on */
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0222: "
+             "Failed to create MCG with valid join state 0xF - got %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+  /* Save the mlid created in test_created_mlids map */
+  p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_run_mcast_flow: "
+           "Created MGID:0x%016" PRIx64 " : "
+           "0x%016" PRIx64 " MLID:0x%04X\n",
+           cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+           cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+           cl_ntoh16( p_recvd_rec->mlid ));
+           cl_map_insert(&test_created_mlids,
+           cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+  /* o15.0.1.10 - can't check on a single client .-- obsolete -
+     checked by SilverStorm bug o15-0.2.4, never the less recheck */
+  /* o15-0.2.4 - Check a join request to already created MCG */
+  p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Check o15-0.2.4 statement...\n" );
+  /* Try to join */
+  memcpy(&mc_req_rec.mgid,&p_mc_res->mgid,sizeof(ib_gid_t));
+  /* Request Join */
+  ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_NON_MEMBER);
+  comp_mask =
+    IB_MCR_COMPMASK_MGID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_JOIN_STATE;
+
+  status = osmt_send_mcast_request( p_osmt, 0x1, /* User Defined query */
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02CC: "
+             "Failed to join MCG with valid req, returned status = %s\n",
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ));
+    goto Exit;
+  }
+
+  /* o15.0.1.11: */
+  /* - Try to join into a MGID that exists with JoinState=SendOnlyMember -  */
+  /*   see that it updates JoinState. What is the routing change? */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Retry of existing MGID - See JoinState update (o15.0.1.11)...\n"
+           );
+
+  mc_req_rec.mgid = good_mgid;
+  mc_req_rec.scope_state = 0x22; /* link-local scope, send only  member */
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02CD: "
+             "Failed to update existing MGID - got %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Validating Join State update with NonMember (o15.0.1.11)...\n"
+           );
+
+  if (p_mc_res->scope_state != 0x23) /* scope is LSB */
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02CE: "
+             "Validating JoinState update failed. Expected 0x23 got: 0x%02X\n",
+             p_mc_res->scope_state
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Try delete current join state then update it with another value  */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking JoinState update request should return 0x22 (o15.0.1.11)...\n"
+           );
+
+  mc_req_rec.rate =
+    IB_LINK_WIDTH_ACTIVE_1X |
+    IB_PATH_SELECTOR_GREATER_THAN << 6;
+  mc_req_rec.mgid = good_mgid;
+  /* link-local scope, non member (so we should not be able to delete) */
+  /*  but the FullMember bit should be gone */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Partially delete JoinState (o15.0.1.14)...\n"
+           );
+  mc_req_rec.scope_state = 0x22;
+  status = osmt_send_mcast_request( p_osmt, 0,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  if ((status != IB_SUCCESS) || (p_mc_res->scope_state != 0x21))
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02CF: "
+             "Failed to partially update JoinState : %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* So far successfully delete state - Now change it */
+  mc_req_rec.mgid = good_mgid;
+  mc_req_rec.scope_state = 0x24; /* link-local scope, send only  member */
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02C0: "
+             "Failed to update existing MCG - got %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Validating Join State update with Send Only Member (o15.0.1.11)...\n"
+           );
+
+  if (p_mc_res->scope_state != 0x25) /* scope is MSB */
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02C1: "
+             "Validating JoinState update failed. Expected 0x25 got: 0x%02X\n",
+             p_mc_res->scope_state
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+  /* Now try to update value of join state */
+  mc_req_rec.scope_state = 0x21; /* link-local scope, full member */
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02C2: "
+             "Failed to update existing MGID - got %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Validating Join State update with Full Member\n\t\t"
+           "to an existing 0x5 state MCG (o15.0.1.11)...\n" );
+
+  if (p_mc_res->scope_state != 0x25) /* scope is LSB */
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02C3: "
+             "Validating JoinState update failed. Expected 0x25 got: 0x%02X\n",
+             p_mc_res->scope_state
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Now try to update value of join state */
+  mc_req_rec.scope_state = 0x22; /* link-local scope,non member */
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02C4: "
+             "Failed to update existing MGID - got %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Validating Join State update with Non Member\n\t\t"
+           "to an existing 0x5 state MCG (o15.0.1.11)...\n" );
+
+  if (p_mc_res->scope_state != 0x27) /* scope is LSB */
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02C5: "
+             "Validating JoinState update failed. Expected 0x27 got: 0x%02X\n",
+             p_mc_res->scope_state
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "DEBUG - Current scope_state value : 0x%02X...\n", p_mc_res->scope_state );
+
+  /* - We can not check simple join since we have only one tester (for now) */
+
+  /* o15.0.1.12: Not Supported */
+  /* - The SendOnlyNonMem join should have a special treatment in the
+       SA but what is it ? */
+
+  /* o15.0.1.13: */
+  /* - Try joining with rate that does not exist in any MCG -
+       ERR_REQ_INVALID */
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking BAD RATE when connecting to existing MGID (o15.0.1.13)...\n"
+           );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+
+  mc_req_rec.mgid = good_mgid;
+  mc_req_rec.rate =
+    IB_LINK_WIDTH_ACTIVE_1X |
+    IB_PATH_SELECTOR_LESS_THAN << 6;
+  comp_mask =
+    IB_MCR_COMPMASK_GID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_RATE_SEL |
+    IB_MCR_COMPMASK_RATE;
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+           
+  if ((status != IB_REMOTE_ERROR) ||
+      (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02C6: "
+             "Failed to catch BAD RATE joining an exiting MGID: %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Try MTU that does not exist in any MCG */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking BAD MTU (higher them max) when connecting to "
+           "existing MGID (o15.0.1.13)...\n"
+           );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+
+  mc_req_rec.mgid = osm_ipoib_mgid;
+  mc_req_rec.mtu =
+    IB_MTU_LEN_4096 |
+    IB_PATH_SELECTOR_GREATER_THAN << 6;
+  comp_mask =
+    IB_MCR_COMPMASK_GID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_MTU_SEL |
+    IB_MCR_COMPMASK_MTU;
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+           
+  if ((status != IB_REMOTE_ERROR) ||
+      (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02C7: "
+             "Failed to catch BAD RATE (higher them max) joining an exiting MGID: %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Try another MTU that does not exist in any MCG */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking BAD MTU (less than min) when connecting "
+           "to existing MGID (o15.0.1.13)...\n"
+           );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+
+  mc_req_rec.mgid = osm_ipoib_mgid;
+  mc_req_rec.mtu =
+    IB_MTU_LEN_256 |
+    IB_PATH_SELECTOR_LESS_THAN << 6;
+  comp_mask =
+    IB_MCR_COMPMASK_GID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_MTU_SEL |
+    IB_MCR_COMPMASK_MTU;
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+           
+  if ((status != IB_REMOTE_ERROR) ||
+      (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02C8: "
+             "Failed to catch BAD RATE (less them min) joining an exiting MGID: %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* o15.0.1.14: */
+  /* - Try partial delete - actually updating the join state. check it. */
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking partial JoinState delete request - removing NonMember (o15.0.1.14)...\n"
+           );
+
+  mc_req_rec.rate =
+    IB_LINK_WIDTH_ACTIVE_1X |
+    IB_PATH_SELECTOR_GREATER_THAN << 6;
+  mc_req_rec.mgid = good_mgid;
+  comp_mask =
+    IB_MCR_COMPMASK_GID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_RATE_SEL |
+    IB_MCR_COMPMASK_RATE;
+  /* link-local scope, non member (so we should not be able to delete) */
+  /* but the FullMember bit should be gone */
+  mc_req_rec.scope_state = 0x22;
+
+  status = osmt_send_mcast_request( p_osmt, 0,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02C9: "
+             "Fail to partially update JoinState during delete: %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Validating Join State removal of Non Member bit (o15.0.1.14)...\n"
+           );
+  if (p_mc_res->scope_state != 0x25) /* scope is MSB - now only the non member & send only member have left */
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02CA: "
+             "Validating JoinState update failed. Expected 0x25 got: 0x%02X\n",
+             p_mc_res->scope_state
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Now use the same scope_state and delete all JoinState - leave multicast group since state is 0x0 */
+
+  mc_req_rec.scope_state = 0x25;
+  status = osmt_send_mcast_request( p_osmt, 0,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02CB: "
+             "Failed to update JoinState during delete: %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Validating Join State update remove (o15.0.1.14)...\n"
+           );
+
+  if (p_mc_res->scope_state != 0x25) /* scope is MSB - now only 0x0 so port is removed from MCG */
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02BF: "
+             "Validating JoinState update failed. Expected 0x25 got: 0x%02X\n",
+             p_mc_res->scope_state
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* - Try joining (not full mem) again to see the group was deleted. (should fail) */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Delete by trying to Join deleted group (o15.0.1.13)...\n"
+           );
+
+  mc_req_rec.scope_state = 0x22; /* use non member - so if no group fail */
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+  status = osmt_send_mcast_request( p_osmt, 1, /* join */
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+  
+  if (status != IB_REMOTE_ERROR)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02BC: "
+             "Succeeded Joining Deleted Group: %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* - Try deletion of the IPoIB MCG and get: ERR_REQ_INVALID */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking BAD Delete of Mgid membership (no prev join) (o15.0.1.15)...\n"
+           );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+
+  mc_req_rec.mgid = osm_ipoib_mgid;
+  mc_req_rec.rate =
+    IB_LINK_WIDTH_ACTIVE_1X |
+    IB_PATH_SELECTOR_GREATER_THAN << 6;
+  mc_req_rec.scope_state = 0x21; /* delete full member */
+
+  status = osmt_send_mcast_request( p_osmt, 0, /* delete flag */
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+           
+  if ((status != IB_REMOTE_ERROR) ||
+      (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02BD: "
+             "Failed to catch BAD delete from IPoIB: %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Prepare another MCG for the following tests : */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Create given MGID=0x%016" PRIx64 " : "
+           "0x%016" PRIx64 "\n\t\t(o15.0.1.4)...\n",
+           cl_ntoh64(osm_ipoib_mgid.unicast.prefix),
+           cl_ntoh64(osm_ipoib_mgid.unicast.interface_id) );
+
+  mc_req_rec.mgid = good_mgid;
+  mc_req_rec.mgid.raw[12] = 0xAA;
+  mc_req_rec.pkt_life = 0 | IB_PATH_SELECTOR_GREATER_THAN << 6;
+  mc_req_rec.scope_state = 0x21; /* Full memeber */
+  comp_mask =
+    IB_MCR_COMPMASK_GID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS |  /* all above are required */
+    IB_MCR_COMPMASK_LIFE |
+    IB_MCR_COMPMASK_LIFE_SEL;
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02BE: "
+             "Failed to create MCG for 0x%016" PRIx64 " : "
+             "0x%016" PRIx64 " - got %s/%s\n",
+             cl_ntoh64(good_mgid.unicast.prefix),
+             cl_ntoh64(good_mgid.unicast.interface_id),
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) );
+    goto Exit;
+  }
+
+  /* - Try delete with valid join state */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Full Delete of a group (o15.0.1.14)...\n"
+           );
+  mc_req_rec.scope_state = 0x21; /* the FullMember is the current JoinState */
+  status = osmt_send_mcast_request( p_osmt, 0,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+
+  if (status != IB_SUCCESS)
+  {
+    goto Exit;
+  }
+
+  /* o15.0.1.15: */
+  /* - Try deletion of the IPoIB MCG and get: ERR_REQ_INVALID */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking BAD Delete of IPoIB membership (no prev join) (o15.0.1.15)...\n"
+           );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+
+  mc_req_rec.mgid = osm_ipoib_mgid;
+  mc_req_rec.rate =
+    IB_LINK_WIDTH_ACTIVE_1X |
+    IB_PATH_SELECTOR_GREATER_THAN << 6;
+  mc_req_rec.scope_state = 0x21; /* delete full member */
+
+  status = osmt_send_mcast_request( p_osmt, 0, /* delete flag */
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+  if ((status != IB_REMOTE_ERROR) ||
+      (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0223: "
+             "Failed to catch BAD delete from IPoIB: %s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /**************************************************************************/
+  /* Checking join with invalid MTU */
+  osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Join with unrealistic mtu : \n"
+           "\t\tFirst create new MCG than try to join it \n"
+           "\t\twith unrealistic MTU greater than 4096 (o15.0.1.8)...\n"
+           );
+
+  /* First create new mgrp */
+  ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+  mc_req_rec.mtu = IB_MTU_LEN_1024 | IB_PATH_SELECTOR_EXACTLY << 6;
+  memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t));
+  comp_mask =
+    IB_MCR_COMPMASK_MGID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_QKEY |
+    IB_MCR_COMPMASK_PKEY |
+    IB_MCR_COMPMASK_SL |
+    IB_MCR_COMPMASK_FLOW |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_TCLASS | /* all above are required */
+    IB_MCR_COMPMASK_MTU_SEL |
+    IB_MCR_COMPMASK_MTU;
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02EB: "
+             "Failed to create new mgrp\n" );
+    goto Exit;
+  }
+  memcpy(&tmp_mgid,&p_mc_res->mgid,sizeof(ib_gid_t));
+  osm_dump_mc_record( &p_osmt->log, p_mc_res, OSM_LOG_INFO );
+  /* tmp_mtu = p_mc_res->mtu & 0x3F; */
+
+  /* impossible requested mtu always greater than exist in MCG */
+  mc_req_rec.mtu = IB_MTU_LEN_4096 | IB_PATH_SELECTOR_GREATER_THAN << 6;
+  memcpy(&mc_req_rec.mgid,&tmp_mgid,sizeof(ib_gid_t));
+  ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+  comp_mask =
+    IB_MCR_COMPMASK_GID |
+    IB_MCR_COMPMASK_PORT_GID |
+    IB_MCR_COMPMASK_JOIN_STATE |
+    IB_MCR_COMPMASK_MTU_SEL |
+    IB_MCR_COMPMASK_MTU;
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+           
+  if (status == IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02E4: "
+             "Expected REMOTE ERROR got:%s/%s\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* - Try GetTable with PortGUID wildcarded and get back some groups. */
+  status = osmt_query_mcast( p_osmt);
+  cnt = cl_qmap_count(&p_osmt->exp_subn.mgrp_mlid_tbl);
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow (Before checking Max MCG creation): "
+           "Number of MC Records found in SA DB is %d\n", cnt );
+
+  /**************************************************************************/
+  /* Checking join on behalf of remote port gid */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Proxy Join...\n"
+           );
+  osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+  memset( &context, 0, sizeof( context ) );
+
+  /*
+   * Do a blocking query for all NodeRecords in the subnet.
+   */
+  status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_NODE_RECORD,
+                                 sizeof( *p_rec ), &context );
+
+  if( status != IB_SUCCESS )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02E5: "
+             "osmtest_get_all_recs failed on getting all node records(%s)\n",
+             ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  /*
+   * Populate the database with the received records.
+   */
+  num_recs = context.result.result_cnt;
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_run_mcast_flow: "
+           "Received %u records\n", num_recs );
+
+  for( i = 0; i < num_recs; i++ )
+  {
+    p_rec = osmv_get_query_node_rec( context.result.p_result_madw, i );
+    if (p_rec->node_info.port_guid != p_osmt->local_port.port_guid &&
+        p_rec->node_info.node_type == IB_NODE_TYPE_CA)
+    {
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "osmt_run_mcast_flow: "
+               "remote port_guid = 0x%" PRIx64 "\n",
+               cl_ntoh64(p_rec->node_info.port_guid) );
+
+      remote_port_guid = p_rec->node_info.port_guid;
+      i = num_recs;
+      break;
+    }
+  }
+
+  if (remote_port_guid != 0x0)
+  {
+    ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+    memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t));
+    mc_req_rec.port_gid.unicast.interface_id = remote_port_guid;
+    comp_mask =
+      IB_MCR_COMPMASK_MGID |
+      IB_MCR_COMPMASK_PORT_GID |
+      IB_MCR_COMPMASK_QKEY |
+      IB_MCR_COMPMASK_PKEY |
+      IB_MCR_COMPMASK_SL |
+      IB_MCR_COMPMASK_FLOW |
+      IB_MCR_COMPMASK_JOIN_STATE |
+      IB_MCR_COMPMASK_TCLASS; /* all above are required */
+
+    status = osmt_send_mcast_request( p_osmt, 1,
+                                      &mc_req_rec,
+                                      comp_mask,
+                                      &res_sa_mad );
+
+
+    if (status != IB_SUCCESS)
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_run_mcast_flow: ERR 02B4: "
+               "Could not join on behalf of remote port 0x%016" PRIx64
+               " remote status: %s\n",
+               cl_ntoh64(remote_port_guid),
+               ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+    p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+    memcpy(&proxy_mgid,&p_mc_res->mgid,sizeof(ib_gid_t));
+
+    /* First try a bad deletion then good one */
+
+    osm_log( &p_osmt->log, OSM_LOG_INFO,
+             "osmt_run_mcast_flow: "
+             "Trying deletion of remote port with local port guid\n" );
+
+    osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+    ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+    comp_mask =
+      IB_MCR_COMPMASK_MGID |
+      IB_MCR_COMPMASK_PORT_GID |
+      IB_MCR_COMPMASK_JOIN_STATE;
+
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+
+    status = osmt_send_mcast_request( p_osmt, 0, /* delete flag */
+                                      &mc_req_rec,
+                                      comp_mask,
+                                      &res_sa_mad );
+
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+    if (status == IB_SUCCESS)
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_run_mcast_flow: ERR 02A9: "
+               "Successful deletion of remote port guid with local one MGID : "
+               "0x%016" PRIx64 " : 0x%016" PRIx64 ", Got : %s/%s\n",
+               cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix),
+               cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id),
+               ib_get_err_str( status ),
+               ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+    osm_log( &p_osmt->log, OSM_LOG_INFO,
+             "osmt_run_mcast_flow: "
+             "Trying deletion of remote port with the right port guid\n" );
+
+    osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+    ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+    mc_req_rec.mgid = proxy_mgid;
+    mc_req_rec.port_gid.unicast.interface_id = remote_port_guid;
+    comp_mask =
+      IB_MCR_COMPMASK_MGID |
+      IB_MCR_COMPMASK_PORT_GID |
+      IB_MCR_COMPMASK_JOIN_STATE;
+    status = osmt_send_mcast_request( p_osmt, 0, /* delete flag */
+                                      &mc_req_rec,
+                                      comp_mask,
+                                      &res_sa_mad );
+    if (status != IB_SUCCESS)
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_run_mcast_flow: ERR 02B0: "
+               "Failed to delete mgid with remote port guid MGID : "
+               "0x%016" PRIx64 " : 0x%016" PRIx64 ", Got : %s/%s\n",
+               cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix),
+               cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id),
+               ib_get_err_str( status ),
+               ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) );
+      goto Exit;
+    }
+  }
+  else
+  {
+    osm_log( &p_osmt->log, OSM_LOG_INFO,
+             "osmt_run_mcast_flow: "
+             "Could not check proxy join since could not found remote port, different from local port\n" );
+  }
+
+  /* prepare init for next check */
+  osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+  /**************************************************************************/
+  if (p_osmt->opt.mmode > 2)
+  {
+    /* Check invalid Join with max mlid which is more than the
+       Mellanox switches support 0xC000+0x1000 = 0xd000 */
+    osm_log( &p_osmt->log, OSM_LOG_INFO,
+             "osmt_run_mcast_flow: "
+             "Checking Creation of Maximum avaliable Groups (MulticastFDBCap)...\n"
+             );
+    tmp_mlid = cl_ntoh16(max_mlid) - cnt;
+
+    while (tmp_mlid > 0 && !ReachedMlidLimit) {
+      uint16_t cur_mlid = 0;
+
+      /* Request Set */
+      ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+      /* Good Flow - mgid is 0 while giving all required fields for
+         join : P_Key, Q_Key, SL, FlowLabel, Tclass */
+
+      mc_req_rec.rate =
+        IB_LINK_WIDTH_ACTIVE_1X |
+        IB_PATH_SELECTOR_GREATER_THAN << 6;
+      mc_req_rec.mlid = max_mlid;
+      memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t));
+      comp_mask =
+        IB_MCR_COMPMASK_MGID |
+        IB_MCR_COMPMASK_PORT_GID |
+        IB_MCR_COMPMASK_QKEY |
+        IB_MCR_COMPMASK_PKEY |
+        IB_MCR_COMPMASK_SL |
+        IB_MCR_COMPMASK_FLOW |
+        IB_MCR_COMPMASK_JOIN_STATE |
+        IB_MCR_COMPMASK_TCLASS | /* all above are required */
+        IB_MCR_COMPMASK_MLID;
+      status = osmt_send_mcast_request( p_osmt, 1,
+                                        &mc_req_rec,
+                                        comp_mask,
+                                        &res_sa_mad );
+
+      p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+      if (status != IB_SUCCESS)
+      {
+
+        if (cur_mlid > cl_ntoh16(max_mlid))
+        {
+
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmt_run_mcast_flow : ERR 2E1 "
+                   "Successful Join with greater mlid than switches support (MulticastFDBCap) 0x%04X\n",
+                   cur_mlid );
+          status = IB_ERROR;
+          osm_dump_mc_record( &p_osmt->log, p_mc_res, OSM_LOG_VERBOSE );
+          goto Exit;
+        } else if (( res_sa_mad.status & IB_SMP_STATUS_MASK ) == IB_SA_MAD_STATUS_NO_RESOURCES) {
+          /* You can quitly exit the loop since no available mlid in SA DB
+             i.e. reached the maximum valiad avalable mlid */
+          ReachedMlidLimit = TRUE;
+        }
+      }
+      else
+      {
+        cur_mlid = cl_ntoh16(p_mc_res->mlid);
+        /* Save the mlid created in test_created_mlids map */
+        p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+        osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+                 "osmt_run_mcast_flow : "
+                 "Created MGID:0x%016" PRIx64 " : "
+                 "0x%016" PRIx64 " MLID:0x%04X\n",
+                 cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+                 cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+                 cl_ntoh16( p_recvd_rec->mlid ));
+                 cl_map_insert(&test_created_mlids,
+                 cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+      }
+      tmp_mlid--;
+    }
+  }
+
+  /* Prepare the mc_req_rec for the rest of the flow */
+  osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+  /**************************************************************************/
+  /* o15.0.1.16: */
+  /* - Try GetTable with PortGUID wildcarded and get back some groups. */
+
+  status = osmt_query_mcast( p_osmt);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02B1: "
+             "Failed to query multicast groups: %s\n",
+             ib_get_err_str(status) );
+    goto Exit;
+  }
+
+  cnt = cl_qmap_count(&p_osmt->exp_subn.mgrp_mlid_tbl);
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow (Before Deletion of all MCG): "
+           "Number of MC Records found in SA DB is %d\n", cnt );
+
+  /* Delete all MCG that are not of IPoIB */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow : "
+           "Cleanup all MCG that are not IPoIB...\n" );
+
+  p_mgrp_mlid_tbl = &p_osmt->exp_subn.mgrp_mlid_tbl;
+  p_mgrp = (osmtest_mgrp_t*)cl_qmap_head( p_mgrp_mlid_tbl );
+  /* scan all available multicast groups in the DB and fill in the table */
+  while( p_mgrp != (osmtest_mgrp_t*)cl_qmap_end( p_mgrp_mlid_tbl ) )
+  {
+    /* Only if different from IPoIB Mgid try to delete */
+    if (!IS_IPOIB_MGID(&p_mgrp->mcmember_rec.mgid))
+    {
+      osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+      mc_req_rec.mgid = p_mgrp->mcmember_rec.mgid;
+
+      /* o15-0.1.4 - need to specify the oppsite state for a valid delete */
+      if (!memcmp(&special_mgid, &p_mgrp->mcmember_rec.mgid, sizeof(special_mgid)))
+      {
+        mc_req_rec.scope_state = 0x2F;
+      }
+      else
+      {
+        mc_req_rec.scope_state = 0x21;
+      }
+      comp_mask =
+        IB_MCR_COMPMASK_MGID |
+        IB_MCR_COMPMASK_PORT_GID |
+        IB_MCR_COMPMASK_JOIN_STATE;
+
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "osmt_run_mcast_flow : "
+               "Sending request to delete MGID : 0x%016" PRIx64
+               " : 0x%016" PRIx64 ", scope_state : 0x%02X\n",
+               cl_ntoh64(mc_req_rec.mgid.unicast.prefix),
+               cl_ntoh64(mc_req_rec.mgid.unicast.interface_id),
+               mc_req_rec.scope_state );
+      status = osmt_send_mcast_request( p_osmt, 0, /* delete flag */
+                                        &mc_req_rec,
+                                        comp_mask,
+                                        &res_sa_mad );
+      if (status != IB_SUCCESS)
+      {
+        osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                 "osmt_run_mcast_flow: ERR 02FF: "
+                 "Failed to delete MGID : 0x%016" PRIx64 " : 0x%016" PRIx64
+                 " ,\n\t\t it is not our MCG, Status : %s/%s\n",
+                 cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix),
+                 cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id),
+                 ib_get_err_str( status ),
+                 ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) );
+        fail_to_delete_mcg++;
+      }
+    }
+    else
+    {
+      end_ipoib_cnt++;
+    }
+    p_mgrp = (osmtest_mgrp_t*)cl_qmap_next( &p_mgrp->map_item );
+  }
+
+  status = osmt_query_mcast( p_osmt);
+
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02B2 "
+             "GetTable of all records has failed - got %s\n",
+             ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  /* If we are in single mode check flow - need to make sure all the multicast groups 
+     that are left are not ones created during the flow.
+  */
+  if (p_osmt->opt.mmode == 1 || p_osmt->opt.mmode == 3)
+  {
+      end_cnt = cl_qmap_count(&p_osmt->exp_subn.mgrp_mlid_tbl);
+
+      osm_log( &p_osmt->log, OSM_LOG_INFO,
+               "osmt_run_mcast_flow: "
+               "Status of MC Records in SA DB during the test flow:\n"
+               "  Beginning of test\n"
+               "       Unrelated to the test: %d\n"
+               "       IPoIB MC Records     : %d\n"
+               "       Total                : %d\n"
+               "  End of test\n"
+               "       Failed to delete     : %d\n"
+               "       IPoIB MC Records     : %d\n"
+               "       Total                : %d\n",
+               mcg_outside_test_cnt, /* Non-IPoIB that existed at the beginning */
+               start_ipoib_cnt,      /* IPoIB records */
+               start_cnt,            /* Total: IPoIB and MC Records unrelated to the test */
+               fail_to_delete_mcg,   /* Failed to delete at the end */
+               end_ipoib_cnt,        /* IPoIB records */
+               end_cnt);             /* Total MC Records at the end */   
+
+      /* when we compare num of MCG we should consider an outside source which create other MCGs */
+      if ((end_cnt - fail_to_delete_mcg-end_ipoib_cnt) != (start_cnt - mcg_outside_test_cnt - start_ipoib_cnt))
+      {
+        osm_log( &p_osmt->log, OSM_LOG_INFO,
+                 "osmt_run_mcast_flow: "
+                 "Got different number of non-IPoIB records stored in SA DB\n\t\t"
+                 "at Start got %d, at End got %d (IPoIB groups only)\n",
+                 (start_cnt - mcg_outside_test_cnt - start_ipoib_cnt),
+                 (end_cnt - fail_to_delete_mcg-end_ipoib_cnt) );
+      }
+
+      p_mgrp_mlid_tbl = &p_osmt->exp_subn.mgrp_mlid_tbl;
+      p_mgrp = (osmtest_mgrp_t*)cl_qmap_head( p_mgrp_mlid_tbl );
+      while( p_mgrp != (osmtest_mgrp_t*)cl_qmap_end( p_mgrp_mlid_tbl ) )
+      {
+        uint16_t mlid = (uint16_t)cl_qmap_key((cl_map_item_t*)p_mgrp);
+
+        osm_log( &p_osmt->log, OSM_LOG_INFO,
+                 "osmt_run_mcast_flow: "
+                 "Found MLID:0x%04X\n",
+                 mlid );
+        /* Check if the mlid is in the test_created_mlids. If TRUE, then we
+           didn't delete a MCgroup that was created in this flow. */
+        if ( cl_map_get (&test_created_mlids, mlid) != NULL )
+        {
+          /* This means that we still have an mgrp that we created!! */
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmt_run_mcast_flow: ERR 02FE: "
+                   "Wasn't able to erase mgrp with MGID:0x%016" PRIx64 " : 0x%016"
+                   PRIx64 " MLID:0x%04X\n",
+                   cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix),
+                   cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id),
+                   mlid );
+          got_error = TRUE;
+        }
+        else
+        {
+           osm_log( &p_osmt->log, OSM_LOG_INFO,
+                    "osmt_run_mcast_flow: "
+                    "Still exists %s MGID:0x%016" PRIx64 " : 0x%016" PRIx64 "\n",
+                    (IS_IPOIB_MGID(&p_mgrp->mcmember_rec.mgid)) ? "IPoIB" : "non-IPoIB",
+                    cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix),
+                    cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id) );
+        }
+        p_mgrp = (osmtest_mgrp_t*)cl_qmap_next( &p_mgrp->map_item );
+      }
+
+      if (got_error)
+      {
+         __osmt_print_all_multicast_records(p_osmt);
+         status = IB_ERROR;
+      }
+  }
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return status;
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_service.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_service.c
new file mode 100644 (file)
index 0000000..62a0612
--- /dev/null
@@ -0,0 +1,1833 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osmt_service.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of service records testing flow..
+ *    Top level is osmt_run_service_records_flow:
+ *     osmt_register_service
+ *     osmt_get_service_by_name
+ *     osmt_get_all_services
+ *     osmt_delete_service_by_name
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.1 $
+ */
+
+#ifndef __WIN__
+#include <unistd.h>
+#else
+#include <time.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include "osmtest.h"
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+osmt_register_service( IN osmtest_t * const p_osmt,
+                       IN ib_net64_t      service_id,
+                       IN ib_net16_t      service_pkey,
+                       IN ib_net32_t      service_lease,
+                       IN uint8_t         service_key_lsb,
+                       IN char            *service_name) {
+  osmv_query_req_t req;
+  osmv_user_query_t user;
+  osmtest_req_context_t context;
+  ib_service_record_t svc_rec;
+  osm_log_t *p_log = &p_osmt->log;
+  ib_api_status_t status;
+
+  OSM_LOG_ENTER( p_log, osmt_register_service );
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_register_service: "
+           "Registering service: name: %s id: 0x%" PRIx64 "\n",
+           service_name, cl_ntoh64(service_id));
+
+  memset( &req, 0, sizeof( req ) );
+  memset( &context, 0, sizeof( context ) );
+  memset( &user, 0, sizeof( user ) );
+  memset( &svc_rec, 0, sizeof( svc_rec ) );
+
+  /* set the new service record fields */
+  svc_rec.service_id = service_id;
+  svc_rec.service_pkey = service_pkey;
+  svc_rec.service_gid.unicast.prefix = 0;
+  svc_rec.service_gid.unicast.interface_id = p_osmt->local_port.port_guid;
+  svc_rec.service_lease = service_lease;
+  memset(&svc_rec.service_key, 0, 16*sizeof(uint8_t));
+  svc_rec.service_key[0] = service_key_lsb;
+  memset(svc_rec.service_name, 0, sizeof(svc_rec.service_name));
+  memcpy(svc_rec.service_name, service_name,
+            (strlen(service_name)+1)*sizeof(char));
+
+  /* prepare the data used for this query */
+  /*  sa_mad_data.method = IB_MAD_METHOD_SET; */
+  /*  sa_mad_data.sm_key = 0; */
+
+  context.p_osmt = p_osmt;
+  req.query_context = &context;
+  req.query_type = OSMV_QUERY_USER_DEFINED;
+  req.pfn_query_cb = osmtest_query_res_cb;
+  req.p_query_input = &user;
+  req.flags = OSM_SA_FLAGS_SYNC;
+  req.sm_key = 0;
+  req.timeout_ms = p_osmt->opt.transaction_timeout;
+
+  user.method = IB_MAD_METHOD_SET;
+  user.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+  if (ib_pkey_is_invalid(service_pkey))
+  {
+    /* if given an invalid service_pkey - don't turn the PKEY compmask on */
+    user.comp_mask = IB_SR_COMPMASK_SID |
+      IB_SR_COMPMASK_SGID |
+      IB_SR_COMPMASK_SLEASE |
+      IB_SR_COMPMASK_SKEY |
+      IB_SR_COMPMASK_SNAME;
+  }
+  else
+  {
+    user.comp_mask = IB_SR_COMPMASK_SID |
+      IB_SR_COMPMASK_SGID |
+      IB_SR_COMPMASK_SPKEY |
+      IB_SR_COMPMASK_SLEASE |
+      IB_SR_COMPMASK_SKEY |
+      IB_SR_COMPMASK_SNAME;
+  }
+  user.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) );
+  user.p_attr = &svc_rec;
+
+  status = osmv_query_sa( p_osmt->h_bind, &req );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_register_service: ERR 4A01: "
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  status = context.result.status;
+
+  if( status != IB_SUCCESS )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_register_service: ERR 4A02: "
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );
+
+    if( status == IB_REMOTE_ERROR )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_register_service: "
+               "Remote error = %s\n",
+               ib_get_mad_status_str( osm_madw_get_mad_ptr
+                                      ( context.result.
+                                        p_result_madw ) ) );
+    }
+    goto Exit;
+  }
+
+ Exit:
+  if( context.result.p_result_madw != NULL )
+  {
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+    context.result.p_result_madw = NULL;
+  }
+
+  OSM_LOG_EXIT( &p_osmt->log );
+  return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+osmt_register_service_with_full_key ( IN osmtest_t * const p_osmt,
+                                      IN ib_net64_t      service_id,
+                                      IN ib_net16_t      service_pkey,
+                                      IN ib_net32_t      service_lease,
+                                      IN uint8_t         *service_key,
+                                      IN char            *service_name) {
+  osmv_query_req_t req;
+  osmv_user_query_t user;
+  osmtest_req_context_t context;
+  ib_service_record_t svc_rec,*p_rec;
+  osm_log_t *p_log = &p_osmt->log;
+  ib_api_status_t status;
+  uint8_t i,skey[16];
+
+  OSM_LOG_ENTER( p_log, osmt_register_service_with_full_key );
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_register_service_with_full_key: "
+           "Registering service: name: %s id: 0x%" PRIx64 "\n",
+           service_name, cl_ntoh64(service_id));
+
+  memset( &req, 0, sizeof( req ) );
+  memset( &context, 0, sizeof( context ) );
+  memset( &user, 0, sizeof( user ) );
+  memset( &svc_rec, 0, sizeof( svc_rec ) );
+
+  /* set the new service record fields */
+  svc_rec.service_id = service_id;
+  svc_rec.service_pkey = service_pkey;
+  svc_rec.service_gid.unicast.prefix = 0;
+  svc_rec.service_gid.unicast.interface_id = p_osmt->local_port.port_guid;
+  svc_rec.service_lease = service_lease;
+  memset(&svc_rec.service_key, 0, 16*sizeof(uint8_t));
+  memcpy(svc_rec.service_key,service_key, 16*sizeof(uint8_t));
+  memset(svc_rec.service_name, 0, sizeof(svc_rec.service_name));
+  memset(skey, 0, 16*sizeof(uint8_t));
+  memcpy(svc_rec.service_name, service_name,
+         (strlen(service_name)+1)*sizeof(char));
+
+  /* prepare the data used for this query */
+  /*  sa_mad_data.method = IB_MAD_METHOD_SET; */
+  /*  sa_mad_data.sm_key = 0; */
+
+  context.p_osmt = p_osmt;
+  req.query_context = &context;
+  req.query_type = OSMV_QUERY_USER_DEFINED;
+  req.pfn_query_cb = osmtest_query_res_cb;
+  req.p_query_input = &user;
+  req.flags = OSM_SA_FLAGS_SYNC;
+  req.sm_key = 0;
+  req.timeout_ms = p_osmt->opt.transaction_timeout;
+
+  user.method = IB_MAD_METHOD_SET;
+  user.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+  if (ib_pkey_is_invalid(service_pkey))
+  {
+    /* if given an invalid service_pkey - don't turn the PKEY compmask on */
+    user.comp_mask = IB_SR_COMPMASK_SID |
+      IB_SR_COMPMASK_SGID |
+      IB_SR_COMPMASK_SLEASE |
+      IB_SR_COMPMASK_SKEY |
+      IB_SR_COMPMASK_SNAME;
+  }
+  else
+  {
+    user.comp_mask = IB_SR_COMPMASK_SID |
+      IB_SR_COMPMASK_SGID |
+      IB_SR_COMPMASK_SPKEY |
+      IB_SR_COMPMASK_SLEASE |
+      IB_SR_COMPMASK_SKEY |
+      IB_SR_COMPMASK_SNAME;
+  }
+  user.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) );
+  user.p_attr = &svc_rec;
+
+  status = osmv_query_sa( p_osmt->h_bind, &req );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_register_service_with_full_key: ERR 4A03: "
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  status = context.result.status;
+  if( status != IB_SUCCESS )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_register_service_with_full_key: ERR 4A04: "
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );
+
+    if( status == IB_REMOTE_ERROR )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_register_service_with_full_key: "
+               "Remote error = %s\n",
+               ib_get_mad_status_str( osm_madw_get_mad_ptr
+                                      ( context.result.
+                                        p_result_madw ) ) );
+    }
+    goto Exit;
+  }
+
+  /*  Check service key on context to see if match */
+  p_rec = osmv_get_query_svc_rec( context.result.p_result_madw, 0 );
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "Comparing service key...\n"
+           "return key is:\n");
+  for (i = 0; i <= 15; i++)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+             "service_key sent[%u] = %u, service_key returned[%u] = %u\n",
+             i,service_key[i],i,p_rec->service_key[i]);
+  }
+  /*  since c15-0.1.14 not supported all key association queries should bring in return zero in service key */
+  if (memcmp(skey,p_rec->service_key, 16*sizeof(uint8_t)) != 0)
+  {
+    status = IB_REMOTE_ERROR;
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_register_service_with_full_key: ERR 4A33: "
+             "Data mismatch in service_key\n"
+             );
+    goto Exit;
+  }
+
+ Exit:
+  if( context.result.p_result_madw != NULL )
+  {
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+    context.result.p_result_madw = NULL;
+  }
+
+  OSM_LOG_EXIT( &p_osmt->log );
+  return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+osmt_register_service_with_data( IN osmtest_t * const p_osmt,
+                                 IN ib_net64_t      service_id,
+                                 IN ib_net16_t      service_pkey,
+                                 IN ib_net32_t      service_lease,
+                                 IN uint8_t         service_key_lsb,
+                                 IN uint8_t       *service_data8,
+                                 IN ib_net16_t    *service_data16,
+                                 IN ib_net32_t    *service_data32,
+                                 IN ib_net64_t    *service_data64,
+                                 IN char            *service_name) {
+  osmv_query_req_t req;
+  osmv_user_query_t user;
+  osmtest_req_context_t context;
+  ib_service_record_t svc_rec,*p_rec;
+  osm_log_t *p_log = &p_osmt->log;
+  ib_api_status_t status;
+  /*   ib_service_record_t* p_rec; */
+
+  OSM_LOG_ENTER( p_log, osmt_register_service_with_data );
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_register_service_with_data: "
+           "Registering service: name: %s id: 0x%" PRIx64 "\n",
+           service_name, cl_ntoh64(service_id));
+
+  memset( &req, 0, sizeof( req ) );
+  memset( &context, 0, sizeof( context ) );
+  memset( &user, 0, sizeof( user ) );
+  memset( &svc_rec, 0, sizeof( svc_rec ) );
+
+  /* set the new service record fields */
+  svc_rec.service_id = service_id;
+  svc_rec.service_pkey = service_pkey;
+  svc_rec.service_gid.unicast.prefix = 0;
+  svc_rec.service_gid.unicast.interface_id = p_osmt->local_port.port_guid;
+  svc_rec.service_lease = service_lease;
+  memset(&svc_rec.service_key, 0, 16*sizeof(uint8_t));
+  svc_rec.service_key[0] = service_key_lsb;
+
+  /*  Copy data to service_data arrays */
+  memcpy(svc_rec.service_data8, service_data8, 16*sizeof(uint8_t));
+  memcpy(svc_rec.service_data16, service_data16, 8*sizeof(ib_net16_t));
+  memcpy(svc_rec.service_data32, service_data32, 4*sizeof(ib_net32_t));
+  memcpy(svc_rec.service_data64, service_data64, 2*sizeof(ib_net64_t));
+
+  memset(svc_rec.service_name, 0, sizeof(svc_rec.service_name));
+  memcpy(svc_rec.service_name, service_name,
+         (strlen(service_name)+1)*sizeof(char));
+
+  /* prepare the data used for this query */
+  /*  sa_mad_data.method = IB_MAD_METHOD_SET; */
+  /*  sa_mad_data.sm_key = 0; */
+
+  context.p_osmt = p_osmt;
+  req.query_context = &context;
+  req.query_type = OSMV_QUERY_USER_DEFINED;
+  req.pfn_query_cb = osmtest_query_res_cb;
+  req.p_query_input = &user;
+  req.flags = OSM_SA_FLAGS_SYNC;
+  req.sm_key = 0;
+  req.timeout_ms = p_osmt->opt.transaction_timeout;
+
+  user.method = IB_MAD_METHOD_SET;
+  user.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+  if (ib_pkey_is_invalid(service_pkey))
+  {
+    /* if given an invalid service_pkey - don't turn the PKEY compmask on */
+    user.comp_mask = IB_SR_COMPMASK_SID |
+      IB_SR_COMPMASK_SGID |
+      IB_SR_COMPMASK_SLEASE |
+      IB_SR_COMPMASK_SKEY |
+      IB_SR_COMPMASK_SNAME |
+      IB_SR_COMPMASK_SDATA8_0 |
+      IB_SR_COMPMASK_SDATA8_1 |
+      IB_SR_COMPMASK_SDATA16_0 |
+      IB_SR_COMPMASK_SDATA16_1 |
+      IB_SR_COMPMASK_SDATA32_0 |
+      IB_SR_COMPMASK_SDATA32_1 |
+      IB_SR_COMPMASK_SDATA64_0 |
+      IB_SR_COMPMASK_SDATA64_1;
+  }
+  else
+  {
+    user.comp_mask = IB_SR_COMPMASK_SID |
+      IB_SR_COMPMASK_SGID |
+      IB_SR_COMPMASK_SPKEY |
+      IB_SR_COMPMASK_SLEASE |
+      IB_SR_COMPMASK_SKEY |
+      IB_SR_COMPMASK_SNAME|
+      IB_SR_COMPMASK_SDATA8_0 |
+      IB_SR_COMPMASK_SDATA8_1 |
+      IB_SR_COMPMASK_SDATA16_0 |
+      IB_SR_COMPMASK_SDATA16_1 |
+      IB_SR_COMPMASK_SDATA32_0 |
+      IB_SR_COMPMASK_SDATA32_1 |
+      IB_SR_COMPMASK_SDATA64_0 |
+      IB_SR_COMPMASK_SDATA64_1;
+  }
+  user.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) );
+  user.p_attr = &svc_rec;
+
+  /*  Dump to Service Data b4 send */
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_register_service_with_data:"
+           "Dumping service data b4 send\n");
+  osm_dump_service_record(&p_osmt->log,&svc_rec,OSM_LOG_VERBOSE);
+
+  status = osmv_query_sa( p_osmt->h_bind, &req );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_register_service_with_data: ERR 4A05: "
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  status = context.result.status;
+
+  if( status != IB_SUCCESS )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_register_service_with_data: ERR 4A06: "
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );
+
+    if( status == IB_REMOTE_ERROR )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_register_service_with_data: "
+               "Remote error = %s\n",
+               ib_get_mad_status_str( osm_madw_get_mad_ptr
+                                      ( context.result.
+                                        p_result_madw ) ) );
+    }
+    goto Exit;
+  }
+
+  /*  Check data on context to see if match */
+  p_rec = osmv_get_query_svc_rec( context.result.p_result_madw, 0 );
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "Comparing service data...\n");
+  if (memcmp(service_data8, p_rec->service_data8,16*sizeof(uint8_t)) != 0 ||
+      memcmp(service_data16, p_rec->service_data16,8*sizeof(uint16_t)) != 0 ||
+      memcmp(service_data32, p_rec->service_data32,4*sizeof(uint32_t)) != 0 ||
+      memcmp(service_data64, p_rec->service_data64,2*sizeof(uint64_t)) != 0
+      )
+  {
+    status = IB_REMOTE_ERROR;
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_register_service_with_data: "
+             "Data mismatch in service_data8\n"
+             );
+    goto Exit;
+  }
+
+ Exit:
+  if( context.result.p_result_madw != NULL )
+  {
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+    context.result.p_result_madw = NULL;
+  }
+
+  OSM_LOG_EXIT( &p_osmt->log );
+  return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+osmt_get_service_by_id_and_name ( IN osmtest_t * const p_osmt,
+                                  IN uint32_t rec_num,
+                                  IN ib_net64_t sid,
+                                  IN char            *sr_name,
+                                  OUT ib_service_record_t *p_out_rec) {
+
+  ib_api_status_t status = IB_SUCCESS;
+  osmtest_req_context_t context;
+  osmv_query_req_t req;
+  ib_service_record_t svc_rec,*p_rec;
+  uint32_t num_recs = 0;
+  osmv_user_query_t user;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmt_get_service_by_id );
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+             "osmt_get_service_by_id_and_name: "
+             "Getting service record: id: 0x%016" PRIx64 " and name: %s\n",
+             cl_ntoh64(sid),sr_name);
+
+  /*
+   * Do a blocking query for this record in the subnet.
+   * The result is returned in the result field of the caller's
+   * context structure.
+   *
+   * The query structures are locals.
+   */
+  memset( &req, 0, sizeof( req ) );
+  memset( &context, 0, sizeof( context ) );
+
+  context.p_osmt = p_osmt;
+
+  /* prepare the data used for this query */
+  req.query_type = OSMV_QUERY_USER_DEFINED;
+  req.timeout_ms = p_osmt->opt.transaction_timeout;
+  req.retry_cnt = p_osmt->opt.retry_count;
+  req.flags = OSM_SA_FLAGS_SYNC;
+  req.query_context = &context;
+  req.pfn_query_cb = osmtest_query_res_cb;
+  req.sm_key = 0;
+
+  memset( &svc_rec, 0, sizeof( svc_rec ) );
+  memset( &user, 0, sizeof( user ) );
+  /* set the new service record fields */
+  memset(svc_rec.service_name, 0, sizeof(svc_rec.service_name));
+  memcpy(svc_rec.service_name, sr_name,
+         (strlen(sr_name)+1)*sizeof(char));
+  svc_rec.service_id = sid;
+  req.p_query_input = &user;
+
+  user.method = IB_MAD_METHOD_GET;
+  user.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+  user.comp_mask = IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SNAME;
+  user.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) );
+  user.p_attr = &svc_rec;
+
+  status = osmv_query_sa( p_osmt->h_bind, &req );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_get_service_by_id_and_name: ERR 4A07: "
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  status = context.result.status;
+  num_recs = context.result.result_cnt;
+
+  if( status != IB_SUCCESS )
+  {
+    char mad_stat_err[256];
+
+    /* If the failure is due to IB_SA_MAD_STATUS_NO_RECORDS and rec_num is 0,
+        then this is fine */
+    if( status == IB_REMOTE_ERROR )
+      strcpy(mad_stat_err, ib_get_mad_status_str( 
+             osm_madw_get_mad_ptr(context.result.p_result_madw) ) );
+    else
+      strcpy(mad_stat_err, ib_get_err_str(status) );
+    if( status == IB_REMOTE_ERROR && 
+        !strcmp(mad_stat_err, "IB_SA_MAD_STATUS_NO_RECORDS") &&
+        rec_num == 0 )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_get_service_by_id_and_name: "
+               "IS EXPECTED ERROR ^^^^\n");
+      status = IB_SUCCESS;
+  }
+  else
+  {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_get_service_by_id_and_name: ERR 4A08: "
+               "Query failed: %s (%s)\n",
+               ib_get_err_str(status),
+               mad_stat_err );
+      goto Exit;
+    }
+  }
+
+  if ( rec_num && num_recs != rec_num )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_get_service_by_id_and_name: "
+             "Unmatched number of records: expected: %d, received: %d\n",
+             rec_num, num_recs);
+    status = IB_REMOTE_ERROR;
+    goto Exit;
+  }
+
+  p_rec = osmv_get_query_svc_rec( context.result.p_result_madw, 0 );
+  *p_out_rec = *p_rec;
+
+  if (num_recs)
+  {
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_get_service_by_id_and_name: "
+             "Found service record: name: %s id: 0x%016" PRIx64 "\n",
+           p_rec->service_name, cl_ntoh64(p_rec->service_id));
+
+  osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_DEBUG);
+  }
+
+ Exit:
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_get_service_by_id_and_name: "
+           "Expected and found %d records\n",
+           rec_num );
+
+  if( context.result.p_result_madw != NULL )
+  {
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+    context.result.p_result_madw = NULL;
+  }
+
+  OSM_LOG_EXIT( &p_osmt->log );
+  return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+osmt_get_service_by_id ( IN osmtest_t * const p_osmt,
+                         IN uint32_t rec_num,
+                         IN ib_net64_t sid,
+                         OUT ib_service_record_t *p_out_rec) {
+
+  ib_api_status_t status = IB_SUCCESS;
+  osmtest_req_context_t context;
+  osmv_query_req_t req;
+  ib_service_record_t svc_rec,*p_rec;
+  uint32_t num_recs = 0;
+  osmv_user_query_t user;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmt_get_service_by_id );
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+             "osmt_get_service_by_id: "
+             "Getting service record: id: 0x%016" PRIx64 "\n",
+             cl_ntoh64(sid));
+
+  /*
+   * Do a blocking query for this record in the subnet.
+   * The result is returned in the result field of the caller's
+   * context structure.
+   *
+   * The query structures are locals.
+   */
+  memset( &req, 0, sizeof( req ) );
+  memset( &context, 0, sizeof( context ) );
+
+  context.p_osmt = p_osmt;
+
+  /* prepare the data used for this query */
+  req.query_type = OSMV_QUERY_USER_DEFINED;
+  req.timeout_ms = p_osmt->opt.transaction_timeout;
+  req.retry_cnt = p_osmt->opt.retry_count;
+  req.flags = OSM_SA_FLAGS_SYNC;
+  req.query_context = &context;
+  req.pfn_query_cb = osmtest_query_res_cb;
+  req.sm_key = 0;
+
+  memset( &svc_rec, 0, sizeof( svc_rec ) );
+  memset( &user, 0, sizeof( user ) );
+  /* set the new service record fields */
+  svc_rec.service_id = sid;
+  req.p_query_input = &user;
+
+  user.method = IB_MAD_METHOD_GET;
+  user.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+  user.comp_mask = IB_SR_COMPMASK_SID;
+  user.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) );
+  user.p_attr = &svc_rec;
+
+  status = osmv_query_sa( p_osmt->h_bind, &req );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_get_service_by_id: ERR 4A09: "
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  status = context.result.status;
+  num_recs = context.result.result_cnt;
+
+  if( status != IB_SUCCESS )
+  {
+    char mad_stat_err[256];
+
+    /* If the failure is due to IB_SA_MAD_STATUS_NO_RECORDS and rec_num is 0,
+        then this is fine */
+    if( status == IB_REMOTE_ERROR )
+      strcpy(mad_stat_err, ib_get_mad_status_str( 
+             osm_madw_get_mad_ptr(context.result.p_result_madw) ) );
+    else
+      strcpy(mad_stat_err, ib_get_err_str(status) );
+
+    if( status == IB_REMOTE_ERROR && 
+        !strcmp(mad_stat_err, "IB_SA_MAD_STATUS_NO_RECORDS") &&
+        rec_num == 0 )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_get_service_by_id: "
+               "IS EXPECTED ERROR ^^^^\n");
+      status = IB_SUCCESS;
+  }
+  else
+  {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_get_service_by_id: ERR 4A0A: "
+               "Query failed: %s (%s)\n",
+               ib_get_err_str(status),
+               mad_stat_err );
+      goto Exit;
+    }
+  }
+
+  if ( rec_num && num_recs != rec_num )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_get_service_by_id: ERR 4A0B: "
+             "Unmatched number of records: expected: %d received: %d\n",
+             rec_num, num_recs);
+    status = IB_REMOTE_ERROR;
+    goto Exit;
+  }
+
+  p_rec = osmv_get_query_svc_rec( context.result.p_result_madw, 0 );
+  *p_out_rec = *p_rec;
+
+  if (num_recs)
+  {
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_get_service_by_id: "
+           "Found service record: name: %s id: 0x%016" PRIx64 "\n",
+           p_rec->service_name, cl_ntoh64(p_rec->service_id));
+
+  osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_DEBUG);
+  }
+
+ Exit:
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_get_service_by_id: "
+           "Expected and found %d records\n",
+           rec_num );
+
+  if( context.result.p_result_madw != NULL )
+  {
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+    context.result.p_result_madw = NULL;
+  }
+
+  OSM_LOG_EXIT( &p_osmt->log );
+  return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+osmt_get_service_by_name_and_key ( IN osmtest_t * const p_osmt,
+                                   IN char * sr_name,
+                                   IN uint32_t rec_num,
+                                   IN uint8_t *skey,
+                                   OUT ib_service_record_t *p_out_rec) {
+
+  ib_api_status_t status = IB_SUCCESS;
+  osmtest_req_context_t context;
+  osmv_query_req_t req;
+  ib_service_record_t svc_rec,*p_rec;
+  uint32_t num_recs = 0, i;
+  osmv_user_query_t user;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmt_get_service_by_name_and_key );
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+  {
+    char buf_service_key[33];
+    
+    sprintf(buf_service_key,
+            "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+            skey[0], skey[1], skey[2], skey[3], skey[4], skey[5], skey[6], skey[7],
+            skey[8], skey[9], skey[10], skey[11], skey[12], skey[13], skey[14],
+            skey[15]);
+    
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+             "osmt_get_service_by_name_and_key: "
+             "Getting service record: name: %s and key: %s\n",
+             sr_name, buf_service_key );
+  }
+
+  /*
+   * Do a blocking query for this record in the subnet.
+   * The result is returned in the result field of the caller's
+   * context structure.
+   *
+   * The query structures are locals.
+   */
+  memset( &req, 0, sizeof( req ) );
+  memset( &context, 0, sizeof( context ) );
+
+  context.p_osmt = p_osmt;
+
+  /* prepare the data used for this query */
+  req.query_type = OSMV_QUERY_USER_DEFINED;
+  req.timeout_ms = p_osmt->opt.transaction_timeout;
+  req.retry_cnt = p_osmt->opt.retry_count;
+  req.flags = OSM_SA_FLAGS_SYNC;
+  req.query_context = &context;
+  req.pfn_query_cb = osmtest_query_res_cb;
+  req.sm_key = 0;
+
+  memset( &svc_rec, 0, sizeof( svc_rec ) );
+  memset( &user, 0, sizeof( user ) );
+  /* set the new service record fields */
+  memset(svc_rec.service_name, 0, sizeof(svc_rec.service_name));
+  memcpy(svc_rec.service_name, sr_name,
+         (strlen(sr_name)+1)*sizeof(char));
+  for (i = 0; i <= 15; i++)
+    svc_rec.service_key[i] = skey[i];
+
+  req.p_query_input = &user;
+
+  user.method = IB_MAD_METHOD_GET;
+  user.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+  user.comp_mask = IB_SR_COMPMASK_SNAME | IB_SR_COMPMASK_SKEY;
+  user.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) );
+  user.p_attr = &svc_rec;
+  status = osmv_query_sa( p_osmt->h_bind, &req );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_get_service_by_name_and_key: ERR 4A0C: "
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  status = context.result.status;
+  num_recs =  context.result.result_cnt;
+
+  if( status != IB_SUCCESS )
+  {
+    char mad_stat_err[256];
+
+    /* If the failure is due to IB_SA_MAD_STATUS_NO_RECORDS and rec_num is 0,
+        then this is fine */
+    if( status == IB_REMOTE_ERROR )
+      strcpy(mad_stat_err, ib_get_mad_status_str( 
+             osm_madw_get_mad_ptr(context.result.p_result_madw) ) );
+    else
+      strcpy(mad_stat_err, ib_get_err_str(status) );
+
+    if( status == IB_REMOTE_ERROR && 
+        !strcmp(mad_stat_err, "IB_SA_MAD_STATUS_NO_RECORDS") &&
+        rec_num == 0 )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_get_service_by_name_and_key: "
+               "IS EXPECTED ERROR ^^^^\n");
+      status = IB_SUCCESS;
+  }
+  else
+  {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_get_service_by_name_and_key: ERR 4A0D: "
+               "Query failed:%s (%s)\n",
+               ib_get_err_str(status),
+               mad_stat_err );
+      goto Exit;
+    }
+  }
+
+  if ( rec_num && num_recs != rec_num )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_get_service_by_name_and_key: "
+             "Unmatched number of records: expected: %d, received: %d\n",
+             rec_num, num_recs);
+    status = IB_REMOTE_ERROR;
+    goto Exit;
+  }
+
+  p_rec = osmv_get_query_svc_rec( context.result.p_result_madw, 0 );
+  *p_out_rec = *p_rec;
+
+  if ( num_recs )
+  {
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_get_service_by_name_and_key: "
+             "Found service record: name: %s id: 0x%016" PRIx64 "\n",
+           sr_name, cl_ntoh64(p_rec->service_id));
+
+  osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_DEBUG);
+  }
+
+ Exit:
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_get_service_by_name_and_key: "
+           "Expected and found %d records\n",
+           rec_num );
+
+  if( context.result.p_result_madw != NULL )
+  {
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+    context.result.p_result_madw = NULL;
+  }
+
+  OSM_LOG_EXIT( &p_osmt->log );
+  return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+osmt_get_service_by_name( IN osmtest_t * const p_osmt,
+                          IN char * sr_name,
+                          IN uint32_t rec_num,
+                          OUT ib_service_record_t *p_out_rec) {
+
+  ib_api_status_t status = IB_SUCCESS;
+  osmtest_req_context_t context;
+  osmv_query_req_t req;
+  ib_service_record_t* p_rec;
+  ib_svc_name_t service_name;
+  uint32_t num_recs = 0;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmt_get_service_by_name );
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+             "osmt_get_service_by_name: "
+             "Getting service record: name: %s\n",
+             sr_name);
+
+  /*
+   * Do a blocking query for this record in the subnet.
+   * The result is returned in the result field of the caller's
+   * context structure.
+   *
+   * The query structures are locals.
+   */
+  memset( &req, 0, sizeof( req ) );
+  memset( &context, 0, sizeof( context ) );
+
+  context.p_osmt = p_osmt;
+
+  /* prepare the data used for this query */
+  req.query_type = OSMV_QUERY_SVC_REC_BY_NAME;
+  req.timeout_ms = p_osmt->opt.transaction_timeout;
+  req.retry_cnt = p_osmt->opt.retry_count;
+  req.flags = OSM_SA_FLAGS_SYNC;
+  req.query_context = &context;
+  req.pfn_query_cb = osmtest_query_res_cb;
+  req.sm_key = 0;
+
+  memset(service_name, 0, sizeof(service_name));
+  memcpy(service_name, sr_name, (strlen(sr_name)+1)*sizeof(char));
+  req.p_query_input = service_name;
+
+  status = osmv_query_sa( p_osmt->h_bind, &req );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_get_service_by_name: ERR 4A0E: "
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  status = context.result.status;
+  num_recs =  context.result.result_cnt;
+
+  if( status != IB_SUCCESS )
+  {
+    char mad_stat_err[256];
+
+    /*  If the failure is due to IB_SA_MAD_STATUS_NO_RECORDS and rec_num is 0,
+        then this is fine */
+    if( status == IB_REMOTE_ERROR )
+      strcpy(mad_stat_err, ib_get_mad_status_str( 
+             osm_madw_get_mad_ptr(context.result.p_result_madw) ) );
+    else
+      strcpy(mad_stat_err, ib_get_err_str(status) );
+
+    if( status == IB_REMOTE_ERROR && 
+        !strcmp(mad_stat_err, "IB_SA_MAD_STATUS_NO_RECORDS") &&
+        rec_num == 0 )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_get_service_by_name: "
+               "IS EXPECTED ERROR ^^^^\n");
+      status = IB_SUCCESS;
+  }
+  else
+  {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_get_service_by_name: ERR 4A0F: "
+               "Query failed: %s (%s)\n",
+               ib_get_err_str(status),
+               mad_stat_err );
+      goto Exit;
+    }
+  }
+
+  if ( rec_num && num_recs != rec_num )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_get_service_by_name: ERR 4A10: "
+             "Unmatched number of records: expected: %d, received: %d\n",
+             rec_num, num_recs);
+    status = IB_REMOTE_ERROR;
+    goto Exit;
+  }
+
+  p_rec = osmv_get_query_svc_rec( context.result.p_result_madw, 0 );
+  *p_out_rec = *p_rec;
+
+  if (num_recs)
+  {
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_get_service_by_name: "
+             "Found service record: name: %s id: 0x%016" PRIx64 "\n",
+           sr_name, cl_ntoh64(p_rec->service_id));
+
+  osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_DEBUG);
+  }
+
+ Exit:
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_get_service_by_name: "
+           "Expected and found %d records\n",
+           rec_num );
+
+  if( context.result.p_result_madw != NULL )
+  {
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+    context.result.p_result_madw = NULL;
+  }
+
+  OSM_LOG_EXIT( &p_osmt->log );
+  return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+#ifdef VENDOR_RMPP_SUPPORT
+ib_api_status_t
+osmt_get_all_services_and_check_names( IN osmtest_t * const p_osmt,
+                                       IN ib_svc_name_t * const p_valid_service_names_arr,
+                                       IN uint8_t    num_of_valid_names,
+                                       OUT uint32_t *num_services) {
+  ib_api_status_t status = IB_SUCCESS;
+  osmtest_req_context_t context;
+  osmv_query_req_t req;
+  ib_service_record_t* p_rec;
+  uint32_t num_recs = 0,i,j;
+  uint8_t *p_checked_names;
+
+  OSM_LOG_ENTER(&p_osmt->log, osmt_get_all_services_and_check_names );
+
+  /* Prepare tracker for the checked names */
+  p_checked_names = (uint8_t*)malloc(sizeof(uint8_t)*num_of_valid_names);
+  for (j = 0 ; j < num_of_valid_names ; j++) 
+  {
+      p_checked_names[j] = 0;
+  }
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+             "osmt_get_all_services_and_check_names: "
+             "Getting all service records\n");
+  }
+  /*
+   * Do a blocking query for this record in the subnet.
+   * The result is returned in the result field of the caller's
+   * context structure.
+   *
+   * The query structures are locals.
+   */
+  memset( &req, 0, sizeof( req ) );
+  memset( &context, 0, sizeof( context ) );
+
+  context.p_osmt = p_osmt;
+
+  req.query_type = OSMV_QUERY_ALL_SVC_RECS;
+  req.timeout_ms = p_osmt->opt.transaction_timeout;
+  req.retry_cnt = p_osmt->opt.retry_count;
+  req.flags = OSM_SA_FLAGS_SYNC;
+  req.query_context = &context;
+  req.pfn_query_cb = osmtest_query_res_cb;
+  req.sm_key = 0;
+
+  status = osmv_query_sa( p_osmt->h_bind, &req );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_get_all_services_and_check_names: ERR 4A12: "
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  status = context.result.status;
+
+  if( status != IB_SUCCESS )
+  {
+    if (status != IB_INVALID_PARAMETER)
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_get_all_services_and_check_names: ERR 4A13: "
+               "ib_query failed (%s)\n", ib_get_err_str( status ) );
+    }
+    if( status == IB_REMOTE_ERROR )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_get_all_services_and_check_names: "
+               "Remote error = %s\n",
+               ib_get_mad_status_str( osm_madw_get_mad_ptr
+                                      ( context.result.
+                                        p_result_madw ) ) );
+    }
+    goto Exit;
+  }
+
+  num_recs = context.result.result_cnt;
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+             "osmt_get_all_services_and_check_names: "
+             "Received %u records\n", num_recs );
+    
+  for( i = 0; i < num_recs; i++ )
+    {
+      p_rec = osmv_get_query_svc_rec( context.result.p_result_madw, i );
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "osmt_get_all_services_and_check_names: "
+               "Found service record: name: %s id: 0x%016" PRIx64 "\n",
+               p_rec->service_name, cl_ntoh64(p_rec->service_id));
+      osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_VERBOSE);
+      for ( j = 0; j < num_of_valid_names; j++) 
+      {
+          /* If the service names exist in the record, mark it as checked (1) */
+          osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+                   "osmt_get_all_services_and_check_names: "
+                   "-I- Comparing source name : >%s<, with record name : >%s<, idx : %d\n",
+                   p_valid_service_names_arr[j], p_rec->service_name, p_checked_names[j]);     
+          if ( strcmp((char *)p_valid_service_names_arr[j],
+                      (char *)p_rec->service_name) == 0 )
+          {
+              osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+                       "osmt_get_all_services_and_check_names: "
+                       "-I- The service %s is valid\n", p_valid_service_names_arr[j]);
+              p_checked_names[j] = 1;
+              break;
+          }
+      }
+    }
+  /* Check that all service names have been identified */
+  for ( j = 0; j < num_of_valid_names; j++) 
+      if (p_checked_names[j] == 0) 
+      {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmt_get_all_services_and_check_names: ERR 4A14: "
+                   "Missing valid service: name: %s\n", p_valid_service_names_arr[j]);
+          status = IB_ERROR;
+          goto Exit;
+      }
+  *num_services = num_recs;
+
+ Exit:
+  if( context.result.p_result_madw != NULL )
+  {
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+    context.result.p_result_madw = NULL;
+  }
+
+  OSM_LOG_EXIT( &p_osmt->log );
+  return status;
+}
+#endif
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+osmt_delete_service_by_name(IN osmtest_t * const p_osmt,
+                            IN uint8_t IsServiceExist,
+                            IN char * sr_name, IN uint32_t rec_num) {
+  osmv_query_req_t req;
+  osmv_user_query_t user;
+  osmtest_req_context_t context;
+  ib_service_record_t svc_rec;
+  ib_api_status_t status;
+
+  OSM_LOG_ENTER( &p_osmt->log,  osmt_delete_service_by_name);
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_delete_service_by_name: "
+           "Trying to Delete service name: %s\n",
+           sr_name);
+
+  memset( &svc_rec, 0, sizeof( svc_rec ) );
+
+  status = osmt_get_service_by_name(p_osmt, sr_name,rec_num, &svc_rec);
+  if (status != IB_SUCCESS)
+  {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_delete_service_by_name: ERR 4A15: "
+             "Failed to get service: name: %s\n",
+             sr_name );
+      goto ExitNoDel;
+  }
+
+  memset( &req, 0, sizeof( req ) );
+  memset( &context, 0, sizeof( context ) );
+  memset( &user, 0, sizeof( user ) );
+
+  /* set the new service record fields */
+  memset(svc_rec.service_name, 0, sizeof(svc_rec.service_name));
+  memcpy(svc_rec.service_name, sr_name,
+         (strlen(sr_name)+1)*sizeof(char));
+
+  /* prepare the data used for this query */
+  context.p_osmt = p_osmt;
+  req.timeout_ms = p_osmt->opt.transaction_timeout;
+  req.query_context = &context;
+  req.query_type = OSMV_QUERY_USER_DEFINED; /*  basically a don't care here */
+  req.pfn_query_cb = osmtest_query_res_cb;
+  req.p_query_input = &user;
+  req.flags = OSM_SA_FLAGS_SYNC;
+  req.sm_key = 0;
+
+  user.method = IB_MAD_METHOD_DELETE;
+  user.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+  user.comp_mask = IB_SR_COMPMASK_SNAME;
+  user.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) );
+  user.p_attr = &svc_rec;
+
+  status = osmv_query_sa( p_osmt->h_bind, &req );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_delete_service_by_name: ERR 4A16: "
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  status = context.result.status;
+  if ( IsServiceExist )
+  {
+    /* If IsServiceExist = 1 then we should succeed here */
+  if( status != IB_SUCCESS )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_delete_service_by_name: ERR 4A17: "
+               "ib_query failed (%s)\n", ib_get_err_str( status ) );
+
+    if( status == IB_REMOTE_ERROR )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                 "osmt_delete_service_by_name: ERR 4A18: "
+                 "Remote error = %s\n",
+               ib_get_mad_status_str( osm_madw_get_mad_ptr
+                                      ( context.result.
+                                        p_result_madw ) ) );
+    }
+    }
+  }
+  else
+  {
+    /* If IsServiceExist = 0 then we should fail here */
+    if ( status == IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_delete_service_by_name: ERR 4A19: "
+               "Succeeded to delete service: %s which "
+               "shouldn't exist", 
+               sr_name );
+      status = IB_ERROR;
+    }
+    else
+    {
+      /* The deletion should have failed, since the service_name
+         shouldn't exist. */
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_run_service_records_flow: "
+               "IS EXPECTED ERROR ^^^^\n");
+      osm_log( &p_osmt->log, OSM_LOG_INFO,
+               "osmt_delete_service_by_name: "
+               "Failed to delete service_name: %s\n",
+               sr_name );
+      status = IB_SUCCESS;
+    }      
+  }
+
+ Exit:
+  if( context.result.p_result_madw != NULL )
+  {
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+    context.result.p_result_madw = NULL;
+  }
+
+ ExitNoDel:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+/*
+ * Run a complete service records flow:
+ * - register a service
+ * - register a service (with a lease period)
+ * - get a service by name
+ * - get all services / must be 2
+ * - delete a service
+ * - get all services / must be 1
+ * - wait for the lease to expire
+ * - get all services / must be 0
+ * - get / set service by data
+ */
+ib_api_status_t
+osmt_run_service_records_flow( IN osmtest_t * const p_osmt ) {
+  ib_service_record_t srv_rec;
+  ib_api_status_t status;
+  uint8_t instance,i;
+  uint8_t      service_data8[16],service_key[16];
+  ib_net16_t      service_data16[8];
+  ib_net32_t      service_data32[4];
+  ib_net64_t      service_data64[2];
+  uint64_t pid = getpid();
+  uint64_t id[7];
+  /* We use up to seven service names - we use the extra for bad flow*/
+  ib_svc_name_t   service_name[7];
+#ifdef VENDOR_RMPP_SUPPORT
+  /* This array contain only the valid names after registering vs SM */
+  ib_svc_name_t   service_valid_names[3];
+  uint32_t num_recs = 0;
+#endif
+
+  OSM_LOG_ENTER( &p_osmt->log,  osmt_run_service_records_flow);
+
+  /* Init Service names */
+  for (i = 0; i <= 6; i++) {
+#ifdef __WIN__
+    uint64_t rand_val = rand()-(uint64_t)i;
+#else
+    uint64_t rand_val = random()-(uint64_t)i;
+#endif
+    id[i] = abs((int)(pid - rand_val));
+    /* Just to be unique any place on any host */
+    sprintf((char*)(service_name[i]),
+            "osmt.srvc.%" PRIu64 ".%" PRIu64, rand_val,pid);
+    /*printf("-I- Service Name is : %s, ID is : 0x%" PRIx64 "\n",service_name[i],id[i]);*/
+  }
+  status = osmt_register_service(
+    p_osmt,
+    cl_ntoh64(id[0]),  /*  IN ib_net64_t      service_id, */
+    IB_DEFAULT_PKEY,/*  IN ib_net16_t      service_pkey, */
+    0xFFFFFFFF,     /*  IN ib_net32_t      service_lease, */
+    11,             /*  IN uint8_t         service_key_lsb, */
+    (char*)service_name[0]   /*  IN char            *service_name */
+    );
+  if (status != IB_SUCCESS)
+  {
+    goto Exit;
+  }
+
+  status = osmt_register_service(
+    p_osmt,
+    cl_ntoh64(id[1]),  /*  IN ib_net64_t      service_id, */
+    IB_DEFAULT_PKEY,/*  IN ib_net16_t      service_pkey, */
+    cl_hton32(0x00000004), /*  IN ib_net32_t     service_lease, */
+    11,             /*  IN uint8_t         service_key_lsb, */
+    (char*)service_name[1]   /*  IN char            *service_name */
+    );
+  if (status != IB_SUCCESS)
+  {
+    goto Exit;
+  }
+
+  status = osmt_register_service(
+    p_osmt,
+    cl_ntoh64(id[2]),  /*  IN ib_net64_t      service_id, */
+    0,                 /*  IN ib_net16_t      service_pkey, */
+    0xFFFFFFFF,        /*  IN ib_net32_t      service_lease, */
+    11,                /* Remove Service Record IN uint8_t service_key_lsb, */
+    (char*)service_name[2]    /*  IN char            *service_name */
+    );
+
+  if (status != IB_SUCCESS)
+  {
+    goto Exit;
+  }
+
+  /*  Generate 2 instances of service record with consecutive data */
+  for (instance = 0 ; instance < 2 ; instance++) {
+    /*  First, clear all arrays */
+    memset (service_data8, 0, 16*sizeof(uint8_t));
+    memset (service_data16, 0, 8*sizeof(uint16_t));
+    memset (service_data32, 0, 4*sizeof(uint32_t));
+    memset (service_data64, 0, 2*sizeof(uint64_t));
+    service_data8[instance] = instance+1;
+    service_data16[instance] = cl_hton16(instance+2);
+    service_data32[instance] = cl_hton32(instance+3);
+    service_data64[instance] = cl_hton64(instance+4);
+    status = osmt_register_service_with_data(
+      p_osmt,
+      cl_ntoh64(id[3]),  /*  IN ib_net64_t      service_id, */
+      IB_DEFAULT_PKEY,              /*  IN ib_net16_t      service_pkey, */
+      cl_ntoh32(10),     /*  IN ib_net32_t      service_lease, */
+      12,             /*  IN uint8_t         service_key_lsb, */
+      service_data8,service_data16,service_data32,service_data64, /* service data structures */
+      (char*)service_name[3]   /*  IN char            *service_name */
+      );
+
+    if (status != IB_SUCCESS)
+    {
+      goto Exit;
+    }
+
+  }
+
+  /*  Trying to create service with zero key */
+  memset (service_key, 0, 16*sizeof(uint8_t));
+  status = osmt_register_service_with_full_key(
+    p_osmt,
+    cl_ntoh64(id[5]),  /*  IN ib_net64_t      service_id, */
+    0,                 /*  IN ib_net16_t      service_pkey, */
+    0xFFFFFFFF,        /*  IN ib_net32_t      service_lease, */
+    service_key,       /*  full service_key, */
+    (char*)service_name[5]    /*  IN char            *service_name */
+    );
+
+  if (status != IB_SUCCESS)
+  {
+    goto Exit;
+  }
+
+  /*  Now update it with Unique key and different service name */
+  for (i = 0; i <= 15; i++) {
+    service_key[i] = i + 1;
+  }
+  status = osmt_register_service_with_full_key(
+    p_osmt,
+    cl_ntoh64(id[5]),  /*  IN ib_net64_t      service_id, */
+    0,              /*  IN ib_net16_t      service_pkey, */
+    0xFFFFFFFF,     /*  IN ib_net32_t      service_lease, */
+    service_key,             /* full service_key, */
+    (char*)service_name[6]   /*  IN char            *service_name */
+    );
+  if (status != IB_SUCCESS)
+  {
+    goto Exit;
+  }
+
+  /* Let OpenSM handle it */
+  usleep(100);
+
+  /* Make sure service_name[0] exists */
+  status = osmt_get_service_by_name(p_osmt,
+                                    (char*)service_name[0], 1, &srv_rec);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A1A: "
+             "Fail to find service: name: %s\n",
+             (char*)service_name[0] );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Make sure service_name[1] exists */
+  status = osmt_get_service_by_name(p_osmt,
+                                    (char*)service_name[1], 1, &srv_rec);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A1B: "
+             "Fail to find service: name: %s\n",
+             (char*)service_name[1] );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Make sure service_name[2] exists */
+  status = osmt_get_service_by_name(p_osmt,
+                                    (char*)service_name[2], 1, &srv_rec);
+  if (status != IB_SUCCESS)
+  {
+     osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A1C: "
+             "Fail to find service: name: %s\n",
+             (char*)service_name[2] );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Make sure service_name[3] exists. */
+  /* After 10 seconds the service should not exist: service_lease = 10 */
+  status = osmt_get_service_by_name(p_osmt,
+                                    (char*)service_name[3], 1, &srv_rec);
+  if (status != IB_SUCCESS)
+  {
+     osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A1D: "
+             "Fail to find service: name: %s\n",
+             (char*)service_name[3] );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  sleep(10);
+
+  status = osmt_get_service_by_name(p_osmt,
+                                    (char*)service_name[3], 0, &srv_rec);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A1E: "
+             "Found service: name: %s that should have been "
+             "deleted due to service lease expiring\n",
+             (char*)service_name[3] );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /*  Check that for service: id[5] only one record exists */
+  status = osmt_get_service_by_id(p_osmt, 1, cl_ntoh64(id[5]), &srv_rec);
+  if (status != IB_SUCCESS)
+  {
+     osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A1F: "
+             "Found number of records != 1 for "
+             "service: id: 0x%016" PRIx64 "\n",
+              id[5] );
+     status = IB_ERROR;
+    goto Exit;
+  }
+
+  /*  Bad Flow of Get with invalid Service ID: id[7] */
+  status = osmt_get_service_by_id(p_osmt, 0, cl_ntoh64(id[7]), &srv_rec);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A20: "
+             "Found service: id: 0x%016" PRIx64 " "
+             "that is invalid\n",
+             id[7] );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /*  Check by both id and service name: id[0], service_name[0] */
+  status = osmt_get_service_by_id_and_name(p_osmt, 1, cl_ntoh64(id[0]),
+                                           (char*)service_name[0], &srv_rec);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A21: "
+             "Fail to find service: id: 0x%016" PRIx64 " "
+             "name: %s\n",
+             id[0],
+             (char*)service_name[0] );
+    status = IB_ERROR;
+    goto Exit;
+  }
+  
+  /*  Check by both id and service name: id[5], service_name[6] */
+  status = osmt_get_service_by_id_and_name(p_osmt, 1, cl_ntoh64(id[5]),
+                                           (char*)service_name[6], &srv_rec);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A22: "
+             "Fail to find service: id: 0x%016" PRIx64 " "
+             "name: %s\n",
+             id[5],
+             (char*)service_name[6] );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Bad Flow of Get with invalid name(service_name[3]) and valid ID(id[0]) */
+  status = osmt_get_service_by_id_and_name(p_osmt, 0, cl_ntoh64(id[0]),
+                                           (char*)service_name[3], &srv_rec);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A23: "
+             "Found service: id: 0x%016" PRIx64
+             "name: %s which is an invalid service\n",
+             id[0],
+             (char*)service_name[3] );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /*  Bad Flow of Get with unmatched name(service_name[5]) and id(id[3]) (both valid) */
+  status = osmt_get_service_by_id_and_name(p_osmt, 0, cl_ntoh64(id[3]),
+                                           (char*)service_name[5], &srv_rec);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A24: "
+             "Found service: id: 0x%016" PRIx64
+             "name: %s which is an invalid service\n",
+             id[3],
+             (char*)service_name[5] );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Bad Flow of Get with service name that doesn't exist (service_name[4]) */
+  status = osmt_get_service_by_name(p_osmt,
+                                    (char*)service_name[4], 0, &srv_rec);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A25: "
+             "Found service: name: %s that shouldn't exist\n",
+             (char*)service_name[4] );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /*  Bad Flow : Check that getting service_name[5] brings no records since another service
+      has been updated with the same ID (service_name[6] */
+  status = osmt_get_service_by_name(p_osmt,
+                                    (char*)service_name[5], 0, &srv_rec);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A26: "
+             "Found service: name: %s which is an "
+             "invalid service\n",
+             (char*)service_name[5] );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /*  Check that getting service_name[6] by name ONLY is valid,
+      since we do not support key&name association, also trusted queries */
+  status = osmt_get_service_by_name(p_osmt,
+                                    (char*)service_name[6], 1, &srv_rec);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A27: "
+             "Fail to find service: name: %s\n",
+             (char*)service_name[6] );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /*  Test Service Key */
+  memset(service_key, 0, 16*sizeof(uint8_t));
+
+  /* Check for service_name[5] with service_key=0 - the service shouldn't
+     exist with this name. */
+  status = osmt_get_service_by_name_and_key (p_osmt,
+                                             (char*)service_name[5],
+                                             0, service_key,&srv_rec);  
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A28: "
+             "Found service: name: %s key:0 which is an "
+             "invalid service (wrong name)\n",
+             (char*)service_name[5] );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Check for service_name[6] with service_key=0 - the service should
+     exist with different key. */
+  status = osmt_get_service_by_name_and_key (p_osmt,
+                                             (char*)service_name[6],
+                                             0, service_key,&srv_rec);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A29: "
+             "Found service: name: %s key: 0 which is an "
+             "invalid service (wrong service_key)\n",
+             (char*)service_name[6] );
+    status = IB_ERROR;
+    goto Exit;
+  }
+      
+  /* check for service_name[6] with the correct service_key */
+  for (i = 0; i <= 15; i++) 
+    service_key[i]=i + 1;
+  status = osmt_get_service_by_name_and_key (p_osmt,
+                                             (char*)service_name[6],
+                                             1, service_key, &srv_rec);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A2A: "
+             "Fail to find service: name: %s with "
+             "correct service key\n",
+             (char*)service_name[6] );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+#ifdef VENDOR_RMPP_SUPPORT
+  /* These ar the only service_names which are valid */
+  memcpy(&service_valid_names[0], &service_name[0], sizeof(uint8_t)*64);
+  memcpy(&service_valid_names[1], &service_name[2], sizeof(uint8_t)*64);
+  memcpy(&service_valid_names[2], &service_name[6], sizeof(uint8_t)*64);
+
+  status = osmt_get_all_services_and_check_names(p_osmt,service_valid_names, 3, &num_recs);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A2B: "
+             "Fail to find all services that should exist\n" );
+    status = IB_ERROR;
+    goto Exit;
+  }
+#endif
+
+  /* Delete service_name[0] */ 
+  status = osmt_delete_service_by_name(p_osmt, 1,
+                                       (char*)service_name[0], 1);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A2C: "
+             "Fail to delete service: name: %s\n",
+             (char*)service_name[0] );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Make sure deletion of service_name[0] succeeded */
+  status = osmt_get_service_by_name(p_osmt,
+                                    (char*)service_name[0], 0, &srv_rec);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A2D: "
+             "Found service: name: %s that was deleted\n",
+             (char*)service_name[0] );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Make sure service_name[1] doesn't exist (expired service lease) */
+  status = osmt_get_service_by_name(p_osmt,
+                                    (char*)service_name[1], 0, &srv_rec);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A2E: "
+             "Found service: name: %s that should have expired\n",
+             (char*)service_name[1] );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Make sure service_name[2] exists */
+  status = osmt_get_service_by_name(p_osmt,
+                                    (char*)service_name[2], 1, &srv_rec);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A2F: "
+             "Fail to find service: name: %s\n",
+             (char*)service_name[2] );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /*  Bad Flow - try to delete non-existent service_name[5] */
+  status = osmt_delete_service_by_name(p_osmt, 0,
+                                       (char*)service_name[5], 0);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A30: "
+             "Succeed to delete non-existent service: name: %s\n",
+             (char*)service_name[5] );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Delete service_name[2] */
+  status = osmt_delete_service_by_name(p_osmt, 1,
+                                       (char*)service_name[2], 1);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A31: "
+             "Fail to delete service: name: %s\n",
+             (char*)service_name[2] );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Delete service_name[6] */
+  status = osmt_delete_service_by_name(p_osmt, 1,
+                                       (char*)service_name[6], 1);
+  if (status != IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: ERR 4A32: "
+             "Failed to delete service name: %s\n",
+             (char*)service_name[6] );
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return status;
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_slvl_vl_arb.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmt_slvl_vl_arb.c
new file mode 100644 (file)
index 0000000..bb8c97a
--- /dev/null
@@ -0,0 +1,570 @@
+/*
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: osmt_slvl_vl_arb.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of SLtoVL and VL Arbitration testing flow..
+ *    Top level is osmt_run_slvl_and_vlarb_records_flow:
+ *     osmt_query_all_ports_vl_arb
+ *     osmt_query_all_ports_slvl_map 
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+#ifndef __WIN__
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include "osmtest.h"
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_write_vl_arb_table( IN osmtest_t * const p_osmt,
+                            IN FILE * fh,
+                            IN const ib_vl_arb_table_record_t * const p_rec )
+{
+  int result,i;
+  cl_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_vl_arb_table );
+
+  result = fprintf( fh,
+                    "VL_ARBITRATION_TABLE\n"
+                    "lid                     0x%X\n"
+                    "port_num                0x%X\n"
+                    "block                   0x%X\n",
+                    cl_ntoh16( p_rec->lid ),
+                    p_rec->port_num,
+                    p_rec->block_num );
+
+  fprintf( fh, "       ");
+  for (i = 0; i < 32; i++)
+    fprintf( fh,"| %-2u ", i);
+  fprintf( fh, "|\nVL:    ");
+
+  for (i = 0; i < 32; i++)
+    fprintf( fh,"|0x%02X",p_rec->vl_arb_tbl.vl_entry[i].vl);
+  fprintf( fh, "|\nWEIGHT:");
+
+  for (i = 0; i < 32; i++)
+    fprintf( fh,"|0x%02X",p_rec->vl_arb_tbl.vl_entry[i].weight);
+  fprintf( fh,"|\nEND\n\n");
+
+  /*  Exit: */
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ * GET A SINGLE PORT INFO BY NODE LID AND PORT NUMBER
+ **********************************************************************/
+ib_api_status_t
+osmt_query_vl_arb(
+                  IN osmtest_t * const p_osmt,
+                  IN ib_net16_t const lid,
+                  IN uint8_t const port_num,
+                  IN uint8_t const block_num,
+                  IN FILE *fh )
+{
+  osmtest_req_context_t context;
+  ib_api_status_t status = IB_SUCCESS;
+  osmv_user_query_t user;
+  osmv_query_req_t req;
+  ib_vl_arb_table_record_t record, *p_rec;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmt_query_vl_arb );
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+             "osmt_query_vl_arb: "
+             "Getting VL_Arbitration Table for port with LID 0x%X Num:0x%X\n",
+             cl_ntoh16( lid ),
+             port_num );
+  }
+
+  /*
+   * Do a blocking query for this record in the subnet.
+   * The result is returned in the result field of the caller's
+   * context structure.
+   *
+   * The query structures are locals.
+   */
+  memset( &req, 0, sizeof( req ) );
+  memset( &user, 0, sizeof( user ) );
+  memset( &context, 0, sizeof( context ) );
+
+  context.p_osmt = p_osmt;
+
+  record.lid = lid;
+  record.port_num = port_num;
+  record.block_num = block_num;
+  user.p_attr = &record;
+
+  req.query_type = OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK;
+  req.timeout_ms = p_osmt->opt.transaction_timeout;
+  req.retry_cnt = p_osmt->opt.retry_count;
+  req.flags = OSM_SA_FLAGS_SYNC;
+  req.query_context = &context;
+  req.pfn_query_cb = osmtest_query_res_cb;
+  req.p_query_input = &user;
+  req.sm_key = 0;
+
+  status = osmv_query_sa( p_osmt->h_bind, &req );
+
+  if ( status != IB_SUCCESS )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_query_vl_arb: ERR 0405: "
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  status = context.result.status;
+
+  if( status != IB_SUCCESS )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_query_vl_arb: ERR 0466: "
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );
+
+    if( status == IB_REMOTE_ERROR )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_query_vl_arb: "
+               "Remote error = %s\n",
+               ib_get_mad_status_str( osm_madw_get_mad_ptr
+                                      ( context.result.p_result_madw ) ) );
+    }
+    goto Exit;
+  }
+
+  /* ok it worked */
+  p_rec = osmv_get_query_result( context.result.p_result_madw, 0);
+  if ( fh )
+  {
+    osmtest_write_vl_arb_table( p_osmt, fh, p_rec );
+  }
+
+ Exit:
+  /*
+   * Return the IB query MAD to the pool as necessary.
+   */
+  if( context.result.p_result_madw != NULL )
+  {
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+    context.result.p_result_madw = NULL;
+  }
+
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+static ib_api_status_t
+osmt_query_all_ports_vl_arb( IN osmtest_t * const p_osmt,
+                             IN FILE * fh )
+{
+  cl_status_t status = CL_SUCCESS;
+  cl_qmap_t *p_tbl;
+  port_t *p_src_port;
+  uint8_t block, anyErr = 0;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmt_query_all_ports_vl_arb );
+
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_query_all_ports_vl_arb: "
+           "Obtaining ALL Ports VL Arbitration Tables\n");
+
+  /*
+   * Go over all ports that exist in the subnet
+   * get the relevant VLarbs 
+   */
+
+  p_tbl = &p_osmt->exp_subn.port_key_tbl;
+
+  p_src_port = ( port_t * ) cl_qmap_head( p_tbl );
+
+  while( p_src_port != ( port_t * ) cl_qmap_end( p_tbl ) )
+  {
+
+    /* HACK we use capability_mask to know diff a CA port from switch port */
+    if( p_src_port->rec.port_info.capability_mask )
+    {
+      /* this is an hca port */
+      for (block = 1; block <= 4; block++)
+      {
+        /*  NOTE to comply we must set port number to 0 and the SA should figure it out */
+        /*  since it is a CA port */
+        status = osmt_query_vl_arb(p_osmt, p_src_port->rec.lid, 0, block, fh);
+        if (status != IB_SUCCESS)
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmt_query_all_ports_vl_arb: ERR 0467: "
+                   "Failed to get Lid:0x%X Port:0x%X (%s)\n",
+                   cl_ntoh16(p_src_port->rec.lid), 0,
+                   ib_get_err_str( status ) );
+          anyErr = 1;
+        }
+      }
+    }
+    else
+    {
+      /* this is a switch port */
+      for (block = 1; block <= 4; block++)
+      {
+        status = osmt_query_vl_arb(p_osmt, p_src_port->rec.lid,
+                                   p_src_port->rec.port_num, block, fh);
+        if (status != IB_SUCCESS)
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmt_query_all_ports_vl_arb: ERR 0468: "
+                   "Failed to get Lid:0x%X Port:0x%X (%s)\n",
+                   cl_ntoh16(p_src_port->rec.lid), p_src_port->rec.port_num,
+                   ib_get_err_str( status ) );
+          anyErr = 1;
+        }
+      }
+    }
+
+    p_src_port = ( port_t * ) cl_qmap_next( &p_src_port->map_item );
+  }
+
+  OSM_LOG_EXIT( &p_osmt->log );
+  if (anyErr)
+  {
+    status = IB_ERROR;
+  }
+  return ( status );
+}
+
+/*******************************************************************************
+ SLtoVL
+*******************************************************************************/
+static ib_api_status_t
+osmtest_write_slvl_map_table( IN osmtest_t * const p_osmt,
+                              IN FILE * fh,
+                              IN const ib_slvl_table_record_t * const p_rec )
+{
+  int result, i;
+  cl_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_slvl_map_table );
+
+  result = fprintf( fh,
+                    "SLtoVL_MAP_TABLE\n"
+                    "lid                     0x%X\n"
+                    "in_port_num             0x%X\n"
+                    "out_port_num            0x%X\n",
+                    cl_ntoh16( p_rec->lid ),
+                    p_rec->in_port_num,
+                    p_rec->out_port_num );
+
+  fprintf( fh, "SL:");
+  for (i = 0; i < 16; i++)
+    fprintf( fh,"| %-2u  ", i);
+  fprintf( fh, "|\nVL:");
+
+  for (i = 0; i < 16; i++) 
+    fprintf( fh,"| 0x%01X ", ib_slvl_table_get( &p_rec->slvl_tbl, (uint8_t)i));
+  fprintf( fh,"|\nEND\n\n");
+
+  /*  Exit: */
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ * GET A SINGLE PORT INFO BY NODE LID AND PORT NUMBER
+ **********************************************************************/
+ib_api_status_t
+osmt_query_slvl_map(
+                    IN osmtest_t * const p_osmt,
+                    IN ib_net16_t const lid,
+                    IN uint8_t const out_port_num,
+                    IN uint8_t const in_port_num,
+                    IN FILE *fh )
+{
+  osmtest_req_context_t context;
+  ib_api_status_t status = IB_SUCCESS;
+  osmv_user_query_t user;
+  osmv_query_req_t req;
+  ib_slvl_table_record_t record, *p_rec;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmt_query_slvl_map );
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+             "osmt_query_slvl_map: "
+             "Getting SLtoVL Map Table for out-port with LID 0x%X Num:0x%X from In-Port:0x%X\n",
+             cl_ntoh16( lid ),
+             out_port_num, in_port_num );
+  }
+
+  /*
+   * Do a blocking query for this record in the subnet.
+   * The result is returned in the result field of the caller's
+   * context structure.
+   *
+   * The query structures are locals.
+   */
+  memset( &req, 0, sizeof( req ) );
+  memset( &user, 0, sizeof( user ) );
+  memset( &context, 0, sizeof( context ) );
+
+  context.p_osmt = p_osmt;
+
+  record.lid = lid;
+  record.in_port_num = in_port_num;
+  record.out_port_num = out_port_num;
+  user.p_attr = &record;
+
+  req.query_type = OSMV_QUERY_SLVL_BY_LID_AND_PORTS;
+  req.timeout_ms = p_osmt->opt.transaction_timeout;
+  req.retry_cnt = p_osmt->opt.retry_count;
+  req.flags = OSM_SA_FLAGS_SYNC;
+  req.query_context = &context;
+  req.pfn_query_cb = osmtest_query_res_cb;
+  req.p_query_input = &user;
+  req.sm_key = 0;
+
+  status = osmv_query_sa( p_osmt->h_bind, &req );
+
+  if ( status != IB_SUCCESS )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_query_slvl_map: ERR 0469: "
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  status = context.result.status;
+
+  if( status != IB_SUCCESS )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_query_slvl_map: ERR 0470: "
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );
+
+    if( status == IB_REMOTE_ERROR )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_query_slvl_map: "
+               "Remote error = %s\n",
+               ib_get_mad_status_str( osm_madw_get_mad_ptr
+                                      ( context.result.p_result_madw ) ) );
+    }
+    goto Exit;
+  }
+
+  /* ok it worked */
+  p_rec = osmv_get_query_result( context.result.p_result_madw, 0);
+  if ( fh )
+  {
+    osmtest_write_slvl_map_table( p_osmt, fh, p_rec );
+  }
+
+ Exit:
+  /*
+   * Return the IB query MAD to the pool as necessary.
+   */
+  if( context.result.p_result_madw != NULL )
+  {
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );
+    context.result.p_result_madw = NULL;
+  }
+
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+static ib_api_status_t
+osmt_query_all_ports_slvl_map( IN osmtest_t * const p_osmt,
+                               IN FILE * fh )
+{
+  cl_status_t status = CL_SUCCESS;
+  cl_qmap_t *p_tbl;
+  port_t *p_src_port;
+  uint8_t in_port,anyErr = 0, num_ports;
+  node_t *p_node;
+  const cl_qmap_t *p_node_tbl;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmt_query_all_ports_slvl_map );
+
+  /*
+   * Go over all ports that exist in the subnet
+   * get the relevant SLtoVLs
+   */
+
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_query_all_ports_slvl_map: "
+           "Obtaining ALL Ports (to other ports) SLtoVL Maps\n");
+
+  p_tbl = &p_osmt->exp_subn.port_key_tbl;
+  p_node_tbl = &p_osmt->exp_subn.node_lid_tbl;
+
+  p_src_port = ( port_t * ) cl_qmap_head( p_tbl );
+
+  while( p_src_port != ( port_t * ) cl_qmap_end( p_tbl ) )
+  {
+
+    /* HACK we use capability_mask to know diff a CA port from switch port */
+    if( p_src_port->rec.port_info.capability_mask )
+    {
+      /* this is an hca port */
+      /*  NOTE to comply we must set port number to 0 and the SA should figure it out */
+      /*  since it is a CA port */
+      status = osmt_query_slvl_map(p_osmt, p_src_port->rec.lid, 0, 0, fh);
+      if (status != IB_SUCCESS)
+      {
+        osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                 "osmt_query_all_ports_slvl_map: ERR 0471: "
+                 "Failed to get Lid:0x%X In-Port:0x%X Out-Port:0x%X(%s)\n",
+                 cl_ntoh16(p_src_port->rec.lid), 0, 0,
+                 ib_get_err_str( status ) );
+        anyErr = 1;
+      }
+    }
+    else
+    {
+      /* this is a switch port */
+      /* get the node */
+      p_node = ( node_t * ) cl_qmap_get( p_node_tbl, p_src_port->rec.lid );
+      if( p_node == ( node_t * ) cl_qmap_end( p_node_tbl ) )
+      {
+        osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                 "osmt_query_all_ports_slvl_map: ERR 0472: "
+                 "Failed to get Node by Lid:0x%X\n",
+                 p_src_port->rec.lid );
+        goto Exit;
+      }
+
+      num_ports = p_node->rec.node_info.num_ports;
+
+      for (in_port = 1; in_port <= num_ports; in_port++)
+      {
+        status = osmt_query_slvl_map(p_osmt, p_src_port->rec.lid,
+                                     p_src_port->rec.port_num, in_port, fh );
+        if (status != IB_SUCCESS)
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmt_query_all_ports_slvl_map: ERR 0473: "
+                   "Failed to get Lid:0x%X In-Port:0x%X Out-Port:0x%X (%s)\n",
+                   cl_ntoh16(p_src_port->rec.lid), p_src_port->rec.port_num, in_port,
+                   ib_get_err_str( status ) );
+          anyErr = 1;
+        }
+      }
+    }
+
+    p_src_port = ( port_t * ) cl_qmap_next( &p_src_port->map_item );
+  }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  if (anyErr)
+  {
+    status = IB_ERROR;
+  }
+  return ( status );
+}
+
+/*
+ * Run a vl arbitration queries and sl2vl maps queries flow:
+ * Good flow:
+ * - for each physical port on the network - obtain the VL Arb
+ * - for each CA physical port obtain its SLtoVL Map
+ * - for each SW physical port (out) obtain the SLtoVL Map to each other port
+ * BAD flow:
+ * - Try get with multiple results
+ * - Try gettable
+ * - Try providing non existing port
+ */
+ib_api_status_t
+osmt_run_slvl_and_vlarb_records_flow( IN osmtest_t * const p_osmt )
+{
+  ib_api_status_t status;
+  FILE *fh;
+  ib_net16_t test_lid;
+  uint8_t lmc;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmt_run_slvl_and_vlarb_records_flow );
+
+  fh = fopen("qos.txt","w");
+
+  /* go over all ports in the subnet */
+  status = osmt_query_all_ports_vl_arb( p_osmt, fh );
+  if (status != IB_SUCCESS)
+  {
+    goto Exit;
+  }
+
+  status = osmt_query_all_ports_slvl_map( p_osmt, fh );
+  if (status != IB_SUCCESS)
+  {
+    goto Exit;
+  }
+
+  /* If LMC > 0, test non base LID SA QoS Record requests */
+  status = osmtest_get_local_port_lmc( p_osmt, p_osmt->local_port.lid, &lmc );
+  if ( status != IB_SUCCESS )
+    goto Exit;
+
+  if (lmc != 0)
+  {
+    test_lid = cl_ntoh16( p_osmt->local_port.lid + 1);
+
+    status = osmt_query_vl_arb( p_osmt, test_lid, 0, 1, NULL );
+    if ( status != IB_SUCCESS )
+      goto Exit;
+
+    status = osmt_query_slvl_map( p_osmt, test_lid, 0, 0, NULL );
+    if ( status != IB_SUCCESS )
+      goto Exit;
+  }
+
+ Exit:
+  fclose(fh);
+  OSM_LOG_EXIT( &p_osmt->log );
+  return status;
+}
+
+
diff --git a/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmtest.c b/branches/WOF2-2/ulp/opensm/user_3_0_0/osmtest/osmtest.c
new file mode 100644 (file)
index 0000000..3282535
--- /dev/null
@@ -0,0 +1,7489 @@
+/*\r
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.\r
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.\r
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: osmtest.c 1928 2009-02-04 15:23:03Z tzachid $\r
+ */\r
+\r
+\r
+/* TODO : Check why we dont free the cl_qmap_items we store when reading DB */\r
+\r
+/*\r
+ * Abstract:\r
+ *    Implementation of osmtest_t.\r
+ *    This object represents the OSMTest Test object.\r
+ *\r
+ * Environment:\r
+ *    Linux User Mode\r
+ *\r
+ * $Revision: 1.10 $\r
+ */\r
+\r
+#ifdef __WIN__\r
+#pragma warning(disable : 4996)\r
+#endif\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#ifdef __WIN__\r
+#include <complib/cl_timer.h>\r
+#else\r
+#include <strings.h>\r
+#include <sys/time.h>\r
+#endif\r
+#include <complib/cl_debug.h>\r
+#include "osmtest.h"\r
+\r
+#ifndef __WIN__\r
+#define strnicmp strncasecmp\r
+#endif\r
+\r
+#define POOL_MIN_ITEMS  64\r
+#define GUID_ARRAY_SIZE 64\r
+\r
+typedef enum _osmtest_token_val\r
+{\r
+    OSMTEST_TOKEN_COMMENT = 0,\r
+    OSMTEST_TOKEN_END,\r
+    OSMTEST_TOKEN_DEFINE_NODE,\r
+    OSMTEST_TOKEN_DEFINE_PORT,\r
+    OSMTEST_TOKEN_DEFINE_PATH,\r
+    OSMTEST_TOKEN_DEFINE_LINK,\r
+    OSMTEST_TOKEN_LID,\r
+    OSMTEST_TOKEN_BASE_VERSION,\r
+    OSMTEST_TOKEN_CLASS_VERSION,\r
+    OSMTEST_TOKEN_NODE_TYPE,\r
+    OSMTEST_TOKEN_NUM_PORTS,\r
+    OSMTEST_TOKEN_SYS_GUID,\r
+    OSMTEST_TOKEN_NODE_GUID,\r
+    OSMTEST_TOKEN_PORT_GUID,\r
+    OSMTEST_TOKEN_PARTITION_CAP,\r
+    OSMTEST_TOKEN_DEVICE_ID,\r
+    OSMTEST_TOKEN_REVISION,\r
+    OSMTEST_TOKEN_PORT_NUM,\r
+    OSMTEST_TOKEN_VENDOR_ID,\r
+    OSMTEST_TOKEN_DGID,\r
+    OSMTEST_TOKEN_SGID,\r
+    OSMTEST_TOKEN_DLID,\r
+    OSMTEST_TOKEN_SLID,\r
+    OSMTEST_TOKEN_HOP_FLOW_RAW,\r
+    OSMTEST_TOKEN_TCLASS,\r
+    OSMTEST_TOKEN_NUM_PATH,\r
+    OSMTEST_TOKEN_PKEY,\r
+    OSMTEST_TOKEN_SL,\r
+    OSMTEST_TOKEN_RATE,\r
+    OSMTEST_TOKEN_PKT_LIFE,\r
+    OSMTEST_TOKEN_PREFERENCE,\r
+    OSMTEST_TOKEN_MKEY,\r
+    OSMTEST_TOKEN_SUBN_PREF,\r
+    OSMTEST_TOKEN_BASE_LID,\r
+    OSMTEST_TOKEN_SM_BASE_LID,\r
+    OSMTEST_TOKEN_CAP_MASK,\r
+    OSMTEST_TOKEN_DIAG_CODE,\r
+    OSMTEST_TOKEN_MKEY_LEASE_PER,\r
+    OSMTEST_TOKEN_LOC_PORT_NUM,\r
+    OSMTEST_TOKEN_LINK_WID_EN,\r
+    OSMTEST_TOKEN_LINK_WID_SUP,\r
+    OSMTEST_TOKEN_LINK_WID_ACT,\r
+    OSMTEST_TOKEN_LINK_SPEED_SUP,\r
+    OSMTEST_TOKEN_PORT_STATE,\r
+    OSMTEST_TOKEN_STATE_INFO2,\r
+    OSMTEST_TOKEN_MKEY_PROT_BITS,\r
+    OSMTEST_TOKEN_LMC,\r
+    OSMTEST_TOKEN_LINK_SPEED,\r
+    OSMTEST_TOKEN_MTU_SMSL,\r
+    OSMTEST_TOKEN_VL_CAP,\r
+    OSMTEST_TOKEN_VL_HIGH_LIMIT,\r
+    OSMTEST_TOKEN_VL_ARB_HIGH_CAP,\r
+    OSMTEST_TOKEN_VL_ARB_LOW_CAP,\r
+    OSMTEST_TOKEN_MTU_CAP,\r
+    OSMTEST_TOKEN_VL_STALL_LIFE,\r
+    OSMTEST_TOKEN_VL_ENFORCE,\r
+    OSMTEST_TOKEN_MKEY_VIOL,\r
+    OSMTEST_TOKEN_PKEY_VIOL,\r
+    OSMTEST_TOKEN_QKEY_VIOL,\r
+    OSMTEST_TOKEN_GUID_CAP,\r
+    OSMTEST_TOKEN_SUBN_TIMEOUT,\r
+    OSMTEST_TOKEN_RESP_TIME_VAL,\r
+    OSMTEST_TOKEN_ERR_THRESHOLD,\r
+    OSMTEST_TOKEN_MTU,\r
+    OSMTEST_TOKEN_FROMLID,\r
+    OSMTEST_TOKEN_FROMPORTNUM,\r
+    OSMTEST_TOKEN_TOPORTNUM,\r
+    OSMTEST_TOKEN_TOLID,\r
+    OSMTEST_TOKEN_UNKNOWN\r
+} osmtest_token_val_t;\r
+\r
+typedef struct _osmtest_token\r
+{\r
+  osmtest_token_val_t val;\r
+  size_t str_size;\r
+  const char *str;\r
+} osmtest_token_t;\r
+\r
+const osmtest_token_t token_array[] = {\r
+  {OSMTEST_TOKEN_COMMENT, 1, "#"},\r
+  {OSMTEST_TOKEN_END, 3, "END"},\r
+  {OSMTEST_TOKEN_DEFINE_NODE, 11, "DEFINE_NODE"},\r
+  {OSMTEST_TOKEN_DEFINE_PORT, 11, "DEFINE_PORT"},\r
+  {OSMTEST_TOKEN_DEFINE_PATH, 11, "DEFINE_PATH"},\r
+  {OSMTEST_TOKEN_DEFINE_LINK, 11, "DEFINE_LINK"},\r
+  {OSMTEST_TOKEN_LID, 3, "LID"},\r
+  {OSMTEST_TOKEN_BASE_VERSION, 12, "BASE_VERSION"},\r
+  {OSMTEST_TOKEN_CLASS_VERSION, 13, "CLASS_VERSION"},\r
+  {OSMTEST_TOKEN_NODE_TYPE, 9, "NODE_TYPE"},\r
+  {OSMTEST_TOKEN_NUM_PORTS, 9, "NUM_PORTS"},\r
+  {OSMTEST_TOKEN_SYS_GUID, 8, "SYS_GUID"},\r
+  {OSMTEST_TOKEN_NODE_GUID, 9, "NODE_GUID"},\r
+  {OSMTEST_TOKEN_PORT_GUID, 9, "PORT_GUID"},\r
+  {OSMTEST_TOKEN_PARTITION_CAP, 13, "PARTITION_CAP"},\r
+  {OSMTEST_TOKEN_DEVICE_ID, 9, "DEVICE_ID"},\r
+  {OSMTEST_TOKEN_REVISION, 8, "REVISION"},\r
+  {OSMTEST_TOKEN_PORT_NUM, 8, "PORT_NUM"},\r
+  {OSMTEST_TOKEN_VENDOR_ID, 9, "VENDOR_ID"},\r
+  {OSMTEST_TOKEN_DGID, 4, "DGID"},\r
+  {OSMTEST_TOKEN_SGID, 4, "SGID"},\r
+  {OSMTEST_TOKEN_DLID, 4, "DLID"},\r
+  {OSMTEST_TOKEN_SLID, 4, "SLID"},\r
+  {OSMTEST_TOKEN_HOP_FLOW_RAW, 12, "HOP_FLOW_RAW"},\r
+  {OSMTEST_TOKEN_TCLASS, 6, "TCLASS"},\r
+  {OSMTEST_TOKEN_NUM_PATH, 8, "NUM_PATH"},\r
+  {OSMTEST_TOKEN_PKEY, 4, "PKEY"},\r
+  {OSMTEST_TOKEN_SL, 2, "SL"},\r
+  {OSMTEST_TOKEN_RATE, 4, "RATE"},\r
+  {OSMTEST_TOKEN_PKT_LIFE, 8, "PKT_LIFE"},\r
+  {OSMTEST_TOKEN_PREFERENCE, 10, "PREFERENCE"},\r
+  {OSMTEST_TOKEN_MKEY, 4, "M_KEY"},\r
+  {OSMTEST_TOKEN_SUBN_PREF, 13, "SUBNET_PREFIX"},\r
+  {OSMTEST_TOKEN_BASE_LID, 8, "BASE_LID"},\r
+  {OSMTEST_TOKEN_SM_BASE_LID, 18, "MASTER_SM_BASE_LID"},\r
+  {OSMTEST_TOKEN_CAP_MASK, 15, "CAPABILITY_MASK"},\r
+  {OSMTEST_TOKEN_DIAG_CODE, 9, "DIAG_CODE"},\r
+  {OSMTEST_TOKEN_MKEY_LEASE_PER, 18, "m_key_lease_period"},\r
+  {OSMTEST_TOKEN_LOC_PORT_NUM, 14, "local_port_num"},\r
+  {OSMTEST_TOKEN_LINK_WID_EN, 18, "link_width_enabled"},\r
+  {OSMTEST_TOKEN_LINK_WID_SUP, 20, "link_width_supported"},\r
+  {OSMTEST_TOKEN_LINK_WID_ACT, 17, "link_width_active"},\r
+  {OSMTEST_TOKEN_LINK_SPEED_SUP, 20, "link_speed_supported"},\r
+  {OSMTEST_TOKEN_PORT_STATE, 10, "port_state"},\r
+  {OSMTEST_TOKEN_STATE_INFO2, 10, "state_info2"},\r
+  {OSMTEST_TOKEN_MKEY_PROT_BITS, 3, "mpb"},\r
+  {OSMTEST_TOKEN_LMC, 3, "lmc"},\r
+  {OSMTEST_TOKEN_LINK_SPEED, 10, "link_speed"},\r
+  {OSMTEST_TOKEN_MTU_SMSL, 8, "mtu_smsl"},\r
+  {OSMTEST_TOKEN_VL_CAP, 6, "vl_cap"},\r
+  {OSMTEST_TOKEN_VL_HIGH_LIMIT, 13, "vl_high_limit"},\r
+  {OSMTEST_TOKEN_VL_ARB_HIGH_CAP, 15, "vl_arb_high_cap"},\r
+  {OSMTEST_TOKEN_VL_ARB_LOW_CAP,  14, "vl_arb_low_cap"},\r
+  {OSMTEST_TOKEN_MTU_CAP, 7, "mtu_cap"},\r
+  {OSMTEST_TOKEN_VL_STALL_LIFE,   13, "vl_stall_life"},\r
+  {OSMTEST_TOKEN_VL_ENFORCE, 10,  "vl_enforce"},\r
+  {OSMTEST_TOKEN_MKEY_VIOL, 16,  "m_key_violations"},\r
+  {OSMTEST_TOKEN_PKEY_VIOL, 16,  "p_key_violations"},\r
+  {OSMTEST_TOKEN_QKEY_VIOL, 16,  "q_key_violations"},\r
+  {OSMTEST_TOKEN_GUID_CAP, 8,  "guid_cap"},\r
+  {OSMTEST_TOKEN_SUBN_TIMEOUT, 14,  "subnet_timeout"},\r
+  {OSMTEST_TOKEN_RESP_TIME_VAL, 15, "resp_time_value"},\r
+  {OSMTEST_TOKEN_ERR_THRESHOLD, 15, "error_threshold"},\r
+  {OSMTEST_TOKEN_MTU, 3, "MTU"}, /*  must be after the other mtu... tokens. */\r
+  {OSMTEST_TOKEN_FROMLID, 8, "from_lid"},\r
+  {OSMTEST_TOKEN_FROMPORTNUM, 13, "from_port_num"},\r
+  {OSMTEST_TOKEN_TOPORTNUM, 11, "to_port_num"},\r
+  {OSMTEST_TOKEN_TOLID, 6, "to_lid"},\r
+  {OSMTEST_TOKEN_UNKNOWN, 0, ""} /* must be last entry */\r
+};\r
+\r
+#define IB_MAD_STATUS_CLASS_MASK       (CL_HTON16(0xFF00))\r
+\r
+static const char ib_mad_status_str_busy[] = "IB_MAD_STATUS_BUSY";\r
+static const char ib_mad_status_str_redirect[] = "IB_MAD_STATUS_REDIRECT";\r
+static const char ib_mad_status_str_unsup_class_ver[] =\r
+"IB_MAD_STATUS_UNSUP_CLASS_VER";\r
+static const char ib_mad_status_str_unsup_method[] =\r
+"IB_MAD_STATUS_UNSUP_METHOD";\r
+static const char ib_mad_status_str_unsup_method_attr[] =\r
+"IB_MAD_STATUS_UNSUP_METHOD_ATTR";\r
+static const char ib_mad_status_str_invalid_field[] =\r
+"IB_MAD_STATUS_INVALID_FIELD";\r
+static const char ib_mad_status_str_no_resources[] =\r
+"IB_SA_MAD_STATUS_NO_RESOURCES";\r
+static const char ib_mad_status_str_req_invalid[] =\r
+"IB_SA_MAD_STATUS_REQ_INVALID";\r
+static const char ib_mad_status_str_no_records[] =\r
+"IB_SA_MAD_STATUS_NO_RECORDS";\r
+static const char ib_mad_status_str_too_many_records[] =\r
+"IB_SA_MAD_STATUS_TOO_MANY_RECORDS";\r
+static const char ib_mad_status_str_invalid_gid[] =\r
+"IB_SA_MAD_STATUS_INVALID_GID";\r
+static const char ib_mad_status_str_insuf_comps[] =\r
+"IB_SA_MAD_STATUS_INSUF_COMPS";\r
+static const char generic_or_str[] = " | ";\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char *\r
+ib_get_mad_status_str( IN const ib_mad_t * const p_mad )\r
+{\r
+  static char line[512];\r
+  uint32_t offset = 0;\r
+  ib_net16_t status;\r
+  boolean_t first = TRUE;\r
+\r
+  line[offset] = '\0';\r
+\r
+  status = ( ib_net16_t ) ( p_mad->status & IB_SMP_STATUS_MASK );\r
+\r
+  if( status == 0 )\r
+  {\r
+    strcat( &line[offset], "IB_SUCCESS" );\r
+    return ( line );\r
+  }\r
+\r
+  if( status & IB_MAD_STATUS_BUSY )\r
+  {\r
+    strcat( &line[offset], ib_mad_status_str_busy );\r
+    offset += sizeof( ib_mad_status_str_busy );\r
+  }\r
+  if( status & IB_MAD_STATUS_REDIRECT )\r
+  {\r
+    if( !first )\r
+    {\r
+      strcat( &line[offset], generic_or_str );\r
+      offset += sizeof( generic_or_str ) - 1;\r
+    }\r
+    first = FALSE;\r
+    strcat( &line[offset], ib_mad_status_str_redirect );\r
+    offset += sizeof( ib_mad_status_str_redirect ) - 1;\r
+  }\r
+  if( ( status & IB_MAD_STATUS_INVALID_FIELD ) == IB_MAD_STATUS_UNSUP_CLASS_VER )\r
+  {\r
+    if( !first )\r
+    {\r
+      strcat( &line[offset], generic_or_str );\r
+      offset += sizeof( generic_or_str ) - 1;\r
+    }\r
+    first = FALSE;\r
+    strcat( &line[offset], ib_mad_status_str_unsup_class_ver );\r
+    offset += sizeof( ib_mad_status_str_unsup_class_ver ) - 1;\r
+  }\r
+  if( ( status & IB_MAD_STATUS_INVALID_FIELD ) == IB_MAD_STATUS_UNSUP_METHOD )\r
+  {\r
+    if( !first )\r
+    {\r
+      strcat( &line[offset], generic_or_str );\r
+      offset += sizeof( generic_or_str ) - 1;\r
+    }\r
+    first = FALSE;\r
+    strcat( &line[offset], ib_mad_status_str_unsup_method );\r
+    offset += sizeof( ib_mad_status_str_unsup_method ) - 1;\r
+  }\r
+  if( (status & IB_MAD_STATUS_INVALID_FIELD ) == IB_MAD_STATUS_UNSUP_METHOD_ATTR )\r
+  {\r
+    if( !first )\r
+    {\r
+      strcat( &line[offset], generic_or_str );\r
+      offset += sizeof( generic_or_str ) - 1;\r
+    }\r
+    first = FALSE;\r
+    strcat( &line[offset], ib_mad_status_str_unsup_method_attr );\r
+    offset += sizeof( ib_mad_status_str_unsup_method_attr ) - 1;\r
+  }\r
+  if( ( status & IB_MAD_STATUS_INVALID_FIELD ) == IB_MAD_STATUS_INVALID_FIELD )\r
+  {\r
+    if( !first )\r
+    {\r
+      strcat( &line[offset], generic_or_str );\r
+      offset += sizeof( generic_or_str ) - 1;\r
+    }\r
+    first = FALSE;\r
+    strcat( &line[offset], ib_mad_status_str_invalid_field );\r
+    offset += sizeof( ib_mad_status_str_invalid_field ) - 1;\r
+  }\r
+  if( ( status & IB_MAD_STATUS_CLASS_MASK ) ==\r
+      IB_SA_MAD_STATUS_NO_RESOURCES )\r
+  {\r
+    if( !first )\r
+    {\r
+      strcat( &line[offset], generic_or_str );\r
+      offset += sizeof( generic_or_str ) - 1;\r
+    }\r
+    first = FALSE;\r
+    strcat( &line[offset], ib_mad_status_str_no_resources );\r
+    offset += sizeof( ib_mad_status_str_no_resources ) - 1;\r
+  }\r
+  if( ( status & IB_MAD_STATUS_CLASS_MASK ) ==\r
+      IB_SA_MAD_STATUS_REQ_INVALID )\r
+  {\r
+    if( !first )\r
+    {\r
+      strcat( &line[offset], generic_or_str );\r
+      offset += sizeof( generic_or_str ) - 1;\r
+    }\r
+    first = FALSE;\r
+    strcat( &line[offset], ib_mad_status_str_req_invalid );\r
+    offset += sizeof( ib_mad_status_str_req_invalid ) - 1;\r
+  }\r
+  if( ( status & IB_MAD_STATUS_CLASS_MASK ) == IB_SA_MAD_STATUS_NO_RECORDS )\r
+  {\r
+    if( !first )\r
+    {\r
+      strcat( &line[offset], generic_or_str );\r
+      offset += sizeof( generic_or_str ) - 1;\r
+    }\r
+    first = FALSE;\r
+    strcat( &line[offset], ib_mad_status_str_no_records );\r
+    offset += sizeof( ib_mad_status_str_no_records ) - 1;\r
+  }\r
+  if( ( status & IB_MAD_STATUS_CLASS_MASK ) ==\r
+      IB_SA_MAD_STATUS_TOO_MANY_RECORDS )\r
+  {\r
+    if( !first )\r
+    {\r
+      strcat( &line[offset], generic_or_str );\r
+      offset += sizeof( generic_or_str ) - 1;\r
+    }\r
+    first = FALSE;\r
+    strcat( &line[offset], ib_mad_status_str_too_many_records );\r
+    offset += sizeof( ib_mad_status_str_too_many_records ) - 1;\r
+  }\r
+  if( ( status & IB_MAD_STATUS_CLASS_MASK ) ==\r
+      IB_SA_MAD_STATUS_INVALID_GID )\r
+  {\r
+    if( !first )\r
+    {\r
+      strcat( &line[offset], generic_or_str );\r
+      offset += sizeof( generic_or_str ) - 1;\r
+    }\r
+    first = FALSE;\r
+    strcat( &line[offset], ib_mad_status_str_invalid_gid );\r
+    offset += sizeof( ib_mad_status_str_invalid_gid ) - 1;\r
+  }\r
+  if( ( status & IB_MAD_STATUS_CLASS_MASK ) ==\r
+      IB_SA_MAD_STATUS_INSUF_COMPS )\r
+  {\r
+    if( !first )\r
+    {\r
+      strcat( &line[offset], generic_or_str );\r
+      offset += sizeof( generic_or_str ) - 1;\r
+    }\r
+    first = FALSE;\r
+    strcat( &line[offset], ib_mad_status_str_insuf_comps );\r
+    offset += sizeof( ib_mad_status_str_insuf_comps ) - 1;\r
+  }\r
+\r
+  return ( line );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+subnet_construct( IN subnet_t * const p_subn )\r
+{\r
+  cl_qmap_init( &p_subn->link_tbl );\r
+  cl_qmap_init( &p_subn->node_lid_tbl );\r
+  cl_qmap_init( &p_subn->node_guid_tbl );\r
+  cl_qmap_init( &p_subn->mgrp_mlid_tbl );\r
+\r
+  /*  NO WAY TO HAVE UNIQUE PORT BY LID OR GUID */\r
+  /*  cl_qmap_init( &p_subn->port_lid_tbl ); */\r
+  /*  cl_qmap_init( &p_subn->port_guid_tbl ); */\r
+\r
+  /*  port key is a lid and num pair */\r
+  cl_qmap_init( &p_subn->port_key_tbl );\r
+  cl_qmap_init( &p_subn->path_tbl );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+cl_status_t\r
+subnet_init( IN subnet_t * const p_subn )\r
+{\r
+  cl_status_t status = IB_SUCCESS;\r
+\r
+  subnet_construct( p_subn );\r
+\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osmtest_construct( IN osmtest_t * const p_osmt )\r
+{\r
+  memset( p_osmt, 0, sizeof( *p_osmt ) );\r
+  osm_log_construct( &p_osmt->log );\r
+  subnet_construct( &p_osmt->exp_subn );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osmtest_destroy( IN osmtest_t * const p_osmt )\r
+{\r
+  cl_map_item_t *p_item,*p_next_item;\r
+\r
+\r
+\r
+  /* Currently there is a problem with IBAL exit flow - memory overrun , so we bypass the vendor deletion\r
+     Since it's already will be cleaned by the Windows OS . */\r
+\r
+#ifndef __WIN__\r
+  if( p_osmt->p_vendor )\r
+  {\r
+    osm_vendor_delete( &p_osmt->p_vendor );\r
+  }\r
+#endif\r
+  cl_qpool_destroy( &p_osmt->port_pool );\r
+  cl_qpool_destroy( &p_osmt->node_pool );\r
+\r
+  /* destroy the qmap tables */\r
+  p_next_item = cl_qmap_head( &p_osmt->exp_subn.link_tbl );\r
+  while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.link_tbl ) )\r
+  {\r
+    p_item = p_next_item;\r
+    p_next_item = cl_qmap_next( p_item );\r
+    free( p_item );\r
+  }\r
+  p_next_item = cl_qmap_head( &p_osmt->exp_subn.mgrp_mlid_tbl );\r
+  while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.mgrp_mlid_tbl ) )\r
+  {\r
+    p_item = p_next_item;\r
+    p_next_item = cl_qmap_next( p_item );\r
+    free( p_item );\r
+  }\r
+  p_next_item = cl_qmap_head( &p_osmt->exp_subn.node_guid_tbl );\r
+  while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.node_guid_tbl ) )\r
+  {\r
+    p_item = p_next_item;\r
+    p_next_item = cl_qmap_next( p_item );\r
+    free( p_item );\r
+  }\r
+\r
+  p_next_item = cl_qmap_head( &p_osmt->exp_subn.node_lid_tbl );\r
+  while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.node_lid_tbl ) )\r
+  {\r
+    p_item = p_next_item;\r
+    p_next_item = cl_qmap_next( p_item );\r
+    free( p_item );\r
+  }\r
+\r
+  p_next_item = cl_qmap_head( &p_osmt->exp_subn.path_tbl );\r
+  while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.path_tbl ) )\r
+  {\r
+    p_item = p_next_item;\r
+    p_next_item = cl_qmap_next( p_item );\r
+    free( p_item );\r
+  }\r
+  p_next_item = cl_qmap_head( &p_osmt->exp_subn.port_key_tbl );\r
+  while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.port_key_tbl ) )\r
+  {\r
+    p_item = p_next_item;\r
+    p_next_item = cl_qmap_next( p_item );\r
+    free( p_item );\r
+  }\r
+\r
+  osm_log_destroy( &p_osmt->log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_init( IN osmtest_t * const p_osmt,\r
+              IN const osmtest_opt_t * const p_opt,\r
+              IN const osm_log_level_t log_flags\r
+              )\r
+{\r
+  ib_api_status_t status;\r
+\r
+  /* Can't use log macros here, since we're initializing the log. */\r
+  osmtest_construct( p_osmt );\r
+\r
+  status = osm_log_init_v2( &p_osmt->log, p_opt->force_log_flush,\r
+                            0x0001, p_opt->log_file, 0, TRUE );\r
+  if( status != IB_SUCCESS )\r
+    return ( status );\r
+\r
+  /* but we do not want any extra stuff here */\r
+  osm_log_set_level( &p_osmt->log, log_flags );\r
+\r
+  osm_log( &p_osmt->log, OSM_LOG_FUNCS,\r
+           "osmtest_init: [\n" );\r
+\r
+  p_osmt->opt = *p_opt;\r
+\r
+  status = cl_qpool_init( &p_osmt->node_pool, POOL_MIN_ITEMS, 0,\r
+                          POOL_MIN_ITEMS, sizeof( node_t ), NULL, NULL,\r
+                          NULL );\r
+  CL_ASSERT( status == CL_SUCCESS );\r
+\r
+  status = cl_qpool_init( &p_osmt->port_pool, POOL_MIN_ITEMS, 0,\r
+                          POOL_MIN_ITEMS, sizeof( port_t ), NULL, NULL,\r
+                          NULL );\r
+  CL_ASSERT( status == CL_SUCCESS );\r
+\r
+  p_osmt->p_vendor = osm_vendor_new( &p_osmt->log,\r
+                                     p_opt->transaction_timeout );\r
+\r
+  if( p_osmt->p_vendor == NULL )\r
+  {\r
+    status = IB_INSUFFICIENT_RESOURCES;\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_init: ERR 0001: "\r
+             "Unable to allocate vendor object" );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  osm_mad_pool_construct( &p_osmt->mad_pool );\r
+  status = osm_mad_pool_init( &p_osmt->mad_pool, &p_osmt->log );\r
+  if( status != IB_SUCCESS )\r
+    goto Exit;\r
+\r
+ Exit:\r
+  osm_log( &p_osmt->log, OSM_LOG_FUNCS,\r
+           "osmtest_init: ]\n" );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osmtest_query_res_cb( IN osmv_query_res_t * p_rec )\r
+{\r
+  osmtest_req_context_t *const p_ctxt =\r
+    ( osmtest_req_context_t * ) p_rec->query_context;\r
+  osmtest_t *const p_osmt = p_ctxt->p_osmt;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_query_res_cb );\r
+\r
+  p_ctxt->result = *p_rec;\r
+\r
+  if( p_rec->status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_query_res_cb: ERR 0003: "\r
+             "Error on query (%s)\n", ib_get_err_str( p_rec->status ) );\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_get_all_recs( IN osmtest_t * const p_osmt,\r
+                      IN ib_net16_t const attr_id,\r
+                      IN size_t const attr_size,\r
+                      IN OUT osmtest_req_context_t * const p_context )\r
+{\r
+  ib_api_status_t status = IB_SUCCESS;\r
+  osmv_user_query_t user;\r
+  osmv_query_req_t req;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_get_all_recs );\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+             "osmtest_get_all_recs: "\r
+             "Getting all %s records\n", ib_get_sa_attr_str( attr_id ) );\r
+  }\r
+\r
+  /*\r
+   * Do a blocking query for all <attr_id> records in the subnet.\r
+   * The result is returned in the result field of the caller's\r
+   * context structure.\r
+   *\r
+   * The query structures are locals.\r
+   */\r
+  memset( &req, 0, sizeof( req ) );\r
+  memset( &user, 0, sizeof( user ) );\r
+\r
+  p_context->p_osmt = p_osmt;\r
+  user.attr_id = attr_id;\r
+  user.attr_offset = cl_ntoh16( ( uint16_t ) ( attr_size >> 3 ) );\r
+\r
+  req.query_type = OSMV_QUERY_USER_DEFINED;\r
+  req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+  req.retry_cnt = p_osmt->opt.retry_count;\r
+  req.flags = OSM_SA_FLAGS_SYNC;\r
+  req.query_context = p_context;\r
+  req.pfn_query_cb = osmtest_query_res_cb;\r
+  req.p_query_input = &user;\r
+  req.sm_key = 0;\r
+\r
+  status = osmv_query_sa( p_osmt->h_bind, &req );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_all_recs: ERR 0004: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  status = p_context->result.status;\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_all_recs: ERR 0064: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+\r
+    if( status == IB_REMOTE_ERROR )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_get_all_recs: "\r
+               "Remote error = %s\n",\r
+               ib_get_mad_status_str( osm_madw_get_mad_ptr\r
+                                      ( p_context->result.p_result_madw ) ) );\r
+    }\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_validate_sa_class_port_info( IN osmtest_t * const p_osmt)\r
+{\r
+  ib_api_status_t status = IB_SUCCESS;\r
+  osmv_query_req_t req;\r
+  ib_class_port_info_t *p_cpi;\r
+  osmtest_req_context_t context;\r
+  osmtest_req_context_t *p_context = &context;\r
+  ib_sa_mad_t           *p_resp_sa_madp;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_sa_class_port_info );\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_validate_sa_class_port_info: "\r
+             "Getting ClassPortInfo\n");\r
+  }\r
+\r
+  /*\r
+   * Do a blocking query for this record in the subnet.\r
+   * The result is returned in the result field of the caller's\r
+   * context structure.\r
+   *\r
+   * The query structures are locals.\r
+   */\r
+  memset( &req, 0, sizeof( req ) );\r
+\r
+  p_context->p_osmt = p_osmt;\r
+  req.query_type = OSMV_QUERY_CLASS_PORT_INFO;\r
+  req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+  req.retry_cnt = p_osmt->opt.retry_count;\r
+  req.flags = OSM_SA_FLAGS_SYNC;\r
+  req.query_context = p_context;\r
+  req.pfn_query_cb = osmtest_query_res_cb;\r
+  req.p_query_input = 0;\r
+  req.sm_key = 0;\r
+\r
+  status = osmv_query_sa( p_osmt->h_bind, &req );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_sa_class_port_info: ERR 0065: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  status = p_context->result.status;\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_sa_class_port_info: ERR 0070: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    if( status == IB_REMOTE_ERROR )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_validate_sa_class_port_info: "\r
+               "Remote error = %s\n",\r
+               ib_get_mad_status_str( osm_madw_get_mad_ptr\r
+                                      ( p_context->result.p_result_madw ) ) );\r
+    }\r
+    goto Exit;\r
+  }\r
+\r
+  /* ok we got it so please print it out */\r
+  p_resp_sa_madp = (ib_sa_mad_t*)osm_madw_get_mad_ptr(context.result.p_result_madw);\r
+  p_cpi = (ib_class_port_info_t*)ib_sa_mad_get_payload_ptr(p_resp_sa_madp );\r
+\r
+  osm_log( &p_osmt->log, OSM_LOG_INFO,\r
+           "osmtest_validate_sa_class_port_info:\n-----------------------------\nSA Class Port Info:\n"\r
+           " base_ver:%u\n class_ver:%u\n cap_mask:0x%X\n resp_time_val:0x%X\n-----------------------------\n",\r
+           p_cpi->base_ver, p_cpi->class_ver, cl_ntoh16(p_cpi->cap_mask), p_cpi->cap_mask2_resp_time\r
+           );\r
+\r
+ Exit:\r
+#if 0\r
+  if( context.result.p_result_madw != NULL )\r
+  {\r
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+    context.result.p_result_madw = NULL;\r
+  }\r
+#endif\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_get_node_rec( IN osmtest_t * const p_osmt,\r
+                      IN ib_net64_t const node_guid,\r
+                      IN OUT osmtest_req_context_t * const p_context )\r
+{\r
+  ib_api_status_t status = IB_SUCCESS;\r
+  osmv_user_query_t user;\r
+  osmv_query_req_t req;\r
+  ib_node_record_t record;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_get_node_rec );\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_get_node_rec: "\r
+             "Getting node record for 0x%016" PRIx64 "\n",\r
+             cl_ntoh64( node_guid ) );\r
+  }\r
+\r
+  /*\r
+   * Do a blocking query for this record in the subnet.\r
+   * The result is returned in the result field of the caller's\r
+   * context structure.\r
+   *\r
+   * The query structures are locals.\r
+   */\r
+  memset( &req, 0, sizeof( req ) );\r
+  memset( &user, 0, sizeof( user ) );\r
+  memset( &record, 0, sizeof( record ) );\r
+\r
+  record.node_info.node_guid = node_guid;\r
+\r
+  p_context->p_osmt = p_osmt;\r
+  user.comp_mask = IB_NR_COMPMASK_NODEGUID;\r
+  user.attr_id = IB_MAD_ATTR_NODE_RECORD;\r
+  user.attr_offset = cl_ntoh16( ( uint16_t ) ( sizeof( record ) >> 3 ) );\r
+  user.p_attr = &record;\r
+\r
+  req.query_type = OSMV_QUERY_USER_DEFINED;\r
+  req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+  req.retry_cnt = p_osmt->opt.retry_count;\r
+  req.flags = OSM_SA_FLAGS_SYNC;\r
+  req.query_context = p_context;\r
+  req.pfn_query_cb = osmtest_query_res_cb;\r
+  req.p_query_input = &user;\r
+  req.sm_key = 0;\r
+\r
+  status = osmv_query_sa( p_osmt->h_bind, &req );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_node_rec: ERR 0071: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  status = p_context->result.status;\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_node_rec: ERR 0072: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    if( status == IB_REMOTE_ERROR )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_get_node_rec: "\r
+               "Remote error = %s\n",\r
+               ib_get_mad_status_str( osm_madw_get_mad_ptr\r
+                                      ( p_context->result.p_result_madw ) ) );\r
+    }\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ * Get a node record by node LID\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_get_node_rec_by_lid( IN osmtest_t * const p_osmt,\r
+                             IN ib_net16_t const  lid,\r
+                             IN OUT osmtest_req_context_t * const p_context )\r
+{\r
+  ib_api_status_t status = IB_SUCCESS;\r
+  osmv_user_query_t user;\r
+  osmv_query_req_t req;\r
+  ib_node_record_t record;\r
+  ib_mad_t *p_mad;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_get_node_rec_by_lid );\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_get_node_rec_by_lid: "\r
+             "Getting node record for LID 0x%02X\n",\r
+             cl_ntoh16( lid ) );\r
+  }\r
+\r
+  /*\r
+   * Do a blocking query for this record in the subnet.\r
+   * The result is returned in the result field of the caller's\r
+   * context structure.\r
+   *\r
+   * The query structures are locals.\r
+   */\r
+  memset( &req, 0, sizeof( req ) );\r
+  memset( &user, 0, sizeof( user ) );\r
+  memset( &record, 0, sizeof( record ) );\r
+\r
+  record.lid = lid;\r
+\r
+  p_context->p_osmt = p_osmt;\r
+  user.comp_mask = IB_NR_COMPMASK_LID;\r
+  user.attr_id = IB_MAD_ATTR_NODE_RECORD;\r
+  user.attr_offset = cl_ntoh16( ( uint16_t ) ( sizeof( record ) >> 3 ) );\r
+  user.p_attr = &record;\r
+\r
+  req.query_type = OSMV_QUERY_USER_DEFINED;\r
+  req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+  req.retry_cnt = p_osmt->opt.retry_count;\r
+  req.flags = OSM_SA_FLAGS_SYNC;\r
+  req.query_context = p_context;\r
+  req.pfn_query_cb = osmtest_query_res_cb;\r
+  req.p_query_input = &user;\r
+  req.sm_key = 0;\r
+\r
+  status = osmv_query_sa( p_osmt->h_bind, &req );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_node_rec_by_lid: ERR 0073: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  status = p_context->result.status;\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_node_rec_by_lid: ERR 0074: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    if( status == IB_REMOTE_ERROR )\r
+    {\r
+      p_mad = osm_madw_get_mad_ptr( p_context->result.p_result_madw );\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_get_node_rec_by_lid: "\r
+               "Remote error = %s\n",\r
+               ib_get_mad_status_str( p_mad ));\r
+\r
+      status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK );\r
+    }\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_get_path_rec_by_guid_pair( IN osmtest_t * const p_osmt,\r
+                                   IN ib_net64_t sguid,\r
+                                   IN ib_net64_t dguid,\r
+                                   IN osmtest_req_context_t *p_context)\r
+{\r
+  cl_status_t status = IB_SUCCESS;\r
+  osmv_query_req_t req;\r
+  osmv_guid_pair_t guid_pair;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log,  osmtest_get_path_rec_by_guid_pair);\r
+\r
+  memset( &req, 0, sizeof( req ) );\r
+  memset( p_context, 0, sizeof( *p_context ) );\r
+\r
+  p_context->p_osmt = p_osmt;\r
+  req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+  req.retry_cnt = p_osmt->opt.retry_count;\r
+  req.flags = OSM_SA_FLAGS_SYNC;\r
+  req.query_context = p_context;\r
+  req.pfn_query_cb = osmtest_query_res_cb;\r
+\r
+  req.query_type = OSMV_QUERY_PATH_REC_BY_PORT_GUIDS;\r
+\r
+  guid_pair.dest_guid = dguid;\r
+  guid_pair.src_guid = sguid;\r
+\r
+  req.p_query_input = &guid_pair;\r
+  req.sm_key = 0;\r
+\r
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+           "osmtest_get_path_rec_by_guid_pair: "\r
+           "Query for path from 0x%" PRIx64 " to 0x%" PRIx64"\n",\r
+           sguid, dguid );\r
+\r
+  status = osmv_query_sa( p_osmt->h_bind, &req );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_path_rec_by_guid_pair: ERR 0063: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  status = (*p_context).result.status;\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_path_rec_by_guid_pair: ERR 0066: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+\r
+    if( status == IB_REMOTE_ERROR )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_get_path_rec_by_guid_pair: "\r
+               "Remote error = %s\n",\r
+               ib_get_mad_status_str( osm_madw_get_mad_ptr\r
+                                      ( (*p_context).result.p_result_madw ) ) );\r
+    }\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_get_path_rec_by_gid_pair( IN osmtest_t * const p_osmt,\r
+                                  IN ib_gid_t sgid,\r
+                                  IN ib_gid_t dgid,\r
+                                  IN osmtest_req_context_t *p_context)\r
+{\r
+  cl_status_t status = IB_SUCCESS;\r
+  osmv_query_req_t req;\r
+  osmv_gid_pair_t gid_pair;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log,  osmtest_get_path_rec_by_gid_pair);\r
+\r
+  memset( &req, 0, sizeof( req ) );\r
+  memset( p_context, 0, sizeof( *p_context ) );\r
+\r
+  p_context->p_osmt = p_osmt;\r
+  req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+  req.retry_cnt = p_osmt->opt.retry_count;\r
+  req.flags = OSM_SA_FLAGS_SYNC;\r
+  req.query_context = p_context;\r
+  req.pfn_query_cb = osmtest_query_res_cb;\r
+\r
+  req.query_type = OSMV_QUERY_PATH_REC_BY_GIDS;\r
+\r
+  gid_pair.dest_gid = dgid;\r
+  gid_pair.src_gid = sgid;\r
+\r
+  req.p_query_input = &gid_pair;\r
+  req.sm_key = 0;\r
+\r
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+           "osmtest_get_path_rec_by_gid_pair: "\r
+           "Query for path from 0x%016" PRIx64 " 0x%016" PRIx64 " to 0x%016" PRIx64 " 0x%016" PRIx64"\n",\r
+           sgid.unicast.prefix, sgid.unicast.interface_id,\r
+           dgid.unicast.prefix, dgid.unicast.interface_id );\r
+\r
+  status = osmv_query_sa( p_osmt->h_bind, &req );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_path_rec_by_gid_pair: ERR 006A: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  status = (*p_context).result.status;\r
+\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_path_rec_by_gid_pair: ERR 006B: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+\r
+    if( status == IB_REMOTE_ERROR )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_get_path_rec_by_gid_pair: "\r
+               "Remote error = %s\n",\r
+               ib_get_mad_status_str( osm_madw_get_mad_ptr\r
+                                      ( (*p_context).result.p_result_madw ) ) );\r
+    }\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_get_multipath_rec( IN osmtest_t * const p_osmt,\r
+                           IN osmv_multipath_req_t *p_request,\r
+                           IN osmtest_req_context_t *p_context)\r
+{\r
+  cl_status_t status = IB_SUCCESS;\r
+  osmv_query_req_t req;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log,  osmtest_get_multipath_rec );\r
+\r
+  /*\r
+   * Do a blocking query for this record in the subnet.\r
+   * The result is returned in the result field of the caller's\r
+   * context structure.\r
+   *\r
+   * The query structures are locals.\r
+   */\r
+  memset( &req, 0, sizeof( req ) );\r
+\r
+  p_context->p_osmt = p_osmt;\r
+  req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+  req.retry_cnt = p_osmt->opt.retry_count;\r
+  req.flags = OSM_SA_FLAGS_SYNC;\r
+  req.query_context = p_context;\r
+  req.pfn_query_cb = osmtest_query_res_cb;\r
+\r
+  req.query_type = OSMV_QUERY_MULTIPATH_REC;\r
+\r
+  req.p_query_input = p_request;\r
+  req.sm_key = 0;\r
+\r
+  status = osmv_query_sa( p_osmt->h_bind, &req );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_multipath_rec: ERR 0068: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  status = p_context->result.status;\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_multipath_rec: ERR 0069: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+\r
+    if( status == IB_REMOTE_ERROR )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_get_multipath_rec: "\r
+               "Remote error = %s\n",\r
+               ib_get_mad_status_str( osm_madw_get_mad_ptr\r
+                                      ( p_context->result.p_result_madw ) ) );\r
+    }\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+#endif\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_get_port_rec( IN osmtest_t * const p_osmt,\r
+                      IN ib_net16_t const lid,\r
+                      IN OUT osmtest_req_context_t * const p_context )\r
+{\r
+  ib_api_status_t status = IB_SUCCESS;\r
+  osmv_user_query_t user;\r
+  osmv_query_req_t req;\r
+  ib_portinfo_record_t record;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_get_port_rec );\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+             "osmtest_get_port_rec: "\r
+             "Getting PortInfoRecord for port with LID 0x%X\n",\r
+             cl_ntoh16( lid ) );\r
+  }\r
+\r
+  /*\r
+   * Do a blocking query for this record in the subnet.\r
+   * The result is returned in the result field of the caller's\r
+   * context structure.\r
+   *\r
+   * The query structures are locals.\r
+   */\r
+  memset( &req, 0, sizeof( req ) );\r
+  memset( &user, 0, sizeof( user ) );\r
+  memset( &record, 0, sizeof( record ) );\r
+\r
+  record.lid = lid;\r
+\r
+  p_context->p_osmt = p_osmt;\r
+  user.comp_mask = IB_PIR_COMPMASK_LID;\r
+  user.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;\r
+  user.attr_offset = cl_ntoh16( ( uint16_t ) ( sizeof( record ) >> 3 ) );\r
+  user.p_attr = &record;\r
+\r
+  req.query_type = OSMV_QUERY_USER_DEFINED;\r
+  req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+  req.retry_cnt = p_osmt->opt.retry_count;\r
+  req.flags = OSM_SA_FLAGS_SYNC;\r
+  req.query_context = p_context;\r
+  req.pfn_query_cb = osmtest_query_res_cb;\r
+  req.p_query_input = &user;\r
+  req.sm_key = 0;\r
+\r
+  status = osmv_query_sa( p_osmt->h_bind, &req );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_port_rec: ERR 0075: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  status = p_context->result.status;\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_port_rec: ERR 0076: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+\r
+    if( status == IB_REMOTE_ERROR )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_get_port_rec: "\r
+               "Remote error = %s\n",\r
+               ib_get_mad_status_str( osm_madw_get_mad_ptr\r
+                                      ( p_context->result.p_result_madw ) ) );\r
+    }\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_get_port_rec_by_num( IN osmtest_t * const p_osmt,\r
+                             IN ib_net16_t const lid,\r
+                             IN uint8_t const port_num,\r
+                             IN OUT osmtest_req_context_t * const p_context )\r
+{\r
+  ib_api_status_t status = IB_SUCCESS;\r
+  osmv_user_query_t user;\r
+  osmv_query_req_t req;\r
+  ib_portinfo_record_t record;\r
+  ib_mad_t *p_mad;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_get_port_rec_by_num );\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+             "osmtest_get_port_rec_by_num: "\r
+             "Getting PortInfoRecord for port with LID 0x%X Num:0x%X\n",\r
+             cl_ntoh16( lid ),\r
+             port_num);\r
+  }\r
+\r
+  /*\r
+   * Do a blocking query for this record in the subnet.\r
+   * The result is returned in the result field of the caller's\r
+   * context structure.\r
+   *\r
+   * The query structures are locals.\r
+   */\r
+  memset( &req, 0, sizeof( req ) );\r
+  memset( &user, 0, sizeof( user ) );\r
+  memset( &record, 0, sizeof( record ) );\r
+\r
+  record.lid = lid;\r
+  record.port_num = port_num;\r
+  user.p_attr = &record;\r
+\r
+  p_context->p_osmt = p_osmt;\r
+\r
+  req.query_type = OSMV_QUERY_PORT_REC_BY_LID_AND_NUM;\r
+  req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+  req.retry_cnt = p_osmt->opt.retry_count;\r
+  req.flags = OSM_SA_FLAGS_SYNC;\r
+  req.query_context = p_context;\r
+  req.pfn_query_cb = osmtest_query_res_cb;\r
+  req.p_query_input = &user;\r
+  req.sm_key = 0;\r
+\r
+  status = osmv_query_sa( p_osmt->h_bind, &req );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_port_rec_by_num: ERR 0077: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  status = p_context->result.status;\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_port_rec_by_num: ERR 0078: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+\r
+    if( status == IB_REMOTE_ERROR )\r
+    {\r
+      p_mad = osm_madw_get_mad_ptr( p_context->result.p_result_madw );\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_get_port_rec_by_num: "\r
+               "Remote error = %s\n",\r
+               ib_get_mad_status_str( p_mad ));\r
+      status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK );\r
+    }\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_stress_port_recs_large( IN osmtest_t * const p_osmt,\r
+                                OUT uint32_t * const p_num_recs,\r
+                                OUT uint32_t * const p_num_queries )\r
+{\r
+  osmtest_req_context_t context;\r
+  ib_portinfo_record_t *p_rec;\r
+  uint32_t i;\r
+  cl_status_t status;\r
+  uint32_t num_recs = 0;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_port_recs_large );\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+  /*\r
+   * Do a blocking query for all PortInfoRecords in the subnet.\r
+   */\r
+  status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_PORTINFO_RECORD,\r
+                                 sizeof( *p_rec ), &context );\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_stress_port_recs_large: ERR 0006: "\r
+             "osmtest_get_all_recs failed (%s)\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  /*\r
+   * Populate the database with the received records.\r
+   */\r
+  num_recs = context.result.result_cnt;\r
+  *p_num_recs += num_recs;\r
+  ++*p_num_queries;\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_stress_port_recs_large: "\r
+             "Received %u records\n", num_recs );\r
+\r
+    for( i = 0; i < num_recs; i++ )\r
+    {\r
+      p_rec = osmv_get_query_portinfo_rec( context.result.p_result_madw, i );\r
+      osm_dump_portinfo_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );\r
+    }\r
+  }\r
+\r
+ Exit:\r
+  /*\r
+   * Return the IB query MAD to the pool as necessary.\r
+   */\r
+  if( context.result.p_result_madw != NULL )\r
+  {\r
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+    context.result.p_result_madw = NULL;\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_stress_node_recs_large( IN osmtest_t * const p_osmt,\r
+                                OUT uint32_t * const p_num_recs,\r
+                                OUT uint32_t * const p_num_queries )\r
+{\r
+  osmtest_req_context_t context;\r
+  ib_node_record_t *p_rec;\r
+  uint32_t i;\r
+  cl_status_t status;\r
+  uint32_t num_recs = 0;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_node_recs_large );\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+\r
+  /*\r
+   * Do a blocking query for all NodeRecords in the subnet.\r
+   */\r
+  status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_NODE_RECORD,\r
+                                 sizeof( *p_rec ), &context );\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_stress_node_recs_large: ERR 0007: "\r
+             "osmtest_get_all_recs failed (%s)\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  /*\r
+   * Populate the database with the received records.\r
+   */\r
+  num_recs = context.result.result_cnt;\r
+  *p_num_recs += num_recs;\r
+  ++*p_num_queries;\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_stress_node_recs_large: "\r
+             "Received %u records\n", num_recs );\r
+\r
+    for( i = 0; i < num_recs; i++ )\r
+    {\r
+      p_rec = osmv_get_query_node_rec( context.result.p_result_madw, i );\r
+      osm_dump_node_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );\r
+    }\r
+  }\r
+\r
+ Exit:\r
+  /*\r
+   * Return the IB query MAD to the pool as necessary.\r
+   */\r
+  if( context.result.p_result_madw != NULL )\r
+  {\r
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+    context.result.p_result_madw = NULL;\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_stress_path_recs_large( IN osmtest_t * const p_osmt,\r
+                                OUT uint32_t * const p_num_recs,\r
+                                OUT uint32_t * const p_num_queries )\r
+{\r
+  osmtest_req_context_t context;\r
+  ib_path_rec_t *p_rec;\r
+  uint32_t i;\r
+  cl_status_t status;\r
+  uint32_t num_recs = 0;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_path_recs_large );\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+\r
+  /*\r
+   * Do a blocking query for all PathRecords in the subnet.\r
+   */\r
+  status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_PATH_RECORD,\r
+                                 sizeof( *p_rec ), &context );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_stress_path_recs_large: ERR 0008: "\r
+             "osmtest_get_all_recs failed (%s)\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  /*\r
+   * Populate the database with the received records.\r
+   */\r
+  num_recs = context.result.result_cnt;\r
+  *p_num_recs += num_recs;\r
+  ++*p_num_queries;\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_stress_path_recs_large: "\r
+             "Received %u records\n", num_recs );\r
+\r
+    for( i = 0; i < num_recs; i++ )\r
+    {\r
+      p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i );\r
+      osm_dump_path_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );\r
+    }\r
+  }\r
+\r
+ Exit:\r
+  /*\r
+   * Return the IB query MAD to the pool as necessary.\r
+   */\r
+  if( context.result.p_result_madw != NULL )\r
+  {\r
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+    context.result.p_result_madw = NULL;\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_stress_path_recs_by_guid ( IN osmtest_t * const p_osmt,\r
+                                   OUT uint32_t * const p_num_recs,\r
+                                   OUT uint32_t * const p_num_queries )\r
+{\r
+  osmtest_req_context_t context;\r
+  ib_path_rec_t *p_rec;\r
+  uint32_t i;\r
+  cl_status_t status = IB_SUCCESS;\r
+  uint32_t num_recs = 0;\r
+  node_t *p_src_node, *p_dst_node;\r
+  cl_qmap_t *p_tbl;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_path_recs_by_guid );\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+\r
+  context.p_osmt = p_osmt;\r
+\r
+  p_tbl = &p_osmt->exp_subn.node_guid_tbl;\r
+\r
+  p_src_node = ( node_t * ) cl_qmap_head( p_tbl );\r
+\r
+  /*\r
+   * Go over all nodes that exist in the subnet\r
+   * for each pair that are not switch nodes get the path record\r
+   */\r
+  while( p_src_node != ( node_t * ) cl_qmap_end( p_tbl ) )\r
+  {\r
+    p_dst_node = ( node_t * ) cl_qmap_head( p_tbl );\r
+\r
+    while( p_dst_node != ( node_t * ) cl_qmap_end( p_tbl ) )\r
+    {\r
+      /*\r
+       * Do a blocking query for CA to CA Path Record\r
+       */\r
+      osm_log(&p_osmt->log, OSM_LOG_VERBOSE,\r
+              "osmtest_stress_path_recs_by_guid:"\r
+              "Source : guid = 0x%" PRIx64 " type = %d"\r
+              "Target : guid = 0x%" PRIx64 " type = %d\n",\r
+              cl_ntoh64(p_src_node->rec.node_info.port_guid),\r
+              p_src_node->rec.node_info.node_type,\r
+              cl_ntoh64(p_dst_node->rec.node_info.port_guid),\r
+              p_dst_node->rec.node_info.node_type);\r
+\r
+      if (p_src_node->rec.node_info.node_type == IB_NODE_TYPE_CA &&\r
+          p_dst_node->rec.node_info.node_type == IB_NODE_TYPE_CA)\r
+      {\r
+        status = osmtest_get_path_rec_by_guid_pair(p_osmt,\r
+                                                   p_src_node->rec.node_info.port_guid,\r
+                                                   p_dst_node->rec.node_info.port_guid,\r
+                                                   &context);\r
+\r
+        /* In a case of TIMEOUT you still can try sending but cant count, maybe its a temporary issue */\r
+        if( status != IB_SUCCESS )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                   "osmtest_stress_path_recs_by_guid: ERR 0009: "\r
+                   "osmtest_get_path_rec_by_guid_pair failed (%s)\n",\r
+                   ib_get_err_str( status ) );\r
+          if (status != IB_TIMEOUT)\r
+            goto Exit;\r
+        }\r
+        else\r
+        {\r
+          /* we might have received several records */\r
+          num_recs = context.result.result_cnt;\r
+          /*\r
+           * Populate the database with the received records.\r
+           */\r
+          *p_num_recs += num_recs;\r
+          ++*p_num_queries;\r
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+            osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+                     "osmtest_stress_path_recs_by_guid: "\r
+                     "Received %u records\n", num_recs );\r
+          /* Dont waste time if not VERBOSE and above */\r
+          if (p_osmt->log.level & OSM_LOG_VERBOSE)\r
+          {\r
+            for (i = 0; i < num_recs; i++)\r
+            {\r
+              p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i);\r
+              osm_dump_path_record(&p_osmt->log,p_rec,OSM_LOG_VERBOSE);\r
+            }\r
+          }\r
+        }\r
+        if( context.result.p_result_madw != NULL )\r
+        {\r
+          osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+          context.result.p_result_madw = NULL;\r
+        }\r
+      }\r
+      /* next one please */\r
+      p_dst_node = ( node_t * ) cl_qmap_next( &p_dst_node->map_item );\r
+    }\r
+\r
+    p_src_node = ( node_t * ) cl_qmap_next( &p_src_node->map_item );\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_stress_port_recs_small( IN osmtest_t * const p_osmt,\r
+                                OUT uint32_t * const p_num_recs,\r
+                                OUT uint32_t * const p_num_queries )\r
+{\r
+  osmtest_req_context_t context;\r
+  ib_portinfo_record_t *p_rec;\r
+  uint32_t i;\r
+  cl_status_t status;\r
+  uint32_t num_recs = 0;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_port_recs_small );\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+\r
+  /*\r
+   * Do a blocking query for our own PortInfoRecord in the subnet.\r
+   */\r
+  status = osmtest_get_port_rec( p_osmt,\r
+                                 cl_ntoh16(p_osmt->local_port.lid),\r
+                                 &context );\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_stress_port_recs_small: ERR 0010: "\r
+             "osmtest_get_port_rec failed (%s)\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  /*\r
+   * Populate the database with the received records.\r
+   */\r
+  num_recs = context.result.result_cnt;\r
+  *p_num_recs += num_recs;\r
+  ++*p_num_queries;\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_stress_port_recs_small: "\r
+             "Received %u records\n", num_recs );\r
+\r
+    for( i = 0; i < num_recs; i++ )\r
+    {\r
+      p_rec = osmv_get_query_portinfo_rec( context.result.p_result_madw, i );\r
+      osm_dump_portinfo_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );\r
+    }\r
+  }\r
+\r
+ Exit:\r
+  /*\r
+   * Return the IB query MAD to the pool as necessary.\r
+   */\r
+  if( context.result.p_result_madw != NULL )\r
+  {\r
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+    context.result.p_result_madw = NULL;\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_get_local_port_lmc( IN osmtest_t * const p_osmt,\r
+                            IN ib_net16_t  lid,\r
+                            OUT uint8_t *  const p_lmc )\r
+{\r
+  osmtest_req_context_t context;\r
+  ib_portinfo_record_t *p_rec;\r
+  uint32_t i;\r
+  cl_status_t status;\r
+  uint32_t num_recs = 0;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_get_local_port_lmc );\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+\r
+  /*\r
+   * Do a blocking query for our own PortInfoRecord in the subnet.\r
+   */\r
+  status = osmtest_get_port_rec( p_osmt,\r
+                                 cl_ntoh16( lid ),\r
+                                 &context );\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_local_port_lmc: ERR 001A: "\r
+             "osmtest_get_port_rec failed (%s)\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  num_recs = context.result.result_cnt;\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_get_local_port_lmc: "\r
+             "Received %u records\n", num_recs );\r
+  }\r
+\r
+  for( i = 0; i < num_recs; i++ )\r
+  {\r
+    p_rec = osmv_get_query_portinfo_rec( context.result.p_result_madw, i );\r
+    osm_dump_portinfo_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );\r
+    if ( p_lmc)\r
+    {\r
+      *p_lmc = ib_port_info_get_lmc( &p_rec->port_info );\r
+      osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+               "osmtest_get_local_port_lmc: "\r
+               "LMC %d\n", *p_lmc );\r
+    }\r
+  }\r
+\r
+ Exit:\r
+  /*\r
+   * Return the IB query MAD to the pool as necessary.\r
+   */\r
+  if( context.result.p_result_madw != NULL )\r
+  {\r
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+    context.result.p_result_madw = NULL;\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ * Use a wrong SM_Key in a simple port query and report success if\r
+ * failed.\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_wrong_sm_key_ignored( IN osmtest_t * const p_osmt)\r
+{\r
+  ib_api_status_t status = IB_SUCCESS;\r
+  osmv_user_query_t user;\r
+  osmv_query_req_t req;\r
+  ib_portinfo_record_t record;\r
+  osmtest_req_context_t context;\r
+  osmtest_req_context_t *p_context = &context;\r
+  uint8_t port_num = 1;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_wrong_sm_key_ignored );\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_INFO ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_INFO,\r
+             "osmtest_wrong_sm_key_ignored: "\r
+             "Trying PortInfoRecord for port with LID 0x%X Num:0x%X\n",\r
+             p_osmt->local_port.sm_lid, \r
+             port_num );\r
+  }\r
+\r
+  /*\r
+   * Do a blocking query for this record in the subnet.\r
+   * The result is returned in the result field of the caller's\r
+   * context structure.\r
+   *\r
+   * The query structures are locals.\r
+   */\r
+  memset( &req, 0, sizeof( req ) );\r
+  memset( &user, 0, sizeof( user ) );\r
+  memset( &record, 0, sizeof( record ) );\r
+\r
+  record.lid = p_osmt->local_port.sm_lid;\r
+  record.port_num = port_num;\r
+  user.p_attr = &record;\r
+\r
+  p_context->p_osmt = p_osmt;\r
+\r
+  req.query_type = OSMV_QUERY_PORT_REC_BY_LID_AND_NUM;\r
+  req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+  req.retry_cnt = p_osmt->opt.retry_count;\r
+  req.flags = OSM_SA_FLAGS_SYNC;\r
+  req.query_context = p_context;\r
+  req.pfn_query_cb = osmtest_query_res_cb;\r
+  req.p_query_input = &user;\r
+  req.sm_key = 9999;\r
+  context.result.p_result_madw = NULL;\r
+\r
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+           "osmtest_wrong_sm_key_ignored: " EXPECTING_ERRORS_START "\n" );\r
+  status = osmv_query_sa( p_osmt->h_bind, &req );\r
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+           "osmtest_wrong_sm_key_ignored: " EXPECTING_ERRORS_END "\n" );\r
+\r
+  /* since we use a wrong sm_key we should get a timeout */\r
+  if( status != IB_TIMEOUT )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_wrong_sm_key_ignored: ERR 0011: "\r
+             "Did not get a timeout but got (%s)\n", ib_get_err_str( status ) );\r
+    if ( status == IB_SUCCESS )\r
+    {\r
+      /* assign some error value to status, since IB_SUCCESS is a bad rc */\r
+      status = IB_ERROR;\r
+    }\r
+    goto Exit;\r
+  }\r
+  else\r
+  {\r
+    status = IB_SUCCESS;\r
+  }\r
+\r
+ Exit:\r
+  if( context.result.p_result_madw != NULL )\r
+  {\r
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+    context.result.p_result_madw = NULL;\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_write_port_info( IN osmtest_t * const p_osmt,\r
+                         IN FILE * fh,\r
+                         IN const ib_portinfo_record_t * const p_rec )\r
+{\r
+  int result;\r
+  cl_status_t status = IB_SUCCESS;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_port_info );\r
+\r
+  result = fprintf( fh,\r
+                    "DEFINE_PORT\n"\r
+                    "lid                     0x%X\n"\r
+                    "port_num                0x%X\n"\r
+                    "m_key                   0x%016" PRIx64 "\n"\r
+                    "subnet_prefix           0x%016" PRIx64 "\n"\r
+                    "base_lid                0x%X\n"\r
+                    "master_sm_base_lid      0x%X\n"\r
+                    "capability_mask         0x%X\n"\r
+                    "diag_code               0x%X\n"\r
+                    "m_key_lease_period      0x%X\n"\r
+                    "local_port_num          0x%X\n"\r
+                    "link_width_enabled      0x%X\n"\r
+                    "link_width_supported    0x%X\n"\r
+                    "link_width_active       0x%X\n"\r
+                    "link_speed_supported    0x%X\n"\r
+                    "port_state              %s\n"\r
+                    "state_info2             0x%X\n"\r
+                    "mpb                     0x%X\n"\r
+                    "lmc                     0x%X\n"\r
+                    "link_speed              0x%X\n"\r
+                    "mtu_smsl                0x%X\n"\r
+                    "vl_cap                  0x%X\n"\r
+                    "vl_high_limit           0x%X\n"\r
+                    "vl_arb_high_cap         0x%X\n"\r
+                    "vl_arb_low_cap          0x%X\n"\r
+                    "mtu_cap                 0x%X\n"\r
+                    "vl_stall_life           0x%X\n"\r
+                    "vl_enforce              0x%X\n"\r
+                    "m_key_violations        0x%X\n"\r
+                    "p_key_violations        0x%X\n"\r
+                    "q_key_violations        0x%X\n"\r
+                    "guid_cap                0x%X\n"\r
+                    "subnet_timeout          0x%X\n"\r
+                    "resp_time_value         0x%X\n"\r
+                    "error_threshold         0x%X\n"\r
+                    "END\n\n",\r
+                    cl_ntoh16( p_rec->lid ),\r
+                    p_rec->port_num,\r
+                    cl_ntoh64( p_rec->port_info.m_key ),\r
+                    cl_ntoh64( p_rec->port_info.subnet_prefix ),\r
+                    cl_ntoh16( p_rec->port_info.base_lid ),\r
+                    cl_ntoh16( p_rec->port_info.master_sm_base_lid ),\r
+                    cl_ntoh32( p_rec->port_info.capability_mask ),\r
+                    cl_ntoh16( p_rec->port_info.diag_code ),\r
+                    cl_ntoh16( p_rec->port_info.m_key_lease_period ),\r
+                    p_rec->port_info.local_port_num,\r
+                    p_rec->port_info.link_width_enabled,\r
+                    p_rec->port_info.link_width_supported,\r
+                    p_rec->port_info.link_width_active,\r
+                    ib_port_info_get_link_speed_sup( &p_rec->port_info ),\r
+                    ib_get_port_state_str( ib_port_info_get_port_state\r
+                                           ( &p_rec->port_info ) ),\r
+                    p_rec->port_info.state_info2,\r
+                    ib_port_info_get_mpb( &p_rec->port_info ),\r
+                    ib_port_info_get_lmc( &p_rec->port_info ),\r
+                    p_rec->port_info.link_speed, p_rec->port_info.mtu_smsl,\r
+                    p_rec->port_info.vl_cap, p_rec->port_info.vl_high_limit,\r
+                    p_rec->port_info.vl_arb_high_cap,\r
+                    p_rec->port_info.vl_arb_low_cap,\r
+                    p_rec->port_info.mtu_cap,\r
+                    p_rec->port_info.vl_stall_life,\r
+                    p_rec->port_info.vl_enforce,\r
+                    cl_ntoh16( p_rec->port_info.m_key_violations ),\r
+                    cl_ntoh16( p_rec->port_info.p_key_violations ),\r
+                    cl_ntoh16( p_rec->port_info.q_key_violations ),\r
+                    p_rec->port_info.guid_cap,\r
+                    ib_port_info_get_timeout(&p_rec->port_info),\r
+                    p_rec->port_info.resp_time_value,\r
+                    p_rec->port_info.error_threshold );\r
+\r
+  if( result < 0 )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_write_port_info: ERR 0161: " "Write failed\n" );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_write_path_info( IN osmtest_t * const p_osmt,\r
+                         IN FILE * fh,\r
+                         IN const ib_path_rec_t * const p_rec )\r
+{\r
+  int result;\r
+  cl_status_t status = IB_SUCCESS;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_path_info );\r
+\r
+  result = fprintf( fh,\r
+                    "DEFINE_PATH\n"\r
+                    "dgid                    0x%016" PRIx64 " 0x%016" PRIx64\r
+                    "\nsgid                    0x%016" PRIx64 " 0x%016" PRIx64\r
+                    "\ndlid                    0x%X\n"\r
+                    "slid                    0x%X\n"\r
+                    "# hop_flow_raw          0x%X\n"\r
+                    "# tclass                0x%X\n"\r
+                    "# num_path              0x%X\n"\r
+                    "pkey                    0x%X\n"\r
+                    "# sl                    0x%X\n"\r
+                    "# mtu                   0x%X\n"\r
+                    "# rate                  0x%X\n"\r
+                    "# pkt_life              0x%X\n"\r
+                    "# preference            0x%X\n" "END\n\n",\r
+                    cl_ntoh64( p_rec->dgid.unicast.prefix ),\r
+                    cl_ntoh64( p_rec->dgid.unicast.interface_id ),\r
+                    cl_ntoh64( p_rec->sgid.unicast.prefix ),\r
+                    cl_ntoh64( p_rec->sgid.unicast.interface_id ),\r
+                    cl_ntoh16( p_rec->dlid ), cl_ntoh16( p_rec->slid ),\r
+                    cl_ntoh32( p_rec->hop_flow_raw ), p_rec->tclass,\r
+                    p_rec->num_path, cl_ntoh16( p_rec->pkey ),\r
+                    p_rec->qos_class_sl,\r
+                    p_rec->mtu, p_rec->rate, p_rec->pkt_life,\r
+                    p_rec->preference );\r
+\r
+  if( result < 0 )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_write_path_info: ERR 0162: " "Write failed\n" );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_write_node_info( IN osmtest_t * const p_osmt,\r
+                         IN FILE * fh,\r
+                         IN const ib_node_record_t * const p_rec )\r
+{\r
+  int result;\r
+  cl_status_t status = IB_SUCCESS;\r
+  char desc[IB_NODE_DESCRIPTION_SIZE + 1];\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_node_info );\r
+\r
+  memcpy(desc, p_rec->node_desc.description, IB_NODE_DESCRIPTION_SIZE);\r
+  desc[IB_NODE_DESCRIPTION_SIZE] = '\0';\r
+\r
+  result = fprintf( fh,\r
+                    "DEFINE_NODE\n"\r
+                    "lid                     0x%X\n"\r
+                    "base_version            0x%X\n"\r
+                    "class_version           0x%X\n"\r
+                    "node_type               0x%X # (%s)\n"\r
+                    "num_ports               0x%X\n"\r
+                    "sys_guid                0x%016" PRIx64 "\n"\r
+                    "node_guid               0x%016" PRIx64 "\n"\r
+                    "port_guid               0x%016" PRIx64 "\n"\r
+                    "partition_cap           0x%X\n"\r
+                    "device_id               0x%X\n"\r
+                    "revision                0x%X\n"\r
+                    "# port_num              0x%X\n"\r
+                    "# vendor_id             0x%X\n"\r
+                    "# node_desc             %s\n"\r
+                    "END\n\n",\r
+                    cl_ntoh16( p_rec->lid ),\r
+                    p_rec->node_info.base_version,\r
+                    p_rec->node_info.class_version,\r
+                    p_rec->node_info.node_type,\r
+                    ib_get_node_type_str( p_rec->node_info.node_type ),\r
+                    p_rec->node_info.num_ports,\r
+                    cl_ntoh64( p_rec->node_info.sys_guid ),\r
+                    cl_ntoh64( p_rec->node_info.node_guid ),\r
+                    cl_ntoh64( p_rec->node_info.port_guid ),\r
+                    cl_ntoh16( p_rec->node_info.partition_cap ),\r
+                    cl_ntoh16( p_rec->node_info.device_id ),\r
+                    cl_ntoh32( p_rec->node_info.revision ),\r
+                    ib_node_info_get_local_port_num( &p_rec->node_info ),\r
+                    cl_ntoh32( ib_node_info_get_vendor_id\r
+                               ( &p_rec->node_info ) ),\r
+                    desc );\r
+\r
+  if( result < 0 )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_write_node_info: ERR 0163: " "Write failed\n" );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_write_link( IN osmtest_t * const p_osmt,\r
+                    IN FILE * fh,\r
+                    IN const ib_link_record_t * const p_rec )\r
+{\r
+  int result;\r
+  cl_status_t status = IB_SUCCESS;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_link );\r
+\r
+  result = fprintf( fh,\r
+                    "DEFINE_LINK\n"\r
+                    "from_lid                0x%X\n"\r
+                    "from_port_num           0x%X\n"\r
+                    "to_port_num             0x%X\n"\r
+                    "to_lid                  0x%X\n"\r
+                    "END\n\n",\r
+                    cl_ntoh16( p_rec->from_lid ),\r
+                    p_rec->from_port_num,\r
+                    p_rec->to_port_num, cl_ntoh16( p_rec->to_lid ) );\r
+\r
+  if( result < 0 )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_write_link: ERR 0164: " "Write failed\n" );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_write_all_link_recs( IN osmtest_t * const p_osmt,\r
+                             IN FILE * fh )\r
+{\r
+  osmtest_req_context_t context;\r
+  const ib_link_record_t *p_rec;\r
+  uint32_t i;\r
+  cl_status_t status;\r
+  size_t num_recs;\r
+  int result;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_link_recs );\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+\r
+  /*\r
+   * Do a blocking query for all NodeRecords in the subnet.\r
+   */\r
+  status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_LINK_RECORD,\r
+                                 sizeof( *p_rec ), &context );\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_write_all_link_recs: ERR 0165: "\r
+             "osmtest_get_all_recs failed (%s)\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  /*\r
+   * Write the received records out to the file.\r
+   */\r
+  num_recs = context.result.result_cnt;\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_write_all_link_recs: "\r
+             "Received %zu records\n", num_recs );\r
+  }\r
+\r
+  result = fprintf( fh, "#\n" "# Link Records\n" "#\n" );\r
+  if( result < 0 )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_write_all_link_recs: ERR 0166: "\r
+             "Write failed\n" );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  for( i = 0; i < num_recs; i++ )\r
+  {\r
+    p_rec = ( ib_link_record_t * ) osmv_get_query_result( context.result.\r
+                                                          p_result_madw, i );\r
+\r
+    osmtest_write_link( p_osmt, fh, p_rec );\r
+  }\r
+\r
+ Exit:\r
+  /*\r
+   * Return the IB query MAD to the pool as necessary.\r
+   */\r
+  if( context.result.p_result_madw != NULL )\r
+  {\r
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+    context.result.p_result_madw = NULL;\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_get_path_rec_by_lid_pair( IN osmtest_t * const p_osmt,\r
+                                  IN ib_net16_t slid,\r
+                                  IN ib_net16_t dlid,\r
+                                  IN osmtest_req_context_t *p_context )\r
+{\r
+  cl_status_t status = IB_SUCCESS;\r
+  osmv_query_req_t req;\r
+  osmv_lid_pair_t lid_pair;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log,  osmtest_get_path_rec_by_lid_pair );\r
+\r
+  memset( &req, 0, sizeof( req ) );\r
+  memset( p_context, 0, sizeof( *p_context ) );\r
+\r
+  p_context->p_osmt = p_osmt;\r
+  req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+  req.retry_cnt = p_osmt->opt.retry_count;\r
+  req.flags = OSM_SA_FLAGS_SYNC;\r
+  req.query_context = p_context;\r
+  req.pfn_query_cb = osmtest_query_res_cb;\r
+\r
+  req.query_type = OSMV_QUERY_PATH_REC_BY_LIDS;\r
+\r
+  lid_pair.dest_lid = dlid;\r
+  lid_pair.src_lid = slid;\r
+\r
+  req.p_query_input = &lid_pair;\r
+  req.sm_key = 0;\r
+\r
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+           "osmtest_get_path_rec_by_lid_pair: "\r
+           "Query for path from 0x%X to 0x%X\n",\r
+           slid,dlid );\r
+  status = osmv_query_sa( p_osmt->h_bind, &req );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_path_rec_by_lid_pair: ERR 0053: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  status = (*p_context).result.status;\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_path_rec_by_lid_pair: ERR 0067: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+\r
+    if( status == IB_REMOTE_ERROR )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_get_path_rec_by_lid_pair: "\r
+               "Remote error = %s\n",\r
+               ib_get_mad_status_str( osm_madw_get_mad_ptr\r
+                                      ( (*p_context).result.p_result_madw ) ) );\r
+    }\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+#ifdef VENDOR_RMPP_SUPPORT\r
+/**********************************************************************\r
+ * ASSUMES RMPP\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_write_all_node_recs( IN osmtest_t * const p_osmt,\r
+                             IN FILE * fh )\r
+{\r
+  osmtest_req_context_t context;\r
+  const ib_node_record_t *p_rec;\r
+  uint32_t i;\r
+  cl_status_t status;\r
+  size_t num_recs;\r
+  int result;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_node_recs );\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+\r
+  /*\r
+   * Do a blocking query for all NodeRecords in the subnet.\r
+   */\r
+  status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_NODE_RECORD,\r
+                                 sizeof( *p_rec ), &context );\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_write_all_node_recs: ERR 0022: "\r
+             "osmtest_get_all_recs failed (%s)\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  /*\r
+   * Write the received records out to the file.\r
+   */\r
+  num_recs = context.result.result_cnt;\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+              "osmtest_write_all_node_recs: "\r
+              "Received %zu records\n", num_recs );\r
+  }\r
+\r
+  result = fprintf( fh, "#\n" "# Node Records\n" "#\n" );\r
+  if( result < 0 )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_write_all_node_recs: ERR 0023: "\r
+             "Write failed\n" );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  for( i = 0; i < num_recs; i++ )\r
+  {\r
+    p_rec = osmv_get_query_node_rec( context.result.p_result_madw, i );\r
+    osmtest_write_node_info( p_osmt, fh, p_rec );\r
+  }\r
+\r
+ Exit:\r
+  /*\r
+   * Return the IB query MAD to the pool as necessary.\r
+   */\r
+  if( context.result.p_result_madw != NULL )\r
+  {\r
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+    context.result.p_result_madw = NULL;\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ * ASSUMES RMPP\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_write_all_port_recs( IN osmtest_t * const p_osmt,\r
+                             IN FILE * fh )\r
+{\r
+  osmtest_req_context_t context;\r
+  const ib_portinfo_record_t *p_rec;\r
+  uint32_t i;\r
+  cl_status_t status;\r
+  size_t num_recs;\r
+  int result;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_port_recs );\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+\r
+  /*\r
+   * Do a blocking query for all NodeRecords in the subnet.\r
+   */\r
+  status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_PORTINFO_RECORD,\r
+                                 sizeof( *p_rec ), &context );\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_write_all_port_recs: ERR 0167: "\r
+             "osmtest_get_all_recs failed (%s)\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  /*\r
+   * Write the received records out to the file.\r
+   */\r
+  num_recs = context.result.result_cnt;\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_write_all_port_recs: "\r
+             "Received %zu records\n", num_recs );\r
+  }\r
+\r
+  result = fprintf( fh, "#\n" "# PortInfo Records\n" "#\n" );\r
+  if( result < 0 )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_write_all_port_recs: ERR 0024: " "Write failed\n" );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  for( i = 0; i < num_recs; i++ )\r
+  {\r
+    p_rec = osmv_get_query_portinfo_rec( context.result.p_result_madw, i );\r
+    osmtest_write_port_info( p_osmt, fh, p_rec );\r
+  }\r
+\r
+ Exit:\r
+  /*\r
+   * Return the IB query MAD to the pool as necessary.\r
+   */\r
+  if( context.result.p_result_madw != NULL )\r
+  {\r
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+    context.result.p_result_madw = NULL;\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ * ASSUMES RMPP\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_write_all_path_recs(\r
+                            IN osmtest_t * const p_osmt,\r
+                            IN FILE * fh )\r
+{\r
+  osmtest_req_context_t context;\r
+  const ib_path_rec_t *p_rec;\r
+  uint32_t i;\r
+  cl_status_t status;\r
+  size_t num_recs;\r
+  int result;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_path_recs );\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+\r
+  /*\r
+   * Do a blocking query for all PathRecords in the subnet.\r
+   */\r
+  status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_PATH_RECORD,\r
+                                 sizeof( *p_rec ), &context );\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_write_all_path_recs: ERR 0025: "\r
+             "osmtest_get_all_recs failed (%s)\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  /*\r
+   * Write the received records out to the file.\r
+   */\r
+  num_recs = context.result.result_cnt;\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_write_all_path_recs: "\r
+             "Received %zu records\n", num_recs );\r
+  }\r
+\r
+  result = fprintf( fh, "#\n" "# Path Records\n" "#\n" );\r
+  if( result < 0 )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_write_all_path_recs: ERR 0026: "\r
+             "Write failed\n" );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  for( i = 0; i < num_recs; i++ )\r
+  {\r
+    p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i );\r
+    osmtest_write_path_info( p_osmt, fh, p_rec );\r
+  }\r
+\r
+ Exit:\r
+  /*\r
+   * Return the IB query MAD to the pool as necessary.\r
+   */\r
+  if( context.result.p_result_madw != NULL )\r
+  {\r
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+    context.result.p_result_madw = NULL;\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+#else\r
+/*\r
+ * NON RMPP BASED QUERY FOR ALL NODES: BASED ON THE MAX LID GIVEN BY THE USER\r
+ */\r
+static ib_api_status_t\r
+osmtest_write_all_node_recs(\r
+                            IN osmtest_t * const p_osmt,\r
+                            IN FILE * fh )\r
+{\r
+  osmtest_req_context_t context;\r
+  node_t *p_node;\r
+  node_t *p_guid_node;\r
+  const ib_node_record_t *p_rec;\r
+  cl_status_t status = CL_SUCCESS;\r
+  int result;\r
+  uint16_t lid;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_node_recs );\r
+\r
+  result = fprintf( fh, "#\n" "# Node Records\n" "#\n" );\r
+  if( result < 0 )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_write_all_node_recs: ERR 0027: "\r
+             "Write failed\n" );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  /*\r
+   * Go over all LIDs in the range 1 to max_lid and do a\r
+   * NodeRecord query by that lid.\r
+   */\r
+  for (lid = 1; lid <= p_osmt->max_lid; lid++)\r
+  {\r
+    /* prepare the query context */\r
+    memset( &context, 0, sizeof( context ) );\r
+\r
+    status = osmtest_get_node_rec_by_lid( p_osmt, cl_ntoh16( lid ), &context );\r
+    if( status != IB_SUCCESS )\r
+    {\r
+      if ( status != IB_SA_MAD_STATUS_NO_RECORDS )\r
+      {\r
+        osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                 "osmtest_write_all_node_recs: ERR 0028: "\r
+                 "failed to get node info for LID:0x%02X (%s)\n",\r
+                 cl_ntoh16( lid ),\r
+                 ib_get_err_str( status ) );\r
+        goto Exit;\r
+      }\r
+      else\r
+      {\r
+        osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                 "osmtest_write_all_node_recs: WRN 0121: "\r
+                 "failed to get node info for LID:0x%02X (%s)\n",\r
+                 cl_ntoh16( lid ),\r
+                 ib_get_err_str( status ) );\r
+        status = IB_SUCCESS;\r
+      }\r
+    }\r
+    else\r
+    {\r
+      /* OK we got something */\r
+      p_rec = osmv_get_query_node_rec( context.result.p_result_madw, 0 );\r
+      osmtest_write_node_info( p_osmt, fh, p_rec );\r
+\r
+      /* create a subnet object */\r
+      p_node = node_new(  );\r
+      CL_ASSERT( p_node != NULL );\r
+\r
+      /* copy the info to the subnet node object */\r
+      p_node->rec = *p_rec;\r
+\r
+      cl_qmap_insert( &p_osmt->exp_subn.node_lid_tbl,\r
+                      p_node->rec.lid, &p_node->map_item );\r
+\r
+      p_guid_node = node_new(  );\r
+      CL_ASSERT( p_guid_node != NULL );\r
+\r
+      *p_guid_node = *p_node;\r
+\r
+      cl_qmap_insert( &p_osmt->exp_subn.node_guid_tbl,\r
+                      p_guid_node->rec.node_info.node_guid,\r
+                      &p_guid_node->map_item );\r
+\r
+    }\r
+\r
+    if( context.result.p_result_madw != NULL )\r
+    {\r
+      osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+      context.result.p_result_madw = NULL;\r
+    }\r
+  }\r
+\r
+ Exit:\r
+  if( context.result.p_result_madw != NULL )\r
+  {\r
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+    context.result.p_result_madw = NULL;\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/*\r
+ * GET ALL PORT RECORDS IN THE FABRIC -\r
+ * one by one by using the node info received\r
+ */\r
+static ib_api_status_t\r
+osmtest_write_all_port_recs( IN osmtest_t * const p_osmt,\r
+                             IN FILE * fh )\r
+{\r
+  osmtest_req_context_t context;\r
+  const ib_node_record_t *p_node_rec;\r
+  const ib_portinfo_record_t *p_rec;\r
+  uint8_t port_num;\r
+  cl_status_t status = CL_SUCCESS;\r
+  cl_qmap_t *p_tbl;\r
+  node_t *p_node;\r
+  port_t *p_port;\r
+  int result;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_port_recs );\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+\r
+  /* print header */\r
+  result = fprintf( fh, "#\n" "# PortInfo Records\n" "#\n" );\r
+  if( result < 0 )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_write_all_port_recs: ERR 0029: " "Write failed\n" );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  /* use the pre-explored set of nodes */\r
+  p_tbl = &p_osmt->exp_subn.node_lid_tbl;\r
+  p_node = ( node_t * ) cl_qmap_head( p_tbl );\r
+\r
+  /*\r
+   * Go over all LIDs in the range 1 to max_lid and do a\r
+   * NodeRecord query by that lid.\r
+   */\r
+  while( p_node != ( node_t * ) cl_qmap_end( p_tbl ) )\r
+  {\r
+\r
+    p_node_rec = &(p_node->rec);\r
+\r
+    /* go through all ports of the node: */\r
+    for (port_num = 0; port_num <= p_node_rec->node_info.num_ports; port_num++)\r
+    {\r
+      /* prepare the query context */\r
+      memset( &context, 0, sizeof( context ) );\r
+\r
+      status = osmtest_get_port_rec_by_num( p_osmt,\r
+                                            p_node_rec->lid,\r
+                                            port_num,\r
+                                            &context );\r
+      if( status != IB_SUCCESS )\r
+      {\r
+        if( status != IB_SA_MAD_STATUS_NO_RECORDS )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                   "osmtest_write_all_port_recs: WRN 0122: "\r
+                   "Error encountered getting port info for LID:0x%04X Num:0x%02X (%s)\n",\r
+                   p_node_rec->lid, port_num,\r
+                   ib_get_err_str( status ) );\r
+          goto Exit;\r
+        }\r
+        else\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_write_all_port_recs: WRN 0123: "\r
+                   "failed to get port info for LID:0x%04X Num:0x%02X (%s)\n",\r
+                   p_node_rec->lid, port_num,\r
+                   ib_get_err_str( status ) );\r
+          status = IB_SUCCESS;\r
+        }\r
+      }\r
+      else\r
+      {\r
+        /* OK we got something */\r
+        p_rec = osmv_get_query_portinfo_rec( context.result.p_result_madw, 0 );\r
+        osmtest_write_port_info( p_osmt, fh, p_rec );\r
+\r
+        /* create a subnet object */\r
+        p_port = port_new(  );\r
+        CL_ASSERT( p_port != NULL );\r
+\r
+        /* copy the info to the subnet node object */\r
+        p_port->rec = *p_rec;\r
+\r
+        cl_qmap_insert( &p_osmt->exp_subn.port_key_tbl,\r
+        port_gen_id(p_node_rec->lid, port_num), &p_port->map_item );\r
+      }\r
+\r
+      if( context.result.p_result_madw != NULL )\r
+      {\r
+        osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+        context.result.p_result_madw = NULL;\r
+      }\r
+    }\r
+    p_node = ( node_t * ) cl_qmap_next( &p_node->map_item );\r
+  }\r
+\r
+  /* we must set the exist status to avoid abort of the over all algorith */\r
+\r
+ Exit:\r
+  /*\r
+   * Return the IB query MAD to the pool as necessary.\r
+   */\r
+\r
+  if( context.result.p_result_madw != NULL )\r
+  {\r
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+    context.result.p_result_madw = NULL;\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ * ASSUMES NO RMPP\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_write_all_path_recs( IN osmtest_t * const p_osmt,\r
+                             IN FILE * fh )\r
+{\r
+  osmtest_req_context_t context;\r
+  const ib_path_rec_t *p_rec;\r
+  cl_status_t status = CL_SUCCESS;\r
+  int num_recs, i;\r
+  cl_qmap_t *p_tbl;\r
+  node_t *p_src_node, *p_dst_node;\r
+  ib_api_status_t got_status = IB_SUCCESS;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_path_recs );\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+\r
+  /*\r
+   * Go over all nodes that exist in the subnet\r
+   * for each pair that are not switch nodes get the path record\r
+   */\r
+\r
+  context.p_osmt = p_osmt;\r
+\r
+  p_tbl = &p_osmt->exp_subn.node_lid_tbl;\r
+\r
+  p_src_node = ( node_t * ) cl_qmap_head( p_tbl );\r
+\r
+  while( p_src_node != ( node_t * ) cl_qmap_end( p_tbl ) )\r
+  {\r
+    /* HACK we use capability_mask to know diff a CA node from switch node */\r
+    /* if(p_src_node->rec.node_info.capability_mask  ) { */\r
+    p_dst_node = ( node_t * ) cl_qmap_head( p_tbl );\r
+\r
+    while( p_dst_node != ( node_t * ) cl_qmap_end( p_tbl ) )\r
+    {\r
+      /* HACK we use capability_mask to know diff a CA node from switch node */\r
+      /* if (p_dst_node->rec.node_info.capability_mask) { */\r
+\r
+      /* query for it: */\r
+      status = osmtest_get_path_rec_by_lid_pair( p_osmt,\r
+                                                 p_src_node->rec.lid,\r
+                                                 p_dst_node->rec.lid,\r
+                                                 &context );\r
+\r
+      if( status != IB_SUCCESS )\r
+      {\r
+        osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                 "osmtest_write_all_path_recs: ERR 012D: "\r
+                 "failed to get path info from LID:0x%X To LID:0x%X (%s)\n",\r
+                 p_src_node->rec.lid, p_dst_node->rec.lid,\r
+                 ib_get_err_str( status ) );\r
+        /* remember the first error status */\r
+        got_status = ( got_status == IB_SUCCESS ) ? status : got_status;\r
+      }\r
+      else\r
+      {\r
+        /* we might have received several records */\r
+        num_recs = context.result.result_cnt;\r
+        for (i = 0; i < num_recs; i++)\r
+        {\r
+          p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i );\r
+          osmtest_write_path_info( p_osmt, fh, p_rec );\r
+        }\r
+      }\r
+/*  } */\r
+\r
+      if( context.result.p_result_madw != NULL )\r
+      {\r
+        osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+        context.result.p_result_madw = NULL;\r
+      }\r
+\r
+      /* next one please */\r
+      p_dst_node = ( node_t * ) cl_qmap_next( &p_dst_node->map_item );\r
+    }\r
+/* } */\r
+\r
+    p_src_node = ( node_t * ) cl_qmap_next( &p_src_node->map_item );\r
+  }\r
+\r
+  if( got_status != IB_SUCCESS )\r
+    status = got_status;\r
+\r
+  /*\r
+   * Return the IB query MAD to the pool as necessary.\r
+   */\r
+  if( context.result.p_result_madw != NULL )\r
+  {\r
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+    context.result.p_result_madw = NULL;\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+#endif\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_create_inventory_file( IN osmtest_t * const p_osmt )\r
+{\r
+  FILE *fh;\r
+  ib_api_status_t status = IB_SUCCESS;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_create_inventory_file );\r
+\r
+  fh = fopen( p_osmt->opt.file_name, "w" );\r
+  if( fh == NULL )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_create_inventory_file: ERR 0079: "\r
+             "Unable to open inventory file (%s)\n",\r
+             p_osmt->opt.file_name );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  /* HACK: the order is important: nodes ports paths */\r
+  status = osmtest_write_all_node_recs( p_osmt, fh );\r
+  if( status != IB_SUCCESS )\r
+    goto Exit;\r
+\r
+  status = osmtest_write_all_port_recs( p_osmt, fh );\r
+  if( status != IB_SUCCESS )\r
+    goto Exit;\r
+\r
+  if (! p_osmt->opt.ignore_path_records)\r
+  {\r
+    status = osmtest_write_all_path_recs( p_osmt, fh );\r
+    if( status != IB_SUCCESS )\r
+      goto Exit;\r
+  }\r
+\r
+  status = osmtest_write_all_link_recs( p_osmt, fh );\r
+  if( status != IB_SUCCESS )\r
+    goto Exit;\r
+\r
+  fclose( fh );\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_stress_large_rmpp_pr( IN osmtest_t * const p_osmt )\r
+{\r
+  ib_api_status_t status = IB_SUCCESS;\r
+  uint64_t num_recs = 0;\r
+  uint64_t num_queries = 0;\r
+  uint32_t delta_recs;\r
+  uint32_t delta_queries;\r
+  uint32_t print_freq = 0;\r
+  struct timeval start_tv,end_tv;\r
+  long sec_diff,usec_diff;\r
+  float ratio;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_large_rmpp_pr );\r
+  gettimeofday( &start_tv, NULL );\r
+  printf("-I- Start time is : %09ld:%06ld [sec:usec]\n", start_tv.tv_sec, (long)start_tv.tv_usec);\r
+\r
+  while( num_queries < STRESS_LARGE_PR_RMPP_THR )\r
+  {\r
+    delta_recs = 0;\r
+    delta_queries = 0;\r
+\r
+    status = osmtest_stress_path_recs_by_guid( p_osmt, &delta_recs,\r
+                                               &delta_queries );\r
+    if( status != IB_SUCCESS )\r
+      goto Exit;\r
+\r
+    num_recs += delta_recs;\r
+    num_queries += delta_queries;\r
+\r
+    print_freq += delta_recs;\r
+    if( print_freq > 10000 )\r
+    {\r
+      gettimeofday( &end_tv, NULL );\r
+      if (end_tv.tv_usec > start_tv.tv_usec)\r
+      {\r
+        sec_diff = end_tv.tv_sec-start_tv.tv_sec;\r
+        usec_diff = end_tv.tv_usec-start_tv.tv_usec;\r
+      }\r
+      else\r
+      {\r
+        sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;\r
+        usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec);\r
+      }\r
+      printf("-I- End time is : %09ld:%06ld [sec:usec]\n",\r
+             end_tv.tv_sec, (long)end_tv.tv_usec);\r
+      printf("-I- Querying %" PRId64 " Path Record queries CA to CA (rmpp)\n\ttook %04ld:%06ld [sec:usec]\n",\r
+             num_queries, sec_diff, usec_diff);\r
+      if (num_recs == 0)\r
+        ratio = 0;\r
+      else\r
+        ratio = ((float)num_queries / (float)num_recs);\r
+      printf( "-I- Queries to Record Ratio is %" PRIu64 " records, %" PRIu64 " queries : %.2f \n",\r
+              num_recs, num_queries, ratio);\r
+      print_freq = 0;\r
+    }\r
+  }\r
+\r
+ Exit:\r
+   gettimeofday( &end_tv, NULL );\r
+   printf("-I- End time is : %09ld:%06ld [sec:usec]\n",\r
+          end_tv.tv_sec, (long)end_tv.tv_usec);\r
+   if (end_tv.tv_usec > start_tv.tv_usec)\r
+   {\r
+     sec_diff = end_tv.tv_sec-start_tv.tv_sec;\r
+     usec_diff = end_tv.tv_usec-start_tv.tv_usec;\r
+   }\r
+   else\r
+   {\r
+     sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;\r
+     usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec);\r
+   }\r
+\r
+   printf("-I- Querying %" PRId64 " Path Record queries (rmpp) took %04ld:%06ld [sec:usec]\n",\r
+          num_queries, sec_diff, usec_diff);\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_stress_large_rmpp( IN osmtest_t * const p_osmt )\r
+{\r
+  ib_api_status_t status = IB_SUCCESS;\r
+  uint64_t num_recs = 0;\r
+  uint64_t num_queries = 0;\r
+  uint32_t delta_recs;\r
+  uint32_t delta_queries;\r
+  uint32_t print_freq = 0;\r
+  struct timeval start_tv,end_tv;\r
+  long sec_diff,usec_diff;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_large_rmpp );\r
+  gettimeofday( &start_tv, NULL );\r
+  printf("-I- Start time is : %09ld:%06ld [sec:usec]\n", start_tv.tv_sec, (long)start_tv.tv_usec);\r
+\r
+  while( num_queries < STRESS_LARGE_RMPP_THR )\r
+  {\r
+    delta_recs = 0;\r
+    delta_queries = 0;\r
+\r
+    status = osmtest_stress_node_recs_large( p_osmt, &delta_recs,\r
+                                             &delta_queries );\r
+    if( status != IB_SUCCESS )\r
+      goto Exit;\r
+\r
+    status = osmtest_stress_path_recs_large( p_osmt, &delta_recs,\r
+                                             &delta_queries );\r
+    if( status != IB_SUCCESS )\r
+      goto Exit;\r
+\r
+    status = osmtest_stress_port_recs_large( p_osmt, &delta_recs,\r
+                                             &delta_queries );\r
+    if( status != IB_SUCCESS )\r
+      goto Exit;\r
+\r
+    num_recs += delta_recs;\r
+    num_queries += delta_queries;\r
+\r
+    print_freq += delta_recs;\r
+\r
+    if( print_freq > 100000 )\r
+    {\r
+      gettimeofday( &end_tv, NULL );\r
+      if (end_tv.tv_usec > start_tv.tv_usec)\r
+      {\r
+        sec_diff = end_tv.tv_sec-start_tv.tv_sec;\r
+        usec_diff = end_tv.tv_usec-start_tv.tv_usec;\r
+      }\r
+      else\r
+      {\r
+        sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;\r
+        usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec);\r
+      }\r
+      printf("-I- End time is : %09ld:%06ld [sec:usec]\n",\r
+             end_tv.tv_sec, (long)end_tv.tv_usec);\r
+      printf("-I- Querying %" PRId64 " large mixed queries (rmpp) took %04ld:%06ld [sec:usec]\n",\r
+             num_queries, sec_diff, usec_diff);\r
+      printf("%" PRIu64 " records, %" PRIu64 " queries\n",\r
+             num_recs, num_queries);\r
+      print_freq = 0;\r
+    }\r
+  }\r
+\r
+ Exit:\r
+   gettimeofday( &end_tv, NULL );\r
+   printf("-I- End time is : %09ld:%06ld [sec:usec]\n",\r
+          end_tv.tv_sec, (long)end_tv.tv_usec);\r
+   if (end_tv.tv_usec > start_tv.tv_usec)\r
+   {\r
+     sec_diff = end_tv.tv_sec-start_tv.tv_sec;\r
+     usec_diff = end_tv.tv_usec-start_tv.tv_usec;\r
+   }\r
+   else\r
+   {\r
+     sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;\r
+     usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec);\r
+   }\r
+\r
+   printf("-I- Querying %" PRId64 " large mixed queries (rmpp) took %04ld:%06ld [sec:usec]\n",\r
+          num_queries, sec_diff, usec_diff);\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_stress_small_rmpp( IN osmtest_t * const p_osmt )\r
+{\r
+  ib_api_status_t status = IB_SUCCESS;\r
+  uint64_t num_recs = 0;\r
+  uint64_t num_queries = 0;\r
+  uint32_t delta_recs;\r
+  uint32_t delta_queries;\r
+  uint32_t print_freq = 0;\r
+  int      num_timeouts = 0;\r
+  struct timeval start_tv,end_tv;\r
+  long sec_diff,usec_diff;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_small_rmpp );\r
+  gettimeofday( &start_tv, NULL );\r
+  printf("-I- Start time is : %09ld:%06ld [sec:usec]\n",\r
+         start_tv.tv_sec, (long)start_tv.tv_usec);\r
+\r
+  while( (num_queries < STRESS_SMALL_RMPP_THR) && (num_timeouts < 100) )\r
+  {\r
+    delta_recs = 0;\r
+    delta_queries = 0;\r
+\r
+    status = osmtest_stress_port_recs_small( p_osmt, &delta_recs,\r
+                                             &delta_queries );\r
+    if( status != IB_SUCCESS )\r
+      goto Exit;\r
+\r
+    num_recs += delta_recs;\r
+    num_queries += delta_queries;\r
+\r
+    print_freq += delta_recs;\r
+    if( print_freq > 5000 )\r
+    {\r
+      gettimeofday( &end_tv, NULL );\r
+      printf( "%" PRIu64 " records, %" PRIu64 " queries\n",\r
+              num_recs, num_queries );\r
+      if (end_tv.tv_usec > start_tv.tv_usec)\r
+      {\r
+        sec_diff = end_tv.tv_sec-start_tv.tv_sec;\r
+        usec_diff = end_tv.tv_usec-start_tv.tv_usec;\r
+      }\r
+      else\r
+      {\r
+        sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;\r
+        usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec);\r
+      }\r
+      printf("-I- End time is : %09ld:%06ld [sec:usec]\n",\r
+             end_tv.tv_sec, (long)end_tv.tv_usec);\r
+      printf("-I- Querying %" PRId64 " port_info queries (single mad) took %04ld:%06ld [sec:usec]\n",\r
+             num_queries, sec_diff, usec_diff);\r
+      print_freq = 0;\r
+    }\r
+  }\r
+\r
+ Exit:\r
+  gettimeofday( &end_tv, NULL );\r
+  printf("-I- End time is : %09ld:%06ld [sec:usec]\n",\r
+         end_tv.tv_sec, (long)end_tv.tv_usec);\r
+  if (end_tv.tv_usec > start_tv.tv_usec)\r
+  {\r
+    sec_diff = end_tv.tv_sec-start_tv.tv_sec;\r
+    usec_diff = end_tv.tv_usec-start_tv.tv_usec;\r
+  }\r
+  else\r
+  {\r
+    sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;\r
+    usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec);\r
+  }\r
+\r
+  printf("-I- Querying %" PRId64 " port_info queries (single mad) took %04ld:%06ld [sec:usec]\n",\r
+          num_queries, sec_diff, usec_diff);\r
+  if (num_timeouts > 50)\r
+  {\r
+    status = IB_TIMEOUT;\r
+  }\r
+  /* Exit: */\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static void\r
+osmtest_prepare_db_generic( IN osmtest_t * const p_osmt,\r
+                            IN cl_qmap_t * const p_tbl )\r
+{\r
+  generic_t *p_generic;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_prepare_db_generic );\r
+\r
+  p_generic = ( generic_t * ) cl_qmap_head( p_tbl );\r
+\r
+  while( p_generic != ( generic_t * ) cl_qmap_end( p_tbl ) )\r
+  {\r
+    p_generic->count = 0;\r
+    p_generic = ( generic_t * ) cl_qmap_next( &p_generic->map_item );\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static void\r
+osmtest_prepare_db( IN osmtest_t * const p_osmt )\r
+{\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_prepare_db );\r
+\r
+  osmtest_prepare_db_generic( p_osmt, &p_osmt->exp_subn.node_lid_tbl );\r
+  osmtest_prepare_db_generic( p_osmt, &p_osmt->exp_subn.path_tbl );\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_check_missing_nodes( IN osmtest_t * const p_osmt )\r
+{\r
+  const node_t *p_node;\r
+  cl_status_t status = IB_SUCCESS;\r
+  cl_qmap_t *p_tbl;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_check_missing_nodes );\r
+\r
+  p_tbl = &p_osmt->exp_subn.node_lid_tbl;\r
+\r
+  p_node = ( node_t * ) cl_qmap_head( p_tbl );\r
+\r
+  while( p_node != ( node_t * ) cl_qmap_end( p_tbl ) )\r
+  {\r
+    if( p_node->count == 0 )\r
+    {\r
+      /*\r
+       * This node was not reported by the SA\r
+       */\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_check_missing_nodes: ERR 0080: "\r
+               "Missing node 0x%016" PRIx64 "\n",\r
+               cl_ntoh64( p_node->rec.node_info.node_guid ) );\r
+      status = IB_ERROR;\r
+    }\r
+\r
+    p_node = ( node_t * ) cl_qmap_next( &p_node->map_item );\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_check_missing_ports( IN osmtest_t * const p_osmt )\r
+{\r
+  const port_t *p_port;\r
+  cl_status_t status = IB_SUCCESS;\r
+  cl_qmap_t *p_tbl;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_check_missing_ports );\r
+\r
+  p_tbl = &p_osmt->exp_subn.port_key_tbl;\r
+\r
+  p_port = ( port_t * ) cl_qmap_head( p_tbl );\r
+\r
+  while( p_port != ( port_t * ) cl_qmap_end( p_tbl ) )\r
+  {\r
+    if( p_port->count == 0 )\r
+    {\r
+      /*\r
+       * This port was not reported by the SA\r
+       */\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_check_missing_ports: ERR 0081: "\r
+               "Missing port LID:0x%X Num:0x%X\n",\r
+               cl_ntoh16( p_port->rec.lid), p_port->rec.port_num);\r
+      status = IB_ERROR;\r
+    }\r
+\r
+    p_port = ( port_t * ) cl_qmap_next( &p_port->map_item );\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_check_missing_paths( IN osmtest_t * const p_osmt )\r
+{\r
+  const path_t *p_path;\r
+  cl_status_t status = IB_SUCCESS;\r
+  cl_qmap_t *p_tbl;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_check_missing_paths );\r
+\r
+  p_tbl = &p_osmt->exp_subn.path_tbl;\r
+\r
+  p_path = ( path_t * ) cl_qmap_head( p_tbl );\r
+\r
+  while( p_path != ( path_t * ) cl_qmap_end( p_tbl ) )\r
+  {\r
+    if( p_path->count == 0 )\r
+    {\r
+      /*\r
+       * This path was not reported by the SA\r
+       */\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_check_missing_paths: ERR 0051: "\r
+               "SA did not return path SLID 0x%X to DLID 0x%X\n",\r
+               cl_ntoh16( p_path->rec.slid ),\r
+               cl_ntoh16( p_path->rec.dlid ) );\r
+      status = IB_ERROR;\r
+      goto Exit;\r
+    }\r
+\r
+    p_path = ( path_t * ) cl_qmap_next( &p_path->map_item );\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+inline uint32_t\r
+osmtest_path_rec_key_get( IN const ib_path_rec_t * const p_rec )\r
+{\r
+  return ( p_rec->dlid << 16 | p_rec->slid );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static boolean_t\r
+osmtest_path_rec_kay_is_valid( IN osmtest_t * const p_osmt,\r
+                               IN const path_t * const p_path )\r
+{\r
+  if( ( p_path->comp.dlid == 0 ) || ( p_path->comp.slid == 0 ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_path_rec_kay_is_valid: ERR 0168: "\r
+             "SLID and DLID must be specified for defined paths\n" );\r
+    return ( FALSE );\r
+  }\r
+\r
+  return ( TRUE );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_path_data( IN osmtest_t * const p_osmt,\r
+                            IN path_t * const p_path,\r
+                            IN const ib_path_rec_t * const p_rec )\r
+{\r
+  cl_status_t status = IB_SUCCESS;\r
+  uint8_t lmc = 0;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_path_data );\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_path_data: "\r
+             "Checking path SLID 0x%X to DLID 0x%X\n",\r
+             cl_ntoh16( p_rec->slid ), cl_ntoh16( p_rec->dlid ) );\r
+  }\r
+\r
+  status = osmtest_get_local_port_lmc( p_osmt, p_osmt->local_port.lid, &lmc );\r
+  if (status != IB_SUCCESS)\r
+    goto Exit;\r
+\r
+  /* HACK: Assume uniform LMC across endports in the subnet */ \r
+  /* This is the only LMC mode which OpenSM currently supports */\r
+  /* In absence of this assumption, validation of this is much more complicated */\r
+  if ( lmc == 0 )\r
+  {\r
+    /*\r
+     * Has this record already been returned?\r
+     */\r
+    if( p_path->count != 0 )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_validate_path_data: ERR 0056: "\r
+               "Already received path SLID 0x%X to DLID 0x%X\n",\r
+               cl_ntoh16( p_rec->slid ), cl_ntoh16( p_rec->dlid ) );\r
+      status = IB_ERROR;\r
+      goto Exit;\r
+    }\r
+  }\r
+  else\r
+  {\r
+    /* Also, this doesn't detect fewer than the correct number of paths being returned */\r
+    if ( p_path->count >= (uint32_t)( 1 << (2*lmc) ) )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_validate_path_data: ERR 0052: "\r
+               "Already received path SLID 0x%X to DLID 0x%X count %d LMC %d\n",\r
+               cl_ntoh16( p_rec->slid ), cl_ntoh16( p_rec->dlid ),\r
+               p_path->count, lmc );\r
+      status = IB_ERROR;\r
+      goto Exit;\r
+    }\r
+  }\r
+\r
+  ++p_path->count;\r
+\r
+  /*\r
+   * Check the fields the user wants checked.\r
+   */\r
+  if( ( p_path->comp.dgid.unicast.interface_id &\r
+        p_path->rec.dgid.unicast.interface_id ) !=\r
+      ( p_path->comp.dgid.unicast.interface_id &\r
+        p_rec->dgid.unicast.interface_id ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_path_data: ERR 0169: "\r
+             "DGID mismatch on path SLID 0x%X to DLID 0x%X\n"\r
+             "\t\t\t\tExpected 0x%016" PRIx64 " 0x%016" PRIx64 "\n"\r
+             "\t\t\t\tReceived 0x%016" PRIx64 " 0x%016" PRIx64 "\n",\r
+             cl_ntoh16( p_path->rec.slid ),\r
+             cl_ntoh16( p_path->rec.dlid ),\r
+             cl_ntoh64( p_path->rec.dgid.unicast.prefix ),\r
+             cl_ntoh64( p_path->rec.dgid.unicast.interface_id ),\r
+             cl_ntoh64( p_rec->dgid.unicast.prefix ),\r
+             cl_ntoh64( p_rec->dgid.unicast.interface_id ) );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  /*\r
+   * Check the fields the user wants checked.\r
+   */\r
+  if( ( p_path->comp.sgid.unicast.interface_id &\r
+        p_path->rec.sgid.unicast.interface_id ) !=\r
+      ( p_path->comp.sgid.unicast.interface_id &\r
+        p_rec->sgid.unicast.interface_id ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_path_data: ERR 0057: "\r
+             "SGID mismatch on path SLID 0x%X to DLID 0x%X\n"\r
+             "\t\t\t\tExpected 0x%016" PRIx64 " 0x%016" PRIx64 ",\n"\r
+             "\t\t\t\tReceived 0x%016" PRIx64 " 0x%016" PRIx64 ".\n",\r
+             cl_ntoh16( p_path->rec.slid ),\r
+             cl_ntoh16( p_path->rec.dlid ),\r
+             cl_ntoh64( p_path->rec.sgid.unicast.prefix ),\r
+             cl_ntoh64( p_path->rec.sgid.unicast.interface_id ),\r
+             cl_ntoh64( p_rec->sgid.unicast.prefix ),\r
+             cl_ntoh64( p_rec->sgid.unicast.interface_id ) );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  /*\r
+   * Compare the fields the user wishes to validate.\r
+   */\r
+  if( ( p_path->comp.pkey & p_path->rec.pkey ) !=\r
+      ( p_path->comp.pkey & p_rec->pkey ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_path_data: ERR 0012: "\r
+             "PKEY mismatch on path SLID 0x%X to DLID 0x%X\n"\r
+             "\t\t\t\tExpected 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_path->rec.slid ),\r
+             cl_ntoh16( p_path->rec.dlid ),\r
+             cl_ntoh16( p_path->rec.pkey ),\r
+             cl_ntoh16( p_rec->pkey ) );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_node_data( IN osmtest_t * const p_osmt,\r
+                            IN node_t * const p_node,\r
+                            IN const ib_node_record_t * const p_rec )\r
+{\r
+  cl_status_t status = IB_SUCCESS;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_node_data );\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_node_data: "\r
+             "Checking node 0x%016" PRIx64 ", LID 0x%X\n",\r
+             cl_ntoh64( p_rec->node_info.node_guid ),\r
+             cl_ntoh16( p_rec->lid ) );\r
+  }\r
+\r
+  /*\r
+   * Has this record already been returned?\r
+   */\r
+  if( p_node->count != 0 )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_node_data: ERR 0013: "\r
+             "Already received node 0x%016" PRIx64 "\n",\r
+             cl_ntoh64( p_node->rec.node_info.node_guid ) );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  ++p_node->count;\r
+\r
+  /*\r
+   * Compare the fields the user wishes to validate.\r
+   */\r
+  if( ( p_node->comp.lid & p_node->rec.lid ) !=\r
+      ( p_node->comp.lid & p_rec->lid ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_node_data: ERR 0014: "\r
+             "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"\r
+             "\t\t\t\tExpected LID 0x%X, received 0x%X\n",\r
+             cl_ntoh64( p_rec->node_info.node_guid ),\r
+             cl_ntoh16( p_rec->lid ), p_node->rec.lid, p_rec->lid );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_node->comp.node_info.base_version &\r
+        p_node->rec.node_info.base_version ) !=\r
+      ( p_node->comp.node_info.base_version &\r
+        p_rec->node_info.base_version ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_node_data: ERR 0015: "\r
+             "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"\r
+             "\t\t\t\tExpected base_version 0x%X, received 0x%X\n",\r
+             cl_ntoh64( p_rec->node_info.node_guid ),\r
+             cl_ntoh16( p_rec->lid ),\r
+             p_node->rec.node_info.base_version,\r
+             p_rec->node_info.base_version );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_node->comp.node_info.class_version &\r
+        p_node->rec.node_info.class_version ) !=\r
+      ( p_node->comp.node_info.class_version &\r
+        p_rec->node_info.class_version ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_node_data: ERR 0016: "\r
+             "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"\r
+             "\t\t\t\tExpected class_version 0x%X, received 0x%X\n",\r
+             cl_ntoh64( p_rec->node_info.node_guid ),\r
+             cl_ntoh16( p_rec->lid ),\r
+             p_node->rec.node_info.class_version,\r
+             p_rec->node_info.class_version );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_node->comp.node_info.node_type &\r
+        p_node->rec.node_info.node_type ) !=\r
+      ( p_node->comp.node_info.node_type & p_rec->node_info.node_type ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_node_data: ERR 0017: "\r
+             "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"\r
+             "\t\t\t\tExpected node_type 0x%X, received 0x%X\n",\r
+             cl_ntoh64( p_rec->node_info.node_guid ),\r
+             cl_ntoh16( p_rec->lid ),\r
+             p_node->rec.node_info.node_type,\r
+             p_rec->node_info.node_type );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_node->comp.node_info.sys_guid &\r
+        p_node->rec.node_info.sys_guid ) !=\r
+      ( p_node->comp.node_info.sys_guid & p_rec->node_info.sys_guid ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_node_data: ERR 0018: "\r
+             "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"\r
+             "\t\t\t\tExpected sys_guid 0x%016" PRIx64\r
+             ", received 0x%016" PRIx64 "\n",\r
+             cl_ntoh64( p_rec->node_info.node_guid ),\r
+             cl_ntoh16( p_rec->lid ),\r
+             cl_ntoh64( p_node->rec.node_info.sys_guid ),\r
+             cl_ntoh64( p_rec->node_info.sys_guid ) );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_node->comp.node_info.node_guid &\r
+        p_node->rec.node_info.node_guid ) !=\r
+      ( p_node->comp.node_info.node_guid & p_rec->node_info.node_guid ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_node_data: ERR 0019: "\r
+             "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"\r
+             "\t\t\t\tExpected node_guid 0x%016" PRIx64\r
+             ", received 0x%016" PRIx64 "\n",\r
+             cl_ntoh64( p_rec->node_info.node_guid ),\r
+             cl_ntoh16( p_rec->lid ),\r
+             cl_ntoh64( p_node->rec.node_info.node_guid ),\r
+             cl_ntoh64( p_rec->node_info.node_guid ) );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_node->comp.node_info.port_guid &\r
+        p_node->rec.node_info.port_guid ) !=\r
+      ( p_node->comp.node_info.port_guid & p_rec->node_info.port_guid ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_node_data: ERR 0031: "\r
+             "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"\r
+             "\t\t\t\tExpected port_guid 0x%016" PRIx64\r
+             ", received 0x%016" PRIx64 "\n",\r
+             cl_ntoh64( p_rec->node_info.node_guid ),\r
+             cl_ntoh16( p_rec->lid ),\r
+             cl_ntoh64( p_node->rec.node_info.port_guid ),\r
+             cl_ntoh64( p_rec->node_info.port_guid ) );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_node->comp.node_info.partition_cap &\r
+        p_node->rec.node_info.partition_cap ) !=\r
+      ( p_node->comp.node_info.partition_cap &\r
+        p_rec->node_info.partition_cap ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_node_data: ERR 0032: "\r
+             "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"\r
+             "\t\t\t\tExpected partition_cap 0x%X"\r
+             ", received 0x%X\n",\r
+             cl_ntoh64( p_rec->node_info.node_guid ),\r
+             cl_ntoh16( p_rec->lid ),\r
+             cl_ntoh16( p_node->rec.node_info.partition_cap ),\r
+             cl_ntoh16( p_rec->node_info.partition_cap ) );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_node->comp.node_info.device_id &\r
+        p_node->rec.node_info.device_id ) !=\r
+      ( p_node->comp.node_info.device_id & p_rec->node_info.device_id ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_node_data: ERR 0033: "\r
+             "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"\r
+             "\t\t\t\tExpected device_id 0x%X"\r
+             ", received 0x%X\n",\r
+             cl_ntoh64( p_rec->node_info.node_guid ),\r
+             cl_ntoh16( p_rec->lid ),\r
+             cl_ntoh16( p_node->rec.node_info.device_id ),\r
+             cl_ntoh16( p_rec->node_info.device_id ) );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_node->comp.node_info.revision &\r
+        p_node->rec.node_info.revision ) !=\r
+      ( p_node->comp.node_info.revision & p_rec->node_info.revision ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_node_data: ERR 0034: "\r
+             "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"\r
+             "\t\t\t\tExpected revision 0x%X"\r
+             ", received 0x%X\n",\r
+             cl_ntoh64( p_rec->node_info.node_guid ),\r
+             cl_ntoh16( p_rec->lid ),\r
+             cl_ntoh32( p_node->rec.node_info.revision ),\r
+             cl_ntoh32( p_rec->node_info.revision ) );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_node_rec( IN osmtest_t * const p_osmt,\r
+                           IN const ib_node_record_t * const p_rec )\r
+{\r
+  cl_status_t status = IB_SUCCESS;\r
+  node_t *p_node;\r
+  const cl_qmap_t *p_tbl;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_node_rec );\r
+\r
+  /*\r
+   * Find proper node record in the database.\r
+   */\r
+  p_tbl = &p_osmt->exp_subn.node_lid_tbl;\r
+  p_node = ( node_t * ) cl_qmap_get( p_tbl, p_rec->lid );\r
+  if( p_node == ( node_t * ) cl_qmap_end( p_tbl ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_node_rec: ERR 0035: "\r
+             "Unexpected node 0x%016" PRIx64 ", LID 0x%X\n",\r
+             cl_ntoh64( p_rec->node_info.node_guid ),\r
+             cl_ntoh16( p_rec->lid ) );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  status = osmtest_validate_node_data( p_osmt, p_node, p_rec );\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_port_data( IN osmtest_t * const p_osmt,\r
+                            IN port_t * const p_port,\r
+                            IN const ib_portinfo_record_t * const p_rec )\r
+{\r
+  cl_status_t status = IB_SUCCESS;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_port_data );\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: "\r
+             "Checking port LID 0x%X, Num 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num);\r
+  }\r
+\r
+  /*\r
+   * Has this record already been returned?\r
+   */\r
+  if( p_port->count != 0 )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0036: "\r
+             "Already received port LID 0x%X, Num 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num);\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  ++p_port->count;\r
+\r
+  /*\r
+   * Compare the fields the user wishes to validate.\r
+   */\r
+  if( ( p_port->comp.lid & p_port->rec.lid ) !=\r
+      ( p_port->comp.lid & p_rec->lid ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0037: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected LID 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.lid, p_rec->lid );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_num & p_port->rec.port_num ) !=\r
+      ( p_port->comp.port_num & p_rec->port_num ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0038: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected port_num 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_num, p_rec->port_num );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.m_key & p_port->rec.port_info.m_key ) !=\r
+      ( p_port->comp.port_info.m_key & p_rec->port_info.m_key ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0039: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected m_key 0x%016" PRIx64 ", received 0x%016" PRIx64 "\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.m_key, p_rec->port_info.m_key );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.subnet_prefix & p_port->rec.port_info.subnet_prefix ) !=\r
+      ( p_port->comp.port_info.subnet_prefix & p_rec->port_info.subnet_prefix ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0040: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected subnet_prefix 0x%016" PRIx64 ", received 0x%016" PRIx64 "\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.subnet_prefix, p_rec->port_info.subnet_prefix );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.base_lid & p_port->rec.port_info.base_lid ) !=\r
+      ( p_port->comp.port_info.base_lid & p_rec->port_info.base_lid ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0041: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected base_lid 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.base_lid, p_rec->port_info.base_lid );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.master_sm_base_lid & p_port->rec.port_info.master_sm_base_lid ) !=\r
+      ( p_port->comp.port_info.master_sm_base_lid & p_rec->port_info.master_sm_base_lid ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0042: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected master_sm_base_lid 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.master_sm_base_lid, p_rec->port_info.master_sm_base_lid );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.capability_mask & p_port->rec.port_info.capability_mask ) !=\r
+      ( p_port->comp.port_info.capability_mask & p_rec->port_info.capability_mask ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0043: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected capability_mask 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.capability_mask, p_rec->port_info.capability_mask );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.diag_code & p_port->rec.port_info.diag_code ) !=\r
+      ( p_port->comp.port_info.diag_code & p_rec->port_info.diag_code ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0044: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected diag_code 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.diag_code, p_rec->port_info.diag_code );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.m_key_lease_period & p_port->rec.port_info.m_key_lease_period ) !=\r
+      ( p_port->comp.port_info.m_key_lease_period & p_rec->port_info.m_key_lease_period ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0045: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected m_key_lease_period 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.m_key_lease_period, p_rec->port_info.m_key_lease_period );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.local_port_num & p_port->rec.port_info.local_port_num ) !=\r
+      ( p_port->comp.port_info.local_port_num & p_rec->port_info.local_port_num ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0046: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected local_port_num 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.local_port_num, p_rec->port_info.local_port_num );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.link_width_enabled & p_port->rec.port_info.link_width_enabled ) !=\r
+      ( p_port->comp.port_info.link_width_enabled & p_rec->port_info.link_width_enabled ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0047: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected link_width_enabled 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.link_width_enabled, p_rec->port_info.link_width_enabled );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.link_width_supported & p_port->rec.port_info.link_width_supported ) !=\r
+      ( p_port->comp.port_info.link_width_supported & p_rec->port_info.link_width_supported ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0048: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected link_width_supported 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.link_width_supported, p_rec->port_info.link_width_supported );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.link_width_active & p_port->rec.port_info.link_width_active ) !=\r
+      ( p_port->comp.port_info.link_width_active & p_rec->port_info.link_width_active ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0049: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected link_width_active 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.link_width_active, p_rec->port_info.link_width_active );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.link_speed & p_port->rec.port_info.link_speed ) !=\r
+      ( p_port->comp.port_info.link_speed & p_rec->port_info.link_speed ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0054: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected link_speed 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.link_speed, p_rec->port_info.link_speed );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.state_info1 & p_port->rec.port_info.state_info1 ) !=\r
+      ( p_port->comp.port_info.state_info1 & p_rec->port_info.state_info1 ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0055: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected state_info1 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.state_info1, p_rec->port_info.state_info1 );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.state_info2 & p_port->rec.port_info.state_info2 ) !=\r
+      ( p_port->comp.port_info.state_info2 & p_rec->port_info.state_info2 ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0058: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected state_info2 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.state_info2, p_rec->port_info.state_info2 );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.mkey_lmc & p_port->rec.port_info.mkey_lmc ) !=\r
+      ( p_port->comp.port_info.mkey_lmc & p_rec->port_info.mkey_lmc ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0059: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected mkey_lmc 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.mkey_lmc, p_rec->port_info.mkey_lmc );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.link_speed & p_port->rec.port_info.link_speed ) !=\r
+      ( p_port->comp.port_info.link_speed & p_rec->port_info.link_speed ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0060: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected link_speed 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.link_speed, p_rec->port_info.link_speed );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.mtu_smsl & p_port->rec.port_info.mtu_smsl ) !=\r
+      ( p_port->comp.port_info.mtu_smsl & p_rec->port_info.mtu_smsl ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0061: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected mtu_smsl 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.mtu_smsl, p_rec->port_info.mtu_smsl );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.vl_cap & p_port->rec.port_info.vl_cap ) !=\r
+      ( p_port->comp.port_info.vl_cap & p_rec->port_info.vl_cap ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0062: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected vl_cap 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.vl_cap, p_rec->port_info.vl_cap );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.vl_high_limit & p_port->rec.port_info.vl_high_limit ) !=\r
+      ( p_port->comp.port_info.vl_high_limit & p_rec->port_info.vl_high_limit ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0082: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected vl_high_limit 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.vl_high_limit, p_rec->port_info.vl_high_limit );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.vl_arb_high_cap & p_port->rec.port_info.vl_arb_high_cap ) !=\r
+      ( p_port->comp.port_info.vl_arb_high_cap & p_rec->port_info.vl_arb_high_cap ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0083: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected vl_arb_high_cap 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.vl_arb_high_cap, p_rec->port_info.vl_arb_high_cap );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.vl_arb_low_cap & p_port->rec.port_info.vl_arb_low_cap ) !=\r
+      ( p_port->comp.port_info.vl_arb_low_cap & p_rec->port_info.vl_arb_low_cap ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0084: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected vl_arb_low_cap 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.vl_arb_low_cap, p_rec->port_info.vl_arb_low_cap );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.mtu_cap & p_port->rec.port_info.mtu_cap ) !=\r
+      ( p_port->comp.port_info.mtu_cap & p_rec->port_info.mtu_cap ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0085: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected mtu_cap 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.mtu_cap, p_rec->port_info.mtu_cap );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+#if 0\r
+  /* this is a dynamic attribute */\r
+  if( ( p_port->comp.port_info.vl_stall_life & p_port->rec.port_info.vl_stall_life ) !=\r
+      ( p_port->comp.port_info.vl_stall_life & p_rec->port_info.vl_stall_life ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 012F: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected vl_stall_life 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.vl_stall_life,\r
+             p_rec->port_info.vl_stall_life );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+#endif\r
+\r
+  if( ( p_port->comp.port_info.vl_enforce & p_port->rec.port_info.vl_enforce ) !=\r
+      ( p_port->comp.port_info.vl_enforce & p_rec->port_info.vl_enforce ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0086: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected vl_enforce 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.vl_enforce, p_rec->port_info.vl_enforce );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.m_key_violations & p_port->rec.port_info.m_key_violations ) !=\r
+      ( p_port->comp.port_info.m_key_violations & p_rec->port_info.m_key_violations ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0087: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected m_key_violations 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             cl_ntoh16( p_port->rec.port_info.m_key_violations ),\r
+             cl_ntoh16( p_rec->port_info.m_key_violations ) );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.p_key_violations & p_port->rec.port_info.p_key_violations ) !=\r
+      ( p_port->comp.port_info.p_key_violations & p_rec->port_info.p_key_violations ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0088: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected p_key_violations 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             cl_ntoh16( p_port->rec.port_info.p_key_violations ),\r
+             cl_ntoh16( p_rec->port_info.p_key_violations ) );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.q_key_violations & p_port->rec.port_info.q_key_violations ) !=\r
+      ( p_port->comp.port_info.q_key_violations & p_rec->port_info.q_key_violations ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0089: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected q_key_violations 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             cl_ntoh16( p_port->rec.port_info.q_key_violations ),\r
+             cl_ntoh16( p_rec->port_info.q_key_violations ) );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.guid_cap & p_port->rec.port_info.guid_cap ) !=\r
+      ( p_port->comp.port_info.guid_cap & p_rec->port_info.guid_cap ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0090: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected guid_cap 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.guid_cap, p_rec->port_info.guid_cap );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.subnet_timeout & p_port->rec.port_info.subnet_timeout ) !=\r
+      ( p_port->comp.port_info.subnet_timeout & p_rec->port_info.subnet_timeout ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0091: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected subnet_timeout 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             ib_port_info_get_timeout(&p_port->rec.port_info),\r
+             ib_port_info_get_timeout(&p_rec->port_info) );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.resp_time_value & p_port->rec.port_info.resp_time_value ) !=\r
+      ( p_port->comp.port_info.resp_time_value & p_rec->port_info.resp_time_value ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0092: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected resp_time_value 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.resp_time_value,\r
+             p_rec->port_info.resp_time_value );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  if( ( p_port->comp.port_info.error_threshold & p_port->rec.port_info.error_threshold ) !=\r
+      ( p_port->comp.port_info.error_threshold & p_rec->port_info.error_threshold ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_data: ERR 0093: "\r
+             "Field mismatch port LID 0x%X Num:0x%X\n"\r
+             "\t\t\t\tExpected error_threshold 0x%X, received 0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+             p_port->rec.port_info.error_threshold,\r
+             p_rec->port_info.error_threshold );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_port_rec( IN osmtest_t * const p_osmt,\r
+                           IN const ib_portinfo_record_t * const p_rec )\r
+{\r
+  cl_status_t status = IB_SUCCESS;\r
+  port_t *p_port;\r
+  const cl_qmap_t *p_tbl;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_port_rec );\r
+\r
+  /*\r
+   * Find proper port record in the database.\r
+   * (we use by guid - since lid is not unique)\r
+   */\r
+  p_tbl = &p_osmt->exp_subn.port_key_tbl;\r
+  p_port = ( port_t * ) cl_qmap_get( p_tbl, port_gen_id( p_rec->lid, p_rec->port_num));\r
+  if( p_port == ( port_t * ) cl_qmap_end( p_tbl ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_port_rec: ERR 0094: "\r
+             "Unexpected port LID 0x%X, Num:0x%X\n",\r
+             cl_ntoh16( p_rec->lid ), p_rec->port_num );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  status = osmtest_validate_port_data( p_osmt, p_port, p_rec );\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_path_rec( IN osmtest_t * const p_osmt,\r
+                           IN const ib_path_rec_t * const p_rec )\r
+{\r
+  cl_status_t status = IB_SUCCESS;\r
+  path_t *p_path;\r
+  const cl_qmap_t *p_tbl;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_path_rec );\r
+\r
+  /*\r
+   * Find proper path record in the database.\r
+   */\r
+  p_tbl = &p_osmt->exp_subn.path_tbl;\r
+  p_path =\r
+    ( path_t * ) cl_qmap_get( p_tbl, osmtest_path_rec_key_get( p_rec ) );\r
+  if( p_path == ( path_t * ) cl_qmap_end( p_tbl ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_path_rec: ERR 0095: "\r
+             "Unexpected path SLID 0x%X to DLID 0x%X\n",\r
+             cl_ntoh16( p_rec->slid ), cl_ntoh16( p_rec->dlid ) );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  status = osmtest_validate_path_data( p_osmt, p_path, p_rec );\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+#ifdef VENDOR_RMPP_SUPPORT\r
+ib_net64_t portguid = 0;\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_all_node_recs( IN osmtest_t * const p_osmt )\r
+{\r
+  osmtest_req_context_t context;\r
+  const ib_node_record_t *p_rec;\r
+  uint32_t i;\r
+  cl_status_t status;\r
+  size_t num_recs;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_all_node_recs );\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+\r
+  /*\r
+   * Do a blocking query for all NodeRecords in the subnet.\r
+   */\r
+  status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_NODE_RECORD,\r
+                                 sizeof( *p_rec ), &context );\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_all_node_recs: ERR 0096: "\r
+             "osmtest_get_all_recs failed (%s)\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  num_recs = context.result.result_cnt;\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_validate_all_node_recs: "\r
+             "Received %zu records\n", num_recs );\r
+  }\r
+\r
+  /*\r
+   * Compare the received records to the database.\r
+   */\r
+  osmtest_prepare_db( p_osmt );\r
+\r
+  for( i = 0; i < num_recs; i++ )\r
+  {\r
+    p_rec = osmv_get_query_node_rec( context.result.p_result_madw, i );\r
+\r
+    status = osmtest_validate_node_rec( p_osmt, p_rec );\r
+    if( status != IB_SUCCESS )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_validate_all_node_recs: ERR 0097: "\r
+               "osmtest_valid_node_rec failed (%s)\n",\r
+               ib_get_err_str( status ) );\r
+      goto Exit;\r
+    }\r
+    if (!portguid)\r
+      portguid = p_rec->node_info.port_guid;\r
+  }\r
+\r
+  status = osmtest_check_missing_nodes( p_osmt );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_all_node_recs: ERR 0098: "\r
+             "osmtest_check_missing_nodes failed (%s)\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  /*\r
+   * Return the IB query MAD to the pool as necessary.\r
+   */\r
+  if( context.result.p_result_madw != NULL )\r
+  {\r
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+    context.result.p_result_madw = NULL;\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_all_guidinfo_recs( IN osmtest_t * const p_osmt )\r
+{   \r
+  osmtest_req_context_t context;\r
+  const ib_guidinfo_record_t *p_rec;\r
+  cl_status_t status;\r
+  size_t num_recs;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_all_guidinfo_recs );\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+\r
+  /*\r
+   * Do a blocking query for all GuidInfoRecords in the subnet.\r
+   */\r
+  status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_GUIDINFO_RECORD,\r
+                                 sizeof( *p_rec ), &context );\r
+\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_all_guidinfo_recs: ERR 0099: "\r
+             "osmtest_get_all_recs failed (%s)\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  num_recs = context.result.result_cnt;\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_validate_all_guidinfo_recs: "\r
+             "Received %zu records\n", num_recs );\r
+  }\r
+\r
+  /* No validation as yet */\r
+\r
+ Exit:\r
+  /*\r
+   * Return the IB query MAD to the pool as necessary.\r
+   */\r
+  if( context.result.p_result_madw != NULL )\r
+  {\r
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+    context.result.p_result_madw = NULL;\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_all_path_recs( IN osmtest_t * const p_osmt )\r
+{\r
+  osmtest_req_context_t context;\r
+  const ib_path_rec_t *p_rec;\r
+  uint32_t i;\r
+  cl_status_t status;\r
+  size_t num_recs;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_all_path_recs );\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+\r
+  /*\r
+   * Do a blocking query for all PathRecords in the subnet.\r
+   */\r
+  status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_PATH_RECORD,\r
+                                 sizeof( *p_rec ), &context );\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_all_path_recs: ERR 009A: "\r
+             "osmtest_get_all_recs failed (%s)\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  num_recs = context.result.result_cnt;\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_validate_all_path_recs: "\r
+             "Received %zu records\n", num_recs );\r
+  }\r
+\r
+  /*\r
+   * Compare the received records to the database.\r
+   */\r
+  osmtest_prepare_db( p_osmt );\r
+\r
+  for( i = 0; i < num_recs; i++ )\r
+  {\r
+    p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i );\r
+\r
+    status = osmtest_validate_path_rec( p_osmt, p_rec );\r
+    if( status != IB_SUCCESS )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_validate_all_path_recs: ERR 0100: "\r
+               "osmtest_validate_path_rec failed (%s)\n",\r
+               ib_get_err_str( status ) );\r
+      goto Exit;\r
+    }\r
+  }\r
+\r
+  status = osmtest_check_missing_paths( p_osmt );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_all_path_recs: ERR 0101: "\r
+             "osmtest_check_missing_paths failed (%s)\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  /*\r
+   * Return the IB query MAD to the pool as necessary.\r
+   */\r
+  if( context.result.p_result_madw != NULL )\r
+  {\r
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+    context.result.p_result_madw = NULL;\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ * Get link record by LID\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_get_link_rec_by_lid( IN osmtest_t * const p_osmt,\r
+                             IN ib_net16_t const  from_lid,\r
+                             IN ib_net16_t const  to_lid,\r
+                             IN OUT osmtest_req_context_t * const p_context )\r
+{\r
+  ib_api_status_t status = IB_SUCCESS;\r
+  osmv_user_query_t user;\r
+  osmv_query_req_t req;\r
+  ib_link_record_t record;\r
+  ib_mad_t *p_mad;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_get_link_rec_by_lid );\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_get_link_rec_by_lid: "\r
+             "Getting link record from LID 0x%02X to LID 0x%02X\n",\r
+             cl_ntoh16( from_lid ), cl_ntoh16( to_lid ) );\r
+  }\r
+\r
+  /*\r
+   * Do a blocking query for this record in the subnet.\r
+   * The result is returned in the result field of the caller's\r
+   * context structure.\r
+   *\r
+   * The query structures are locals.\r
+   */\r
+  memset( &req, 0, sizeof( req ) );\r
+  memset( &user, 0, sizeof( user ) );\r
+  memset( &record, 0, sizeof( record ) );\r
+\r
+  record.from_lid = from_lid;\r
+  record.to_lid = to_lid;\r
+  p_context->p_osmt = p_osmt;\r
+  if (from_lid)\r
+    user.comp_mask |= IB_LR_COMPMASK_FROM_LID;\r
+  if (to_lid)\r
+    user.comp_mask |= IB_LR_COMPMASK_TO_LID;\r
+  user.attr_id = IB_MAD_ATTR_LINK_RECORD;\r
+  user.attr_offset = cl_ntoh16( ( uint16_t ) ( sizeof( record ) >> 3 ) );\r
+  user.p_attr = &record;\r
+\r
+  req.query_type = OSMV_QUERY_USER_DEFINED;\r
+  req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+  req.retry_cnt = p_osmt->opt.retry_count;\r
+  req.flags = OSM_SA_FLAGS_SYNC;\r
+  req.query_context = p_context;\r
+  req.pfn_query_cb = osmtest_query_res_cb;\r
+  req.p_query_input = &user;\r
+  req.sm_key = 0;\r
+\r
+  status = osmv_query_sa( p_osmt->h_bind, &req );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_link_rec_by_lid: ERR 007A: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  status = p_context->result.status;\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_link_rec_by_lid: ERR 007B: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    if( status == IB_REMOTE_ERROR )\r
+    {\r
+      p_mad = osm_madw_get_mad_ptr( p_context->result.p_result_madw );\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_get_link_rec_by_lid: "\r
+               "Remote error = %s\n",\r
+               ib_get_mad_status_str( p_mad ));\r
+\r
+      status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK );\r
+    }\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ * Get GUIDInfo record by LID\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_get_guidinfo_rec_by_lid( IN osmtest_t * const p_osmt,\r
+                                 IN ib_net16_t const  lid,\r
+                                 IN OUT osmtest_req_context_t * const p_context )\r
+{   \r
+  ib_api_status_t status = IB_SUCCESS;\r
+  osmv_user_query_t user;\r
+  osmv_query_req_t req;\r
+  ib_guidinfo_record_t record;\r
+  ib_mad_t *p_mad;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_get_guidinfo_rec_by_lid );\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_get_guidinfo_rec_by_lid: "\r
+             "Getting GUIDInfo record for LID 0x%02X\n",\r
+             cl_ntoh16( lid ) );\r
+  }\r
+\r
+  /*\r
+   * Do a blocking query for this record in the subnet.\r
+   * The result is returned in the result field of the caller's\r
+   * context structure.\r
+   *\r
+   * The query structures are locals.\r
+   */\r
+  memset( &req, 0, sizeof( req ) );\r
+  memset( &user, 0, sizeof( user ) );\r
+  memset( &record, 0, sizeof( record ) );\r
+\r
+  record.lid = lid;\r
+  p_context->p_osmt = p_osmt;\r
+  user.comp_mask = IB_GIR_COMPMASK_LID;\r
+  user.attr_id = IB_MAD_ATTR_GUIDINFO_RECORD;\r
+  user.attr_offset = cl_ntoh16( ( uint16_t ) ( sizeof( record ) >> 3 ) );\r
+  user.p_attr = &record;\r
+\r
+  req.query_type = OSMV_QUERY_USER_DEFINED;\r
+  req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+  req.retry_cnt = p_osmt->opt.retry_count;\r
+\r
+  req.flags = OSM_SA_FLAGS_SYNC;\r
+  req.query_context = p_context;\r
+  req.pfn_query_cb = osmtest_query_res_cb;\r
+  req.p_query_input = &user;\r
+  req.sm_key = 0;\r
+\r
+  status = osmv_query_sa( p_osmt->h_bind, &req );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_guidinfo_rec_by_lid: ERR 007C: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  status = p_context->result.status;\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_guidinfo_rec_by_lid: ERR 007D: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    if( status == IB_REMOTE_ERROR )\r
+    {\r
+      p_mad = osm_madw_get_mad_ptr( p_context->result.p_result_madw );\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_get_guidinfo_rec_by_lid: "\r
+               "Remote error = %s\n",\r
+               ib_get_mad_status_str( p_mad ));\r
+\r
+      status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK );\r
+    }\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ * Get PKeyTable record by LID\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_get_pkeytbl_rec_by_lid( IN osmtest_t * const p_osmt,\r
+                                IN ib_net16_t const  lid,\r
+                                IN ib_net64_t const  sm_key,\r
+                                IN OUT osmtest_req_context_t * const p_context )\r
+{\r
+  ib_api_status_t status = IB_SUCCESS;\r
+  osmv_user_query_t user;\r
+  osmv_query_req_t req;\r
+  ib_pkey_table_record_t record;\r
+  ib_mad_t *p_mad;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_get_pkeytbl_rec_by_lid );\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_get_pkeytbl_rec_by_lid: "\r
+             "Getting PKeyTable record for LID 0x%02X\n",\r
+             cl_ntoh16( lid ) );\r
+  }\r
+\r
+  /*\r
+   * Do a blocking query for this record in the subnet.\r
+   * The result is returned in the result field of the caller's\r
+   * context structure.\r
+   *\r
+   * The query structures are locals.\r
+   */\r
+  memset( &req, 0, sizeof( req ) );\r
+  memset( &user, 0, sizeof( user ) );\r
+  memset( &record, 0, sizeof( record ) );\r
+\r
+  record.lid = lid;\r
+  p_context->p_osmt = p_osmt;\r
+  user.comp_mask = IB_PKEY_COMPMASK_LID;\r
+  user.attr_id = IB_MAD_ATTR_PKEY_TBL_RECORD;\r
+  user.attr_offset = cl_ntoh16( ( uint16_t ) ( sizeof( record ) >> 3 ) );\r
+  user.p_attr = &record;\r
+\r
+  req.query_type = OSMV_QUERY_USER_DEFINED;\r
+  req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+  req.retry_cnt = p_osmt->opt.retry_count;\r
+\r
+  req.flags = OSM_SA_FLAGS_SYNC;\r
+  req.query_context = p_context;\r
+  req.pfn_query_cb = osmtest_query_res_cb;\r
+  req.p_query_input = &user;\r
+  req.sm_key = sm_key;\r
+\r
+  status = osmv_query_sa( p_osmt->h_bind, &req );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_pkeytbl_rec_by_lid: ERR 007E: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  status = p_context->result.status;\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_pkeytbl_rec_by_lid: ERR 007F: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    if( status == IB_REMOTE_ERROR )\r
+    {\r
+      p_mad = osm_madw_get_mad_ptr( p_context->result.p_result_madw );\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_get_pkeytbl_rec_by_lid: "\r
+               "Remote error = %s\n",\r
+               ib_get_mad_status_str( p_mad ));\r
+\r
+      status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK );\r
+    }\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ * Get LFT record by LID\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_get_lft_rec_by_lid( IN osmtest_t * const p_osmt,\r
+                            IN ib_net16_t const  lid,\r
+                            IN OUT osmtest_req_context_t * const p_context )\r
+{\r
+  ib_api_status_t status = IB_SUCCESS;\r
+  osmv_user_query_t user;\r
+  osmv_query_req_t req;\r
+  ib_lft_record_t record;\r
+  ib_mad_t *p_mad;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_get_lft_rec_by_lid );\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_get_lft_rec_by_lid: "\r
+             "Getting LFT record for LID 0x%02X\n",\r
+             cl_ntoh16( lid ) );\r
+  }\r
+\r
+  /*\r
+   * Do a blocking query for this record in the subnet.\r
+   * The result is returned in the result field of the caller's\r
+   * context structure.\r
+   *\r
+   * The query structures are locals.\r
+   */\r
+  memset( &req, 0, sizeof( req ) );\r
+  memset( &user, 0, sizeof( user ) );\r
+  memset( &record, 0, sizeof( record ) );\r
+\r
+  record.lid = lid;\r
+  p_context->p_osmt = p_osmt;\r
+  user.comp_mask = IB_LFTR_COMPMASK_LID;\r
+  user.attr_id = IB_MAD_ATTR_LFT_RECORD;\r
+  user.attr_offset = cl_ntoh16( ( uint16_t ) ( sizeof( record ) >> 3 ) );\r
+  user.p_attr = &record;\r
+\r
+  req.query_type = OSMV_QUERY_USER_DEFINED;\r
+  req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+  req.retry_cnt = p_osmt->opt.retry_count;\r
+\r
+  req.flags = OSM_SA_FLAGS_SYNC;\r
+  req.query_context = p_context;\r
+  req.pfn_query_cb = osmtest_query_res_cb;\r
+  req.p_query_input = &user;\r
+  req.sm_key = 0;\r
+\r
+  status = osmv_query_sa( p_osmt->h_bind, &req );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_lft_rec_by_lid: ERR 008A: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  status = p_context->result.status;\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_get_lft_rec_by_lid: ERR 008B: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    if( status == IB_REMOTE_ERROR )\r
+    {\r
+      p_mad = osm_madw_get_mad_ptr( p_context->result.p_result_madw );\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_get_lft_rec_by_lid: "\r
+               "Remote error = %s\n",\r
+               ib_get_mad_status_str( p_mad ));\r
+\r
+      status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK );\r
+    }\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_sminfo_record_request(\r
+        IN osmtest_t * const p_osmt,\r
+        IN OUT osmtest_req_context_t * const p_context )\r
+{\r
+  ib_api_status_t status = IB_SUCCESS;\r
+  osmv_user_query_t user;\r
+  osmv_query_req_t req;\r
+  ib_sminfo_record_t record;\r
+  ib_mad_t *p_mad;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_sminfo_record_request );\r
+\r
+  /*\r
+   * Do a blocking query for these records in the subnet.\r
+   * The result is returned in the result field of the caller's\r
+   * context structure.\r
+   *\r
+   * The query structures are locals.\r
+   */\r
+  memset( &req, 0, sizeof( req ) );\r
+  memset( &user, 0, sizeof( user ) );\r
+  memset( &record, 0, sizeof( record ) );\r
+\r
+  p_context->p_osmt = p_osmt;\r
+  user.attr_id = IB_MAD_ATTR_SMINFO_RECORD;\r
+  user.attr_offset = cl_ntoh16( ( uint16_t ) ( sizeof( record ) >> 3 ) );\r
+  user.p_attr = &record;\r
+\r
+  req.query_type = OSMV_QUERY_USER_DEFINED;\r
+  req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+  req.retry_cnt = p_osmt->opt.retry_count;\r
+\r
+  req.flags = OSM_SA_FLAGS_SYNC;\r
+  req.query_context = p_context;\r
+  req.pfn_query_cb = osmtest_query_res_cb;\r
+  req.p_query_input = &user;\r
+  req.sm_key = 0;\r
+\r
+  status = osmv_query_sa( p_osmt->h_bind, &req );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_sminfo_record_request: ERR 008C: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  status = p_context->result.status;\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_sminfo_record_request: ERR 008D: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    if( status == IB_REMOTE_ERROR )\r
+    {\r
+      p_mad = osm_madw_get_mad_ptr( p_context->result.p_result_madw );\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_sminfo_record_request: "\r
+               "Remote error = %s\n",\r
+               ib_get_mad_status_str( p_mad ));\r
+\r
+      status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK );\r
+    }\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+#endif\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_single_path_rec_lid_pair( IN osmtest_t * const p_osmt,\r
+                                           IN path_t * const p_path )\r
+{\r
+  osmtest_req_context_t context;\r
+  const ib_path_rec_t *p_rec;\r
+  cl_status_t status = IB_SUCCESS;\r
+  size_t num_recs;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_path_rec_lid_pair );\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+\r
+  status = osmtest_get_path_rec_by_lid_pair( p_osmt,\r
+                                             p_path->rec.slid,\r
+                                             p_path->rec.dlid,\r
+                                             &context );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_single_path_rec_lid_pair: ERR 0102: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  num_recs = context.result.result_cnt;\r
+  if( num_recs != 1 )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_single_path_rec_lid_pair: ERR 0103: "\r
+             "Too many records. Expected 1, received %zu\n", num_recs );\r
+\r
+    status = IB_ERROR;\r
+  }\r
+  else\r
+  {\r
+    p_rec = osmv_get_query_path_rec( context.result.p_result_madw, 0 );\r
+\r
+    status = osmtest_validate_path_data( p_osmt, p_path, p_rec );\r
+    if( status != IB_SUCCESS )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_validate_single_path_rec_lid_pair: ERR 0104: "\r
+               "osmtest_validate_path_data failed (%s)\n",\r
+               ib_get_err_str( status ) );\r
+    }\r
+  }\r
+\r
+ Exit:\r
+  /*\r
+   * Return the IB query MAD to the pool as necessary.\r
+   */\r
+  if( context.result.p_result_madw != NULL )\r
+  {\r
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+    context.result.p_result_madw = NULL;\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_single_node_rec_lid( IN osmtest_t * const p_osmt,\r
+                                      IN ib_net16_t const lid,\r
+                                      IN node_t * const p_node )\r
+{\r
+  cl_status_t status = IB_SUCCESS;\r
+  osmv_user_query_t user;\r
+  osmv_query_req_t req;\r
+  ib_node_record_t record;\r
+\r
+  osmtest_req_context_t context;\r
+  const ib_node_record_t *p_rec;\r
+  int num_recs, i;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_node_rec_lid );\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+             "osmtest_validate_single_node_rec_lid: "\r
+             "Getting NodeRecord for node with LID 0x%X\n",\r
+             cl_ntoh16( lid ) );\r
+  }\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+  memset( &req, 0, sizeof( req ) );\r
+  memset( &user, 0, sizeof( user ) );\r
+  memset( &record, 0, sizeof( record ) );\r
+\r
+  record.lid = lid;\r
+\r
+  context.p_osmt = p_osmt;\r
+  user.comp_mask = IB_NR_COMPMASK_LID;\r
+  user.attr_id = IB_MAD_ATTR_NODE_RECORD;\r
+  user.attr_offset = cl_ntoh16( (uint16_t) ( sizeof( record ) >> 3 ) );\r
+  user.p_attr = &record;\r
+\r
+  req.query_type = OSMV_QUERY_USER_DEFINED;\r
+  req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+  req.retry_cnt = p_osmt->opt.retry_count;\r
+  req.flags = OSM_SA_FLAGS_SYNC;\r
+  req.query_context = &context;\r
+  req.pfn_query_cb = osmtest_query_res_cb;\r
+  req.p_query_input = &user;\r
+  req.sm_key = 0;\r
+\r
+  status = osmv_query_sa( p_osmt->h_bind, &req );\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_single_node_rec_lid: ERR 0105: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  status = context.result.status;\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_single_node_rec_lid: ERR 0106: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+\r
+    if( status == IB_REMOTE_ERROR )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_validate_single_node_rec_lid: "\r
+               "Remote error = %s\n",\r
+               ib_get_mad_status_str( osm_madw_get_mad_ptr\r
+                                      ( context.result.p_result_madw ) ) );\r
+    }\r
+    goto Exit;\r
+  }\r
+\r
+  num_recs = context.result.result_cnt;\r
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+           "osmtest_validate_single_node_rec_lid: "\r
+           "Received %d nodes\n", num_recs);\r
+\r
+  for( i = 0; i < num_recs; i++ )\r
+  {\r
+    p_rec = osmv_get_query_node_rec( context.result.p_result_madw, i );\r
+\r
+    status = osmtest_validate_node_rec( p_osmt, p_rec );\r
+    if( status != IB_SUCCESS )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_validate_single_node_rec_lid: ERR 0107: "\r
+               "osmtest_validate_node_data failed (%s)\n",\r
+               ib_get_err_str( status ) );\r
+      goto Exit;\r
+    }\r
+  }\r
+\r
+ Exit:\r
+  /*\r
+   * Return the IB query MAD to the pool as necessary.\r
+   */\r
+  if( context.result.p_result_madw != NULL )\r
+  {\r
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+    context.result.p_result_madw = NULL;\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_single_port_rec_lid( IN osmtest_t * const p_osmt,\r
+                                      IN port_t * const p_port )\r
+{\r
+  osmtest_req_context_t context;\r
+\r
+  const ib_portinfo_record_t *p_rec;\r
+  cl_status_t status = IB_SUCCESS;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_port_rec_lid );\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+\r
+  context.p_osmt = p_osmt;\r
+  osmtest_get_port_rec_by_num( p_osmt,\r
+                               p_port->rec.lid,\r
+                               p_port->rec.port_num,\r
+                               &context);\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_single_port_rec_lid: ERR 0108: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+\r
+    goto Exit;\r
+  }\r
+\r
+  /* we should have got exactly one port */\r
+  p_rec = osmv_get_query_portinfo_rec( context.result.p_result_madw, 0);\r
+  status = osmtest_validate_port_rec( p_osmt, p_rec );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_single_port_rec_lid: ERR 0109: "\r
+             "osmtest_validate_port_data failed (%s)\n",\r
+             ib_get_err_str( status ) );\r
+  }\r
+\r
+ Exit:\r
+  /*\r
+   * Return the IB query MAD to the pool as necessary.\r
+   */\r
+  if( context.result.p_result_madw != NULL )\r
+  {\r
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+    context.result.p_result_madw = NULL;\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_single_path_rec_guid_pair( IN osmtest_t * const p_osmt,\r
+                                            IN const osmv_guid_pair_t *\r
+                                            const p_pair )\r
+{\r
+  osmtest_req_context_t context;\r
+  const ib_path_rec_t *p_rec;\r
+  cl_status_t status = IB_SUCCESS;\r
+  size_t num_recs;\r
+  osmv_query_req_t req;\r
+  uint32_t i;\r
+  boolean_t got_error = FALSE;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_path_rec_guid_pair );\r
+\r
+  memset( &req, 0, sizeof( req ) );\r
+  memset( &context, 0, sizeof( context ) );\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_single_path_rec_guid_pair: "\r
+             "\n\t\t\t\tChecking src 0x%016" PRIx64\r
+             " to dest 0x%016" PRIx64 "\n",\r
+             cl_ntoh64( p_pair->src_guid ),\r
+             cl_ntoh64( p_pair->dest_guid ) );\r
+  }\r
+\r
+  context.p_osmt = p_osmt;\r
+\r
+  req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+  req.retry_cnt = p_osmt->opt.retry_count;\r
+  req.flags = OSM_SA_FLAGS_SYNC;\r
+  req.query_context = &context;\r
+  req.pfn_query_cb = osmtest_query_res_cb;\r
+\r
+  req.query_type = OSMV_QUERY_PATH_REC_BY_PORT_GUIDS;\r
+  req.p_query_input = p_pair;\r
+  req.sm_key = 0;\r
+\r
+  status = osmv_query_sa( p_osmt->h_bind, &req );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_single_path_rec_guid_pair: ERR 0110: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  status = context.result.status;\r
+\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_single_path_rec_guid_pair: ERR 0111: "\r
+             "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+\r
+    if( status == IB_REMOTE_ERROR )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_validate_single_path_rec_guid_pair: "\r
+               "Remote error = %s\n",\r
+               ib_get_mad_status_str( osm_madw_get_mad_ptr\r
+                                      ( context.result.p_result_madw ) ) );\r
+    }\r
+    goto Exit;\r
+  }\r
+\r
+  num_recs = context.result.result_cnt;\r
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+           "osmtest_validate_single_path_rec_guid_pair: %zu records\n",\r
+           num_recs);\r
+\r
+  for( i = 0; i < num_recs; i++ )\r
+  {\r
+    p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i );\r
+\r
+    /*\r
+     * Make sure the GUID values are correct\r
+     */\r
+    if( p_rec->dgid.unicast.interface_id != p_pair->dest_guid )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_validate_single_path_rec_guid_pair: ERR 0112: "\r
+               "Destination GUID mismatch\n"\r
+               "\t\t\t\texpected 0x%016" PRIx64\r
+               ", received 0x%016" PRIx64 "\n",\r
+               cl_ntoh64( p_pair->dest_guid ),\r
+               cl_ntoh64( p_rec->dgid.unicast.interface_id ) );\r
+      got_error = TRUE;\r
+    }\r
+\r
+    if( p_rec->sgid.unicast.interface_id != p_pair->src_guid )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_validate_single_path_rec_guid_pair: ERR 0113: "\r
+               "Source GUID mismatch\n"\r
+               "\t\t\t\texpected 0x%016" PRIx64\r
+               ", received 0x%016" PRIx64 ".\n",\r
+               cl_ntoh64( p_pair->src_guid ),\r
+               cl_ntoh64( p_rec->sgid.unicast.interface_id ) );\r
+      got_error = TRUE;\r
+    }\r
+\r
+    status = osmtest_validate_path_rec( p_osmt, p_rec );\r
+    if( status != IB_SUCCESS )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_validate_single_path_rec_guid_pair: ERR 0114: "\r
+               "osmtest_validate_path_rec failed (%s)\n",\r
+               ib_get_err_str( status ) );\r
+      got_error = TRUE;\r
+    }\r
+    if( got_error || (status != IB_SUCCESS) )\r
+    {\r
+      osm_dump_path_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );\r
+      if( status == IB_SUCCESS )\r
+         status = IB_ERROR;\r
+      goto Exit;\r
+    }\r
+  }\r
+\r
+ Exit:\r
+  /*\r
+   * Return the IB query MAD to the pool as necessary.\r
+   */\r
+  if( context.result.p_result_madw != NULL )\r
+  {\r
+    osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+    context.result.p_result_madw = NULL;\r
+  }\r
+\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_single_path_recs( IN osmtest_t * const p_osmt )\r
+{\r
+  path_t *p_path;\r
+  cl_status_t status = IB_SUCCESS;\r
+  const cl_qmap_t *p_path_tbl;\r
+/* We skip node to node path record validation since it might contains \r
+   NONEXISTENT PATHS, i.e. when using UPDN */\r
+  osmv_guid_pair_t guid_pair;\r
+  uint16_t cnt;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_path_recs );\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_validate_single_path_recs: "\r
+             "Validating individual path record queries\n" );\r
+  }\r
+  p_path_tbl = &p_osmt->exp_subn.path_tbl;\r
+\r
+  osmtest_prepare_db( p_osmt );\r
+\r
+  /*\r
+   * Walk the list of all path records, and ask for each one\r
+   * specifically.  Make sure we get it.\r
+   */\r
+  cnt = 0;\r
+  p_path = ( path_t * ) cl_qmap_head( p_path_tbl );\r
+  while( p_path != ( path_t * ) cl_qmap_end( p_path_tbl ) )\r
+  {\r
+    status = osmtest_validate_single_path_rec_lid_pair( p_osmt, p_path );\r
+    if( status != IB_SUCCESS )\r
+      goto Exit;\r
+    cnt++;\r
+    p_path = ( path_t * ) cl_qmap_next( &p_path->map_item );\r
+  }\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_validate_single_path_recs: "\r
+             "Total of %u path records validated using LID based query\n", cnt );\r
+  }\r
+\r
+  status = osmtest_check_missing_paths( p_osmt );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_single_path_recs: ERR 0115: "\r
+             "osmtest_check_missing_paths failed (%s)\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  /*\r
+   * Do the whole thing again with port GUID pairs.\r
+   * Note that multiple path records may be returned\r
+   * for each guid pair if LMC > 0.\r
+   */\r
+  osmtest_prepare_db( p_osmt );\r
+  cnt = 0;\r
+  p_path = ( path_t * ) cl_qmap_head( p_path_tbl );\r
+  while( p_path != ( path_t * ) cl_qmap_end( p_path_tbl ) )\r
+  {\r
+    guid_pair.src_guid = p_path->rec.sgid.unicast.interface_id;\r
+    guid_pair.dest_guid = p_path->rec.dgid.unicast.interface_id;\r
+    status = osmtest_validate_single_path_rec_guid_pair( p_osmt,\r
+                                                        &guid_pair );\r
+    if( status != IB_SUCCESS )\r
+      goto Exit;\r
+    cnt++;\r
+    p_path = ( path_t * ) cl_qmap_next( &p_path->map_item );\r
+  }\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_validate_single_path_recs: "\r
+             "Total of %u path records validated using GUID based query\n", cnt );\r
+  }\r
+\r
+  status = osmtest_check_missing_paths( p_osmt );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_single_path_recs: ERR 0116: "\r
+             "osmtest_check_missing_paths failed (%s)\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_single_node_recs( IN osmtest_t * const p_osmt )\r
+{\r
+  node_t *p_node;\r
+  cl_status_t status = IB_SUCCESS;\r
+  const cl_qmap_t *p_node_lid_tbl;\r
+  uint16_t cnt = 0;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_node_recs );\r
+\r
+  p_node_lid_tbl = &p_osmt->exp_subn.node_lid_tbl;\r
+\r
+  osmtest_prepare_db( p_osmt );\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_validate_single_node_recs: "\r
+             "Validating individual node record queries\n" );\r
+  }\r
+\r
+  /*\r
+   * Walk the list of all node records, and ask for each one\r
+   * specifically.  Make sure we get it.\r
+   */\r
+  p_node = ( node_t * ) cl_qmap_head( p_node_lid_tbl );\r
+  while( p_node != ( node_t * ) cl_qmap_end( p_node_lid_tbl ) )\r
+  {\r
+    status = osmtest_validate_single_node_rec_lid( p_osmt,\r
+                                                   (ib_net16_t) cl_qmap_key ((cl_map_item_t*)p_node),\r
+                                                   p_node );\r
+    if( status != IB_SUCCESS )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_validate_single_node_recs: ERR 011A: "\r
+               "osmtest_validate_single_node_rec_lid (%s)\n",\r
+               ib_get_err_str( status ) );\r
+      goto Exit;\r
+    }\r
+    cnt++;\r
+    p_node = ( node_t * ) cl_qmap_next( &p_node->map_item );\r
+  }\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_validate_single_node_recs: "\r
+             "Total of %u node records validated\n", cnt );\r
+  }\r
+\r
+  status = osmtest_check_missing_nodes( p_osmt );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_single_node_recs: ERR 0117: "\r
+             "osmtest_check_missing_nodes (%s)\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_single_port_recs( IN osmtest_t * const p_osmt )\r
+{\r
+  port_t *p_port;\r
+  cl_status_t status = IB_SUCCESS;\r
+  const cl_qmap_t *p_port_key_tbl;\r
+  uint16_t cnt = 0;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_port_recs );\r
+\r
+  p_port_key_tbl = &p_osmt->exp_subn.port_key_tbl;\r
+\r
+  osmtest_prepare_db( p_osmt );\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_validate_single_port_recs: "\r
+             "Validating individual port record queries\n" );\r
+  }\r
+\r
+  /*\r
+   * Walk the list of all port records, and ask for each one\r
+   * specifically.  Make sure we get it.\r
+   */\r
+  p_port = ( port_t * ) cl_qmap_head( p_port_key_tbl );\r
+  while( p_port != ( port_t * ) cl_qmap_end( p_port_key_tbl ) )\r
+  {\r
+    status = osmtest_validate_single_port_rec_lid( p_osmt, p_port );\r
+    if( status != IB_SUCCESS )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_validate_single_port_recs: ERR 011B: "\r
+               "osmtest_validate_single_port_rec_lid (%s)\n",\r
+               ib_get_err_str( status ) );\r
+      goto Exit;\r
+    }\r
+    cnt++;\r
+    p_port = ( port_t * ) cl_qmap_next( &p_port->map_item );\r
+  }\r
+\r
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+             "osmtest_validate_single_port_recs: "\r
+             "Total of %u port records validated\n", cnt );\r
+  }\r
+\r
+  status = osmtest_check_missing_ports( p_osmt );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_validate_single_port_recs: ERR 0118: "\r
+             "osmtest_check_missing_paths failed (%s)\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_against_db( IN osmtest_t * const p_osmt )\r
+{\r
+  ib_api_status_t status = IB_SUCCESS;\r
+  ib_gid_t portgid, mgid;\r
+#ifdef VENDOR_RMPP_SUPPORT\r
+  ib_net64_t sm_key;\r
+  ib_net16_t test_lid;\r
+  uint8_t lmc;\r
+  osmtest_req_context_t context;\r
+#ifdef DUAL_SIDED_RMPP\r
+  osmv_multipath_req_t request;\r
+#endif\r
+#endif\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_against_db );\r
+\r
+#ifdef VENDOR_RMPP_SUPPORT\r
+  status = osmtest_validate_all_node_recs( p_osmt );\r
+  if( status != IB_SUCCESS )\r
+    goto Exit;\r
+#endif\r
+\r
+  status = osmtest_validate_single_node_recs( p_osmt );\r
+  if( status != IB_SUCCESS )\r
+    goto Exit;\r
+\r
+  /* Exercise SA PathRecord multicast destination code */\r
+  memset( &context, 0, sizeof( context ) );\r
+  ib_gid_set_default( &portgid, portguid );\r
+  /* Set IPoIB broadcast MGID */\r
+  mgid.unicast.prefix = CL_HTON64(0xff12401bffff0000ULL);\r
+  mgid.unicast.interface_id = CL_HTON64(0x00000000ffffffffULL);\r
+  /* Can't check status as don't know whether port is running IPoIB */\r
+  osmtest_get_path_rec_by_gid_pair( p_osmt, portgid, mgid, &context);\r
+\r
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)\r
+  memset( &context, 0, sizeof( context ) );\r
+  memset( &request, 0, sizeof( request ) );\r
+  request.comp_mask = IB_MPR_COMPMASK_SGIDCOUNT | IB_MPR_COMPMASK_DGIDCOUNT;\r
+  request.sgid_count = 1;\r
+  request.dgid_count = 1;\r
+  ib_gid_set_default( &request.gids[0], portguid );\r
+  ib_gid_set_default( &request.gids[1], portguid );\r
+  status = osmtest_get_multipath_rec( p_osmt, &request, &context );\r
+  if( status != IB_SUCCESS )\r
+    goto Exit;\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+  memset( &request, 0, sizeof( request ) );\r
+\r
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+           "osmtest_get_multipath_rec: " EXPECTING_ERRORS_START "\n" );\r
+  status = osmtest_get_multipath_rec( p_osmt, &request, &context );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+     osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+              "osmtest_get_multipath_rec: "\r
+              "Got error %s\n", ib_get_err_str(status) );\r
+  }\r
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+           "osmtest_get_multipath_rec: " EXPECTING_ERRORS_END "\n" );\r
+\r
+  if( status == IB_SUCCESS )\r
+  {\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+  memset( &request, 0, sizeof( request ) );\r
+  request.comp_mask = IB_MPR_COMPMASK_SGIDCOUNT;\r
+  request.sgid_count = 1;\r
+  ib_gid_set_default( &request.gids[0], portguid );\r
+\r
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+           "osmtest_get_multipath_rec: " EXPECTING_ERRORS_START "\n" );\r
+  status = osmtest_get_multipath_rec( p_osmt, &request, &context );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+     osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+              "osmtest_get_multipath_rec: "\r
+              "Got error %s\n", ib_get_err_str(status) );\r
+  }\r
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+           "osmtest_get_multipath_rec: " EXPECTING_ERRORS_END "\n" );\r
+\r
+  if( status == IB_SUCCESS )\r
+  {\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+  memset( &request, 0, sizeof( request ) );\r
+  request.comp_mask = IB_MPR_COMPMASK_SGIDCOUNT | IB_MPR_COMPMASK_DGIDCOUNT;\r
+  request.sgid_count = 1;\r
+  request.dgid_count = 1;\r
+  ib_gid_set_default( &request.gids[0], portguid );\r
+  /* Set IPoIB broadcast MGID */\r
+  request.gids[1].unicast.prefix = CL_HTON64(0xff12401bffff0000ULL);\r
+  request.gids[1].unicast.interface_id = CL_HTON64(0x00000000ffffffffULL);\r
+\r
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+           "osmtest_get_multipath_rec: " EXPECTING_ERRORS_START "\n" );\r
+  status = osmtest_get_multipath_rec( p_osmt, &request, &context );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+     osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+              "osmtest_get_multipath_rec: "\r
+              "Got error %s\n", ib_get_err_str(status) );\r
+  }\r
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+           "osmtest_get_multipath_rec: " EXPECTING_ERRORS_END "\n" );\r
+\r
+  if( status == IB_SUCCESS )\r
+  {\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+  request.comp_mask = IB_MPR_COMPMASK_SGIDCOUNT | IB_MPR_COMPMASK_DGIDCOUNT;\r
+  request.sgid_count = 1;\r
+  request.dgid_count = 1;\r
+  /* Set IPoIB broadcast MGID */\r
+  request.gids[0].unicast.prefix = CL_HTON64(0xff12401bffff0000ULL);\r
+  request.gids[0].unicast.interface_id = CL_HTON64(0x00000000ffffffffULL);\r
+  ib_gid_set_default( &request.gids[1], portguid );\r
+\r
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+           "osmtest_get_multipath_rec: " EXPECTING_ERRORS_START "\n" );\r
+  status = osmtest_get_multipath_rec( p_osmt, &request, &context );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+     osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+              "osmtest_get_multipath_rec: "\r
+              "Got error %s\n", ib_get_err_str(status) );\r
+  }\r
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+           "osmtest_get_multipath_rec: " EXPECTING_ERRORS_END "\n" );\r
+\r
+  if( status == IB_SUCCESS )\r
+  {\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+  memset( &request, 0, sizeof( request ) );\r
+  request.comp_mask = IB_MPR_COMPMASK_SGIDCOUNT | IB_MPR_COMPMASK_DGIDCOUNT |\r
+                      IB_MPR_COMPMASK_NUMBPATH;\r
+  request.sgid_count = 2;\r
+  request.dgid_count = 2;\r
+  request.num_path = 2;\r
+  ib_gid_set_default( &request.gids[0], portguid );\r
+  ib_gid_set_default( &request.gids[1], portguid );\r
+  ib_gid_set_default( &request.gids[2], portguid );\r
+  ib_gid_set_default( &request.gids[3], portguid );\r
+  status = osmtest_get_multipath_rec( p_osmt, &request, &context );\r
+  if( status != IB_SUCCESS )\r
+    goto Exit;\r
+#endif\r
+\r
+#ifdef VENDOR_RMPP_SUPPORT\r
+  /* GUIDInfoRecords */\r
+  status = osmtest_validate_all_guidinfo_recs( p_osmt );\r
+  if( status != IB_SUCCESS )\r
+    goto Exit;\r
+\r
+  /* If LMC > 0, test non base LID SA PortInfoRecord request */\r
+  status = osmtest_get_local_port_lmc( p_osmt, p_osmt->local_port.lid, &lmc );\r
+  if ( status != IB_SUCCESS )\r
+    goto Exit;\r
+\r
+  if (lmc != 0)\r
+  {\r
+    status = osmtest_get_local_port_lmc( p_osmt, p_osmt->local_port.lid + 1, NULL );\r
+    if ( status != IB_SUCCESS )\r
+      goto Exit;\r
+  }\r
+\r
+  status = osmtest_get_local_port_lmc( p_osmt, 0xffff, NULL );\r
+  if ( status != IB_SUCCESS )\r
+    goto Exit;\r
+\r
+  test_lid = cl_ntoh16( p_osmt->local_port.lid );\r
+\r
+  /* More GUIDInfo Record tests */\r
+  memset( &context, 0, sizeof( context ) ); \r
+  status = osmtest_get_guidinfo_rec_by_lid( p_osmt, test_lid, &context );\r
+  if ( status != IB_SUCCESS )\r
+    goto Exit;\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+  status = osmtest_get_guidinfo_rec_by_lid( p_osmt, 0xffff, &context );\r
+  if ( status != IB_SUCCESS )\r
+    goto Exit;\r
+\r
+  /* Some PKeyTable Record tests */\r
+  sm_key = OSM_DEFAULT_SM_KEY;\r
+  memset( &context, 0, sizeof( context ) );\r
+  status = osmtest_get_pkeytbl_rec_by_lid( p_osmt, test_lid, sm_key, &context );\r
+  if ( status != IB_SUCCESS )\r
+    goto Exit;\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+\r
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+           "osmtest_get_multipath_rec: " EXPECTING_ERRORS_START "\n" );\r
+  status = osmtest_get_pkeytbl_rec_by_lid( p_osmt, test_lid, 0, &context );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+     osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+              "osmtest_get_multipath_rec: "\r
+              "Got error %s\n", ib_get_err_str(status) );\r
+  }\r
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+           "osmtest_get_multipath_rec: " EXPECTING_ERRORS_END "\n" );\r
+\r
+  if( status == IB_SUCCESS )\r
+  {\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  memset( &context, 0, sizeof( context ) );\r
+  status = osmtest_get_pkeytbl_rec_by_lid( p_osmt, 0xffff, sm_key, &context );\r
+  if ( status != IB_SUCCESS )\r
+    goto Exit;\r
+\r
+  /* LFT Record test */\r
+  memset( &context, 0, sizeof( context ) );\r
+  status = osmtest_get_lft_rec_by_lid( p_osmt, test_lid, &context );\r
+  if ( status != IB_SUCCESS )\r
+    goto Exit;\r
+\r
+  /* Some LinkRecord tests */\r
+  /* FromLID */\r
+  memset( &context, 0, sizeof( context ) );\r
+  status = osmtest_get_link_rec_by_lid( p_osmt, test_lid, 0, &context );\r
+  if ( status != IB_SUCCESS )\r
+    goto Exit;\r
+\r
+  /* ToLID */\r
+  memset( &context, 0, sizeof( context ) );\r
+  status = osmtest_get_link_rec_by_lid( p_osmt, 0, test_lid, &context );\r
+  if ( status != IB_SUCCESS )\r
+    goto Exit;\r
+\r
+  /* FromLID & ToLID */\r
+  memset( &context, 0, sizeof( context ) );\r
+  status = osmtest_get_link_rec_by_lid( p_osmt, test_lid, test_lid, &context );\r
+  if ( status != IB_SUCCESS )\r
+    goto Exit;\r
+\r
+  /* NodeRecord test */\r
+  memset( &context, 0, sizeof( context ) );\r
+  status = osmtest_get_node_rec_by_lid( p_osmt, 0xffff , &context );\r
+  if ( status != IB_SUCCESS )\r
+    goto Exit;\r
+\r
+  /* SMInfoRecord test */\r
+  memset( &context, 0, sizeof( context ) );\r
+  status = osmtest_sminfo_record_request( p_osmt, &context );\r
+  if ( status != IB_SUCCESS )\r
+    goto Exit;\r
+\r
+  if (lmc != 0)\r
+  {\r
+    test_lid = cl_ntoh16( p_osmt->local_port.lid + 1 );\r
+\r
+    /* Another GUIDInfo Record test */\r
+    memset( &context, 0, sizeof( context ) );\r
+    status = osmtest_get_guidinfo_rec_by_lid( p_osmt, test_lid, &context );\r
+    if ( status != IB_SUCCESS )\r
+      goto Exit;\r
+\r
+    /* Another PKeyTable Record test */\r
+    memset( &context, 0, sizeof( context ) );\r
+    status = osmtest_get_pkeytbl_rec_by_lid( p_osmt, test_lid, sm_key, &context );\r
+    if ( status != IB_SUCCESS )\r
+      goto Exit;\r
+\r
+    /* Another LFT Record test */\r
+    memset( &context, 0, sizeof( context ) );\r
+    status = osmtest_get_lft_rec_by_lid( p_osmt, test_lid, &context );\r
+    if ( status != IB_SUCCESS )\r
+      goto Exit;\r
+\r
+    /* More LinkRecord tests */\r
+    /* FromLID */\r
+    memset( &context, 0, sizeof( context ) );\r
+    status = osmtest_get_link_rec_by_lid( p_osmt, test_lid, 0, &context );\r
+    if ( status != IB_SUCCESS )\r
+      goto Exit;\r
+\r
+    /* ToLID */\r
+    memset( &context, 0, sizeof( context ) );\r
+    status = osmtest_get_link_rec_by_lid( p_osmt, 0, test_lid, &context );\r
+    if ( status != IB_SUCCESS )\r
+      goto Exit;\r
+\r
+    /* Another NodeRecord test */\r
+    memset( &context, 0, sizeof( context ) );\r
+    status = osmtest_get_node_rec_by_lid( p_osmt, test_lid, &context );\r
+    if ( status != IB_SUCCESS )\r
+      goto Exit;\r
+  }\r
+\r
+  /* PathRecords */\r
+  if (! p_osmt->opt.ignore_path_records)\r
+  {\r
+    status = osmtest_validate_all_path_recs( p_osmt );\r
+    if( status != IB_SUCCESS )\r
+      goto Exit;\r
+\r
+    if (lmc != 0)\r
+    {\r
+      memset( &context, 0, sizeof( context ) );\r
+      status = osmtest_get_path_rec_by_lid_pair( p_osmt, test_lid,\r
+                                                 test_lid, &context );\r
+      if (status != IB_SUCCESS )\r
+        goto Exit;\r
+\r
+      memset( &context, 0, sizeof( context ) );\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_get_path_rec_by_lid_pair: " EXPECTING_ERRORS_START "\n" );\r
+      status = osmtest_get_path_rec_by_lid_pair( p_osmt, 0xffff,\r
+                                                 0xffff, &context );\r
+      if( status != IB_SUCCESS )\r
+      {\r
+         osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                  "osmtest_get_path_rec_by_lid_pair: "\r
+                  "Got error %s\n", ib_get_err_str(status) );\r
+      }\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_get_path_rec_by_lid_pair: " EXPECTING_ERRORS_END "\n" );\r
+\r
+      if( status == IB_SUCCESS )\r
+      {\r
+        status = IB_ERROR;\r
+        goto Exit;\r
+      }\r
+\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_get_path_rec_by_lid_pair: " EXPECTING_ERRORS_START "\n" );\r
+\r
+      status = osmtest_get_path_rec_by_lid_pair( p_osmt, test_lid,\r
+                                                 0xffff, &context );\r
+      if( status != IB_SUCCESS )\r
+      {\r
+         osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                  "osmtest_get_path_rec_by_lid_pair: "\r
+                  "Got error %s\n", ib_get_err_str(status) );\r
+      }\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_get_path_rec_by_lid_pair: " EXPECTING_ERRORS_END "\n" );\r
+\r
+      if( status == IB_SUCCESS )\r
+      {\r
+        status = IB_ERROR;\r
+        goto Exit;\r
+      }\r
+    }\r
+  }\r
+#endif\r
+\r
+  status = osmtest_validate_single_port_recs( p_osmt );\r
+  if( status != IB_SUCCESS )\r
+    goto Exit;\r
+\r
+  if (! p_osmt->opt.ignore_path_records)\r
+  {\r
+    status = osmtest_validate_single_path_recs( p_osmt );\r
+    if( status != IB_SUCCESS )\r
+      goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static const osmtest_token_t *\r
+str_get_token( IN char *const p_str )\r
+{\r
+  const osmtest_token_t *p_tok;\r
+  uint32_t index = 0;\r
+\r
+  p_tok = &token_array[index];\r
+\r
+  while( p_tok->val != OSMTEST_TOKEN_UNKNOWN )\r
+  {\r
+    if( strnicmp( p_str, p_tok->str, p_tok->str_size ) == 0 )\r
+      return ( p_tok );\r
+\r
+    p_tok = &token_array[++index];\r
+  }\r
+\r
+  return ( NULL );\r
+}\r
+\r
+/**********************************************************************\r
+   Returns true if not whitespace character encountered before EOL.\r
+**********************************************************************/\r
+static boolean_t\r
+str_skip_white( IN char line[],\r
+                IN OUT uint32_t * const p_offset )\r
+{\r
+  while( ( ( line[*p_offset] == '\t' ) ||\r
+           ( line[*p_offset] == ' ' ) ) &&\r
+         ( line[*p_offset] != '\n' ) && ( line[*p_offset] != '\0' ) )\r
+  {\r
+    ++*p_offset;\r
+  }\r
+\r
+  if( ( line[*p_offset] == '\n' ) || ( line[*p_offset] == '\0' ) )\r
+    return ( FALSE );\r
+  else\r
+    return ( TRUE );\r
+}\r
+\r
+/**********************************************************************\r
+   Returns true if not whitespace character encountered before EOL.\r
+**********************************************************************/\r
+static void\r
+str_skip_token( IN char line[],\r
+                IN OUT uint32_t * const p_offset )\r
+{\r
+  while( ( line[*p_offset] != '\t' ) &&\r
+         ( line[*p_offset] != ' ' ) && ( line[*p_offset] != '\0' ) )\r
+  {\r
+    ++*p_offset;\r
+  }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_parse_node( IN osmtest_t * const p_osmt,\r
+                    IN FILE * const fh,\r
+                    IN OUT uint32_t * const p_line_num )\r
+{\r
+  ib_api_status_t status = IB_SUCCESS;\r
+  uint32_t offset;\r
+  char line[OSMTEST_MAX_LINE_LEN];\r
+  boolean_t done = FALSE;\r
+  node_t *p_node;\r
+  node_t *p_guid_node;\r
+  const osmtest_token_t *p_tok;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_parse_node );\r
+\r
+  p_node = node_new(  );\r
+  CL_ASSERT( p_node != NULL );\r
+\r
+  /*\r
+   * Parse the inventory file and create the database.\r
+   */\r
+  while( !done )\r
+  {\r
+    if( fgets( line, OSMTEST_MAX_LINE_LEN, fh ) == NULL )\r
+    {\r
+      /*\r
+       * End of file in the middle of a definition.\r
+       */\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_parse_node: ERR 0119: "\r
+               "Unexpected end of file\n" );\r
+      status = IB_ERROR;\r
+      goto Exit;\r
+    }\r
+\r
+    ++*p_line_num;\r
+\r
+    /*\r
+     * Skip whitespace\r
+     */\r
+    offset = 0;\r
+    if( !str_skip_white( line, &offset ) )\r
+      continue;       /* whole line was whitespace */\r
+\r
+    p_tok = str_get_token( &line[offset] );\r
+    if( p_tok == NULL )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_parse_node: ERR 0120: "\r
+               "Ignoring line %u with unknown token: %s\n",\r
+               *p_line_num, &line[offset] );\r
+      continue;\r
+    }\r
+\r
+    if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+               "osmtest_parse_node: "\r
+               "Found '%s' (line %u)\n", p_tok->str, *p_line_num );\r
+    }\r
+\r
+    str_skip_token( line, &offset );\r
+\r
+    switch ( p_tok->val )\r
+    {\r
+      case OSMTEST_TOKEN_COMMENT:\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_LID:\r
+        p_node->comp.lid = 0xFFFF;\r
+        p_node->rec.lid =\r
+          cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_node: "\r
+                   "lid = 0x%X\n", cl_ntoh16( p_node->rec.lid ) );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_BASE_VERSION:\r
+        p_node->comp.node_info.base_version = 0xFF;\r
+        p_node->rec.node_info.base_version =\r
+          ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_node: "\r
+                   "base_version = 0x%X\n",\r
+                   p_node->rec.node_info.base_version );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_CLASS_VERSION:\r
+        p_node->comp.node_info.class_version = 0xFF;\r
+        p_node->rec.node_info.class_version =\r
+          ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_node: "\r
+                   "class_version = 0x%X\n",\r
+                   p_node->rec.node_info.class_version );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_NODE_TYPE:\r
+        p_node->comp.node_info.node_type = 0xFF;\r
+        p_node->rec.node_info.node_type =\r
+          ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_node: "\r
+                   "node_type = 0x%X\n",\r
+                   p_node->rec.node_info.node_type );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_NUM_PORTS:\r
+        p_node->comp.node_info.num_ports = 0xFF;\r
+        p_node->rec.node_info.num_ports =\r
+          ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_node: "\r
+                   "num_ports = 0x%X\n",\r
+                   p_node->rec.node_info.num_ports );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_SYS_GUID:\r
+        p_node->comp.node_info.sys_guid = 0xFFFFFFFFFFFFFFFFULL;\r
+        p_node->rec.node_info.sys_guid =\r
+          cl_hton64( strtoull( &line[offset], NULL, 0 ) );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_node: "\r
+                   "sys_guid = 0x%016" PRIx64 "\n",\r
+                   cl_ntoh64( p_node->rec.node_info.sys_guid ) );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_NODE_GUID:\r
+        p_node->comp.node_info.node_guid = 0xFFFFFFFFFFFFFFFFULL;\r
+        p_node->rec.node_info.node_guid =\r
+          cl_hton64( strtoull( &line[offset], NULL, 0 ) );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_node: "\r
+                   "node_guid = 0x%016" PRIx64 "\n",\r
+                   cl_ntoh64( p_node->rec.node_info.node_guid ) );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_PORT_GUID:\r
+        p_node->comp.node_info.port_guid = 0xFFFFFFFFFFFFFFFFULL;\r
+        p_node->rec.node_info.port_guid =\r
+          cl_hton64( strtoull( &line[offset], NULL, 0 ) );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_node: "\r
+                   "port_guid = 0x%016" PRIx64 "\n",\r
+                   cl_ntoh64( p_node->rec.node_info.port_guid ) );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_PARTITION_CAP:\r
+        p_node->comp.node_info.partition_cap = 0xFFFF;\r
+        p_node->rec.node_info.partition_cap = cl_hton16( ( uint16_t )\r
+                                                         strtoul( &line[offset],\r
+                                                                  NULL, 0 ) );\r
+       if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+       {\r
+         osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                  "osmtest_parse_node: "\r
+                  "partition_cap = 0x%X\n",\r
+                  cl_ntoh16( p_node->rec.node_info.partition_cap ) );\r
+       }\r
+       break;\r
+\r
+     case OSMTEST_TOKEN_DEVICE_ID:\r
+       p_node->comp.node_info.device_id = 0xFFFF;\r
+       p_node->rec.node_info.device_id = cl_hton16( ( uint16_t )\r
+                                                    strtoul( &line[offset],\r
+                                                             NULL, 0 ) );\r
+       if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+       {\r
+         osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                  "osmtest_parse_node: "\r
+                  "device_id = 0x%X\n",\r
+                  cl_ntoh16( p_node->rec.node_info.device_id ) );\r
+       }\r
+       break;\r
+\r
+     case OSMTEST_TOKEN_REVISION:\r
+       p_node->comp.node_info.revision = 0xFFFFFFFF;\r
+       p_node->rec.node_info.revision =\r
+         cl_hton32( strtoul( &line[offset], NULL, 0 ) );\r
+       if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+       {\r
+         osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                  "osmtest_parse_node: "\r
+                  "revision = 0x%X\n",\r
+                  cl_ntoh32( p_node->rec.node_info.revision ) );\r
+       }\r
+       break;\r
+\r
+     case OSMTEST_TOKEN_PORT_NUM:\r
+       p_node->comp.node_info.port_num_vendor_id |= IB_NODE_INFO_PORT_NUM_MASK;\r
+       p_node->rec.node_info.port_num_vendor_id |=\r
+         ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+       if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+       {\r
+         osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                  "osmtest_parse_node: "\r
+                  "local_port_num = 0x%X\n",\r
+                  ib_node_info_get_local_port_num( &p_node->rec.\r
+                                                   node_info ) );\r
+       }\r
+       break;\r
+\r
+     case OSMTEST_TOKEN_VENDOR_ID:\r
+       p_node->comp.node_info.port_num_vendor_id |= IB_NODE_INFO_VEND_ID_MASK;\r
+       p_node->rec.node_info.port_num_vendor_id |=\r
+         cl_hton32( strtoul( &line[offset], NULL, 0 ) );\r
+       if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+       {\r
+         osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                  "osmtest_parse_node: "\r
+                  "vendor_id = 0x%X\n",\r
+                  cl_ntoh32( ib_node_info_get_vendor_id\r
+                             ( &p_node->rec.node_info ) ) );\r
+       }\r
+       break;\r
+\r
+     case OSMTEST_TOKEN_END:\r
+       done = TRUE;\r
+       break;\r
+\r
+     default:\r
+       osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                "osmtest_parse_node: ERR 0121: "\r
+                "Ignoring line %u with unknown token: %s\n",\r
+                *p_line_num, &line[offset] );\r
+\r
+       break;\r
+     }\r
+  }\r
+\r
+  /*\r
+   * Make sure the user specified enough information, then\r
+   * add this object to the database.\r
+   */\r
+  if( p_node->comp.lid == 0 )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_parse_node: ERR 0122: "\r
+             "LID must be specified for defined nodes\n" );\r
+    node_delete( p_node );\r
+    goto Exit;\r
+  }\r
+\r
+  cl_qmap_insert( &p_osmt->exp_subn.node_lid_tbl,\r
+                  p_node->rec.lid, &p_node->map_item );\r
+\r
+  p_guid_node = node_new(  );\r
+  CL_ASSERT( p_node != NULL );\r
+\r
+  *p_guid_node = *p_node;\r
+\r
+  cl_qmap_insert( &p_osmt->exp_subn.node_guid_tbl,\r
+                  p_guid_node->rec.node_info.node_guid,\r
+                  &p_guid_node->map_item );\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_parse_port( IN osmtest_t * const p_osmt,\r
+                    IN FILE * const fh,\r
+                    IN OUT uint32_t * const p_line_num )\r
+{\r
+  ib_api_status_t status = IB_SUCCESS;\r
+  uint32_t offset;\r
+  char line[OSMTEST_MAX_LINE_LEN];\r
+  boolean_t done = FALSE;\r
+  port_t *p_port;\r
+  const osmtest_token_t *p_tok;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_parse_port );\r
+\r
+  p_port = port_new(  );\r
+  CL_ASSERT( p_port != NULL );\r
+\r
+  /*\r
+   * Parse the inventory file and create the database.\r
+   */\r
+  while( !done )\r
+  {\r
+    if( fgets( line, OSMTEST_MAX_LINE_LEN, fh ) == NULL )\r
+    {\r
+      /*\r
+       * End of file in the middle of a definition.\r
+       */\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_parse_port: ERR 0123: "\r
+               "Unexpected end of file\n" );\r
+      status = IB_ERROR;\r
+      goto Exit;\r
+    }\r
+\r
+    ++*p_line_num;\r
+\r
+    /*\r
+     * Skip whitespace\r
+     */\r
+    offset = 0;\r
+    if( !str_skip_white( line, &offset ) )\r
+      continue;       /* whole line was whitespace */\r
+\r
+    p_tok = str_get_token( &line[offset] );\r
+    if( p_tok == NULL )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_parse_port: ERR 0124: "\r
+               "Ignoring line %u with unknown token: %s\n",\r
+               *p_line_num, &line[offset] );\r
+      continue;\r
+    }\r
+\r
+    if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+               "osmtest_parse_port: "\r
+               "Found '%s' (line %u)\n", p_tok->str, *p_line_num );\r
+    }\r
+\r
+    str_skip_token( line, &offset );\r
+\r
+    switch ( p_tok->val )\r
+    {\r
+      case OSMTEST_TOKEN_COMMENT:\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_LID:\r
+        p_port->comp.lid = 0xFFFF;\r
+        p_port->rec.lid =\r
+          cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "lid = 0x%X\n", cl_ntoh16( p_port->rec.lid ) );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_PORT_NUM:\r
+        p_port->comp.port_num = 0xFF;\r
+        p_port->rec.port_num =\r
+          ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "port_num = 0x%u\n",\r
+                   p_port->rec.port_num );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_MKEY:\r
+        p_port->comp.port_info.m_key = 0xFFFFFFFFFFFFFFFFULL;\r
+        p_port->rec.port_info.m_key =\r
+          cl_hton64( strtoull( &line[offset], NULL, 0 ) );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "m_key = 0x%016" PRIx64 "\n",\r
+                   cl_ntoh64( p_port->rec.port_info.m_key ) );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_SUBN_PREF:\r
+        p_port->comp.port_info.subnet_prefix = 0xFFFFFFFFFFFFFFFFULL;\r
+        p_port->rec.port_info.subnet_prefix =\r
+          cl_hton64( strtoull( &line[offset], NULL, 0 ) );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "subnet_prefix = 0x%016" PRIx64 "\n",\r
+                   cl_ntoh64( p_port->rec.port_info.subnet_prefix ) );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_BASE_LID:\r
+        p_port->comp.port_info.base_lid = 0xFFFF;\r
+        p_port->rec.port_info.base_lid =\r
+          cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "base_lid = 0x%X\n", cl_ntoh16( p_port->rec.port_info.base_lid ) );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_SM_BASE_LID:\r
+        p_port->comp.port_info.master_sm_base_lid = 0xFFFF;\r
+        p_port->rec.port_info.master_sm_base_lid =\r
+          cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "master_sm_base_lid = 0x%X\n",\r
+                   cl_ntoh16( p_port->rec.port_info.master_sm_base_lid ) );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_CAP_MASK:\r
+        p_port->comp.port_info.capability_mask = 0xFFFFFFFF;\r
+        p_port->rec.port_info.capability_mask =\r
+          cl_hton32( ( uint32_t ) strtoul( &line[offset], NULL, 0 ) );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "capability_mask = 0x%X\n",\r
+                   cl_ntoh32( p_port->rec.port_info.capability_mask ) );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_DIAG_CODE:\r
+        p_port->comp.port_info.diag_code = 0xFFFF;\r
+        p_port->rec.port_info.diag_code =\r
+          cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "diag_code = 0x%X\n",\r
+                   cl_ntoh16( p_port->rec.port_info.diag_code ) );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_MKEY_LEASE_PER:\r
+        p_port->comp.port_info.m_key_lease_period = 0xFFFF;\r
+        p_port->rec.port_info.m_key_lease_period =\r
+          cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "m_key_lease_period = 0x%X\n",\r
+                   cl_ntoh16( p_port->rec.port_info.m_key_lease_period ) );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_LOC_PORT_NUM:\r
+        p_port->comp.port_info.local_port_num = 0xFF;\r
+        p_port->rec.port_info.local_port_num =\r
+          ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "local_port_num = 0x%u\n",\r
+                   p_port->rec.port_info.local_port_num );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_LINK_WID_EN:\r
+        p_port->comp.port_info.link_width_enabled = 0xFF;\r
+        p_port->rec.port_info.link_width_enabled =\r
+          ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "link_width_enabled = 0x%u\n",\r
+                   p_port->rec.port_info.link_width_enabled );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_LINK_WID_SUP:\r
+        p_port->comp.port_info.link_width_supported = 0xFF;\r
+        p_port->rec.port_info.link_width_supported =\r
+          ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "link_width_supported = 0x%u\n",\r
+                   p_port->rec.port_info.link_width_supported );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_LINK_WID_ACT:\r
+        p_port->comp.port_info.link_width_active = 0xFF;\r
+        p_port->rec.port_info.link_width_active =\r
+          ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "link_width_active = 0x%u\n",\r
+                   p_port->rec.port_info.link_width_active );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_LINK_SPEED_SUP:\r
+        p_port->comp.port_info.state_info1 = 0xFF;\r
+        ib_port_info_set_link_speed_sup( ( uint8_t ) strtoul( &line[offset],\r
+                                                              NULL, 0 ),\r
+                                         &p_port->rec.port_info);\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+           osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                    "osmtest_parse_port: "\r
+                    "link_speed_supported = 0x%u\n",\r
+                    ib_port_info_get_link_speed_sup(&p_port->rec.port_info));\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_PORT_STATE:\r
+        str_skip_white( line, &offset );\r
+        p_port->comp.port_info.state_info1 = 0xFF;\r
+        ib_port_info_set_port_state(&p_port->rec.port_info,\r
+                                    ib_get_port_state_from_str(&line[offset]));\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "port_state = 0x%u\n",\r
+                   ib_port_info_get_port_state(&p_port->rec.port_info));\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_STATE_INFO2:\r
+        p_port->comp.port_info.state_info2 = 0xFF;\r
+        p_port->rec.port_info.state_info2 =\r
+           ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "state_info2 = 0x%u\n",\r
+                   p_port->rec.port_info.state_info2 );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_MKEY_PROT_BITS:\r
+        p_port->comp.port_info.mkey_lmc = 0xFF;\r
+        ib_port_info_set_mpb( &p_port->rec.port_info,\r
+                              ( uint8_t ) strtoul( &line[offset], NULL, 0 ) );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "mpb = 0x%u\n",\r
+                   ib_port_info_get_mpb(&p_port->rec.port_info) );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_LMC:\r
+        p_port->comp.port_info.mkey_lmc = 0xFF;\r
+        ib_port_info_set_lmc( &p_port->rec.port_info,\r
+                              ( uint8_t ) strtoul( &line[offset], NULL, 0 ) );\r
+\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "lmc = 0x%u\n",\r
+                   ib_port_info_get_lmc(&p_port->rec.port_info) );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_LINK_SPEED:\r
+        p_port->comp.port_info.link_speed = 0xFF;\r
+        p_port->rec.port_info.link_speed =\r
+          ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "link_speed = 0x%u\n",\r
+                   p_port->rec.port_info.link_speed );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_MTU_SMSL:\r
+        p_port->comp.port_info.mtu_smsl = 0xFF;\r
+        p_port->rec.port_info.mtu_smsl =\r
+          ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "mtu_smsl = 0x%u\n",\r
+                   p_port->rec.port_info.mtu_smsl );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_VL_CAP:\r
+        p_port->comp.port_info.vl_cap = 0xFF;\r
+        p_port->rec.port_info.vl_cap =\r
+          ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "vl_cap = 0x%u\n",\r
+                   p_port->rec.port_info.vl_cap );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_VL_HIGH_LIMIT:\r
+        p_port->comp.port_info.vl_high_limit = 0xFF;\r
+        p_port->rec.port_info.vl_high_limit =\r
+          ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "vl_high_limit = 0x%u\n",\r
+                   p_port->rec.port_info.vl_high_limit );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_VL_ARB_HIGH_CAP:\r
+        p_port->comp.port_info.vl_arb_high_cap = 0xFF;\r
+        p_port->rec.port_info.vl_arb_high_cap =\r
+          ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "vl_arb_high_cap = 0x%u\n",\r
+                   p_port->rec.port_info.vl_arb_high_cap );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_VL_ARB_LOW_CAP:\r
+        p_port->comp.port_info.vl_arb_low_cap = 0xFF;\r
+        p_port->rec.port_info.vl_arb_low_cap =\r
+          ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "vl_arb_low_cap = 0x%u\n",\r
+                   p_port->rec.port_info.vl_arb_low_cap );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_MTU_CAP:\r
+        p_port->comp.port_info.mtu_cap = 0xFF;\r
+        p_port->rec.port_info.mtu_cap =\r
+          ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "mtu_cap = 0x%u\n",\r
+                   p_port->rec.port_info.mtu_cap );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_VL_STALL_LIFE:\r
+        p_port->comp.port_info.vl_stall_life = 0xFF;\r
+        p_port->rec.port_info.vl_stall_life =\r
+          ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "vl_stall_life = 0x%u\n",\r
+                   p_port->rec.port_info.vl_stall_life );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_VL_ENFORCE:\r
+        p_port->comp.port_info.vl_enforce = 0xFF;\r
+        p_port->rec.port_info.vl_enforce =\r
+          ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "vl_enforce = 0x%u\n",\r
+                   p_port->rec.port_info.vl_enforce );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_MKEY_VIOL:\r
+        p_port->comp.port_info.m_key_violations = 0xFFFF;\r
+        p_port->rec.port_info.m_key_violations =\r
+          cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "m_key_violations = 0x%X\n",\r
+                   cl_ntoh16( p_port->rec.port_info.m_key_violations ) );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_PKEY_VIOL:\r
+        p_port->comp.port_info.p_key_violations = 0xFFFF;\r
+        p_port->rec.port_info.p_key_violations =\r
+          cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "p_key_violations = 0x%X\n",\r
+                   cl_ntoh16( p_port->rec.port_info.p_key_violations ) );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_QKEY_VIOL:\r
+        p_port->comp.port_info.q_key_violations = 0xFFFF;\r
+        p_port->rec.port_info.q_key_violations =\r
+          cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "q_key_violations = 0x%X\n",\r
+                   cl_ntoh16( p_port->rec.port_info.q_key_violations ) );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_GUID_CAP:\r
+        p_port->comp.port_info.guid_cap = 0xFF;\r
+        p_port->rec.port_info.guid_cap =\r
+          ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "guid_cap = 0x%u\n",\r
+                   p_port->rec.port_info.guid_cap );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_SUBN_TIMEOUT:\r
+        p_port->comp.port_info.subnet_timeout = 0x1F;\r
+        p_port->rec.port_info.subnet_timeout =\r
+          ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "subnet_timeout = 0x%u\n",\r
+                   ib_port_info_get_timeout(&p_port->rec.port_info) );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_RESP_TIME_VAL:\r
+        p_port->comp.port_info.resp_time_value = 0xFF;\r
+        p_port->rec.port_info.resp_time_value =\r
+          ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "resp_time_value = 0x%u\n",\r
+                   p_port->rec.port_info.resp_time_value );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_ERR_THRESHOLD:\r
+        p_port->comp.port_info.error_threshold = 0xFF;\r
+        p_port->rec.port_info.error_threshold =\r
+          ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_port: "\r
+                   "error_threshold = 0x%u\n",\r
+                   p_port->rec.port_info.error_threshold );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_END:\r
+        done = TRUE;\r
+        break;\r
+\r
+      default:\r
+        osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                 "osmtest_parse_port: ERR 0125: "\r
+                 "Ignoring line %u with unknown token: %s\n",\r
+                 *p_line_num, &line[offset] );\r
+       break;\r
+    }\r
+  }\r
+\r
+  /*\r
+   * Make sure the user specified enough information, then\r
+   * add this object to the database.\r
+   */\r
+  if( p_port->comp.lid == 0 )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_parse_port: ERR 0126: "\r
+             "LID must be specified for defined ports\n" );\r
+    port_delete( p_port );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  cl_qmap_insert( &p_osmt->exp_subn.port_key_tbl,\r
+                  port_gen_id(p_port->rec.lid, p_port->rec.port_num),\r
+                  &p_port->map_item );\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_parse_path( IN osmtest_t * const p_osmt,\r
+                    IN FILE * const fh,\r
+                    IN OUT uint32_t * const p_line_num )\r
+{\r
+  ib_api_status_t status = IB_SUCCESS;\r
+  uint32_t offset;\r
+  char line[OSMTEST_MAX_LINE_LEN];\r
+  boolean_t done = FALSE;\r
+  path_t *p_path;\r
+  const osmtest_token_t *p_tok;\r
+  boolean_t got_error = FALSE;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_parse_path );\r
+\r
+  p_path = path_new( );\r
+  CL_ASSERT( p_path != NULL );\r
+\r
+  /*\r
+   * Parse the inventory file and create the database.\r
+   */\r
+  while( !done )\r
+  {\r
+    if( fgets( line, OSMTEST_MAX_LINE_LEN, fh ) == NULL )\r
+    {\r
+      /*\r
+       * End of file in the middle of a definition.\r
+       */\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_parse_path: ERR 0127: "\r
+               "Unexpected end of file\n" );\r
+      status = IB_ERROR;\r
+      goto Exit;\r
+    }\r
+\r
+    ++*p_line_num;\r
+\r
+    /*\r
+     * Skip whitespace\r
+     */\r
+    offset = 0;\r
+    if( !str_skip_white( line, &offset ) )\r
+      continue;       /* whole line was whitespace */\r
+\r
+    p_tok = str_get_token( &line[offset] );\r
+    if( p_tok == NULL )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_parse_path: ERR 0128: "\r
+               "Ignoring line %u with unknown token: %s\n",\r
+               *p_line_num, &line[offset] );\r
+      got_error = TRUE;\r
+      continue;\r
+    }\r
+\r
+    if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+               "osmtest_parse_path: "\r
+               "Found '%s' (line %u)\n", p_tok->str, *p_line_num );\r
+    }\r
+\r
+    str_skip_token( line, &offset );\r
+\r
+    switch ( p_tok->val )\r
+    {\r
+      case OSMTEST_TOKEN_COMMENT:\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_DGID:\r
+        p_path->comp.dgid.unicast.prefix = 0xFFFFFFFFFFFFFFFFULL;\r
+        p_path->comp.dgid.unicast.interface_id = 0xFFFFFFFFFFFFFFFFULL;\r
+\r
+        str_skip_white( line, &offset );\r
+        p_path->rec.dgid.unicast.prefix =\r
+          cl_hton64( strtoull( &line[offset], NULL, 0 ) );\r
+        str_skip_token( line, &offset );\r
+        p_path->rec.dgid.unicast.interface_id =\r
+          cl_hton64( strtoull( &line[offset], NULL, 0 ) );\r
+\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_path: "\r
+                   "dgid = 0x%016" PRIx64 " 0x%016" PRIx64 "\n",\r
+                   cl_ntoh64( p_path->rec.dgid.unicast.prefix ),\r
+                   cl_ntoh64( p_path->rec.dgid.unicast.interface_id ) );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_SGID:\r
+        p_path->comp.sgid.unicast.prefix = 0xFFFFFFFFFFFFFFFFULL;\r
+        p_path->comp.sgid.unicast.interface_id = 0xFFFFFFFFFFFFFFFFULL;\r
+\r
+        str_skip_white( line, &offset );\r
+        p_path->rec.sgid.unicast.prefix =\r
+          cl_hton64( strtoull( &line[offset], NULL, 0 ) );\r
+        str_skip_token( line, &offset );\r
+        p_path->rec.sgid.unicast.interface_id =\r
+          cl_hton64( strtoull( &line[offset], NULL, 0 ) );\r
+\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_path: "\r
+                   "sgid = 0x%016" PRIx64 " 0x%016" PRIx64 "\n",\r
+                   cl_ntoh64( p_path->rec.sgid.unicast.prefix ),\r
+                   cl_ntoh64( p_path->rec.sgid.unicast.interface_id ) );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_DLID:\r
+        p_path->comp.dlid = 0xFFFF;\r
+        p_path->rec.dlid =\r
+          cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_path: "\r
+                   "dlid = 0x%X\n", cl_ntoh16( p_path->rec.dlid ) );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_SLID:\r
+        p_path->comp.slid = 0xFFFF;\r
+        p_path->rec.slid =\r
+          cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_path: "\r
+                   "slid = 0x%X\n", cl_ntoh16( p_path->rec.slid ) );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_PKEY:\r
+        p_path->comp.pkey = 0xFFFF;\r
+        p_path->rec.pkey =\r
+          cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+        if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+        {\r
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+                   "osmtest_parse_path: "\r
+                   "pkey = 0x%X\n", cl_ntoh16( p_path->rec.pkey ) );\r
+        }\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_END:\r
+        done = TRUE;\r
+        break;\r
+\r
+      default:\r
+        osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                 "osmtest_parse_path: ERR 0129: "\r
+                 "Ignoring line %u with unknown token: %s\n",\r
+                 *p_line_num, &line[offset] );\r
+        got_error = TRUE;\r
+        break;\r
+    }\r
+  }\r
+\r
+  if( got_error ) \r
+  {\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+  /*\r
+   * Make sure the user specified enough information, then\r
+   * add this object to the database.\r
+   */\r
+  if( osmtest_path_rec_kay_is_valid( p_osmt, p_path ) == FALSE )\r
+  {\r
+    path_delete( p_path );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  cl_qmap_insert( &p_osmt->exp_subn.path_tbl,\r
+                  osmtest_path_rec_key_get( &p_path->rec ),\r
+                  &p_path->map_item );\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_parse_link( IN osmtest_t * const p_osmt,\r
+                    IN FILE * const fh,\r
+                    IN OUT uint32_t * const p_line_num )\r
+{\r
+  ib_api_status_t status = IB_SUCCESS;\r
+  uint32_t offset;\r
+  char line[OSMTEST_MAX_LINE_LEN];\r
+  boolean_t done = FALSE;\r
+  const osmtest_token_t *p_tok;\r
+  boolean_t got_error = FALSE;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_parse_link);\r
+\r
+  /*\r
+   * Parse the inventory file and create the database.\r
+   */\r
+  while( !done )\r
+  {\r
+    if( fgets( line, OSMTEST_MAX_LINE_LEN, fh ) == NULL )\r
+    {\r
+      /*\r
+       * End of file in the middle of a definition.\r
+       */\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_parse_link: ERR 012A: "\r
+               "Unexpected end of file\n" );\r
+      status = IB_ERROR;\r
+      goto Exit;\r
+    }\r
+\r
+    ++*p_line_num;\r
+\r
+    /*\r
+     * Skip whitespace\r
+     */\r
+    offset = 0;\r
+    if( !str_skip_white( line, &offset ) )\r
+      continue;       /* whole line was whitespace */\r
+\r
+    p_tok = str_get_token( &line[offset] );\r
+    if( p_tok == NULL )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_parse_link: ERR 012B: "\r
+               "Ignoring line %u with unknown token: %s\n",\r
+               *p_line_num, &line[offset] );\r
+      got_error = TRUE;\r
+      continue;\r
+    }\r
+\r
+    if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+               "osmtest_parse_link: "\r
+               "Found '%s' (line %u)\n", p_tok->str, *p_line_num );\r
+    }\r
+\r
+    str_skip_token( line, &offset );\r
+\r
+    switch ( p_tok->val )\r
+    {\r
+      case OSMTEST_TOKEN_FROMLID:\r
+      case OSMTEST_TOKEN_FROMPORTNUM:\r
+      case OSMTEST_TOKEN_TOPORTNUM:\r
+      case OSMTEST_TOKEN_TOLID:\r
+        /* For now */\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_END:\r
+        done = TRUE;\r
+        break;\r
+\r
+      default:\r
+        osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                 "osmtest_parse_link: ERR 012C: "\r
+                 "Ignoring line %u with unknown token: %s\n",\r
+                 *p_line_num, &line[offset] );\r
+        got_error = TRUE;\r
+        break;\r
+    }\r
+  }\r
+\r
+  if( got_error )\r
+    status = IB_ERROR;\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_create_db( IN osmtest_t * const p_osmt )\r
+{\r
+  FILE *fh;\r
+  ib_api_status_t status = IB_SUCCESS;\r
+  uint32_t offset;\r
+  char line[OSMTEST_MAX_LINE_LEN];\r
+  uint32_t line_num = 0;\r
+  const osmtest_token_t *p_tok;\r
+  boolean_t got_error = FALSE;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_create_db );\r
+\r
+  fh = fopen( p_osmt->opt.file_name, "r" );\r
+  if( fh == NULL )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_create_db: ERR 0130: "\r
+             "Unable to open inventory file (%s)\n", p_osmt->opt.file_name);\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  /*\r
+   * Parse the inventory file and create the database.\r
+   */\r
+  while( fgets( line, OSMTEST_MAX_LINE_LEN, fh ) != NULL )\r
+  {\r
+    line_num++;\r
+\r
+    /*\r
+     * Skip whitespace\r
+     */\r
+    offset = 0;\r
+    if( !str_skip_white( line, &offset ) )\r
+      continue;       /* whole line was whitespace */\r
+\r
+    p_tok = str_get_token( &line[offset] );\r
+    if( p_tok == NULL )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_create_db: ERR 0131: "\r
+               "Ignoring line %u: %s\n", line_num, &line[offset] );\r
+      got_error = TRUE;\r
+      continue;\r
+    }\r
+\r
+    if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+               "osmtest_create_db: "\r
+               "Found '%s' (line %u)\n", p_tok->str, line_num );\r
+    }\r
+\r
+    switch ( p_tok->val )\r
+    {\r
+      case OSMTEST_TOKEN_COMMENT:\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_DEFINE_NODE:\r
+        status = osmtest_parse_node( p_osmt, fh, &line_num );\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_DEFINE_PORT:\r
+        status = osmtest_parse_port( p_osmt, fh, &line_num );\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_DEFINE_PATH:\r
+        status = osmtest_parse_path( p_osmt, fh, &line_num );\r
+        break;\r
+\r
+      case OSMTEST_TOKEN_DEFINE_LINK:\r
+        status = osmtest_parse_link( p_osmt, fh, &line_num );\r
+        break;\r
+\r
+      default:\r
+        osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                 "osmtest_create_db: ERR 0132: "\r
+                 "Ignoring line %u: %s\n", line_num, &line[offset] );\r
+        got_error = TRUE;\r
+        break;\r
+    }\r
+\r
+    if( got_error )\r
+      status = IB_ERROR;\r
+\r
+    if( status != IB_SUCCESS )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_create_db: ERR 0133: "\r
+               "Bad status received during parsing (%s)\n",\r
+               ib_get_err_str( status ) );\r
+      fclose( fh );\r
+      goto Exit;\r
+    }\r
+  }\r
+\r
+  fclose( fh );\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+   Returns the index in the local port attribute array for the\r
+   user's selection.\r
+**********************************************************************/\r
+static uint32_t\r
+osmtest_get_user_port( IN osmtest_t * const p_osmt,\r
+                       IN const ib_port_attr_t p_attr_array[],\r
+                       IN uint32_t const num_ports )\r
+{\r
+  uint32_t i;\r
+  uint32_t choice = 0;\r
+  boolean_t done_flag = FALSE;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_get_user_port );\r
+\r
+  /*\r
+   * User needs prompting for the local port GUID with which\r
+   * to bind.\r
+   */\r
+\r
+  while( done_flag == FALSE )\r
+  {\r
+    printf( "\nChoose a local port number with which to bind:\n\n" );\r
+    for( i = 0; i < num_ports; i++ )\r
+    {\r
+      /*\r
+       * Print the index + 1 since by convention, port numbers\r
+       * start with 1 on host channel adapters.\r
+       */\r
+\r
+      printf( "\t%u: GUID = 0x%8" PRIx64 ", lid = 0x%04X, state = %s\n",\r
+              i + 1, cl_ntoh64( p_attr_array[i].port_guid ),\r
+              p_attr_array[i].lid,\r
+              ib_get_port_state_str( p_attr_array[i].link_state ) );\r
+    }\r
+\r
+    printf( "\nEnter choice (1-%u): ", i );\r
+    scanf( "%u", &choice );\r
+    if( choice > num_ports )\r
+      printf( "\nError: Lame choice!\n" );\r
+    else\r
+      done_flag = TRUE;\r
+\r
+  }\r
+  printf("\n");\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( choice - 1 );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_bind( IN osmtest_t * p_osmt,\r
+              IN uint16_t max_lid,\r
+              IN ib_net64_t guid OPTIONAL )\r
+{\r
+  uint32_t port_index;\r
+  ib_api_status_t status;\r
+  uint32_t num_ports = GUID_ARRAY_SIZE;\r
+  ib_port_attr_t attr_array[GUID_ARRAY_SIZE];\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_bind );\r
+\r
+  /*\r
+   * Call the transport layer for a list of local port\r
+   * GUID values.\r
+   */\r
+  status = osm_vendor_get_all_port_attr( p_osmt->p_vendor,\r
+                                         attr_array, &num_ports );\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_bind: ERR 0134: "\r
+             "Failure getting local port attributes (%s)\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  if( guid == 0 )\r
+  {\r
+    /*\r
+     * User needs prompting for the local port GUID with which\r
+     * to bind.\r
+     */\r
+    port_index = osmtest_get_user_port( p_osmt, attr_array, num_ports );\r
+\r
+    if( num_ports == 0 )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_bind: ERR 0135: "\r
+               "No local ports.  Unable to proceed\n" );\r
+      goto Exit;\r
+    }\r
+    guid = attr_array[port_index].port_guid;\r
+  }\r
+  else\r
+  {\r
+    for( port_index = 0; port_index < num_ports; port_index++ )\r
+    {\r
+      if( attr_array[port_index].port_guid == guid )\r
+        break;\r
+    }\r
+\r
+    if( port_index == num_ports )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_bind: ERR 0136: "\r
+               "No local port with guid 0x%016" PRIx64 "\n",\r
+               cl_ntoh64( guid ) );\r
+      status = IB_NOT_FOUND;\r
+      goto Exit;\r
+    }\r
+  }\r
+\r
+  /*\r
+   * Copy the port info for the selected port.\r
+   */\r
+  memcpy( &p_osmt->local_port, &attr_array[port_index],\r
+          sizeof( p_osmt->local_port ) );\r
+\r
+  /* bind to the SA */\r
+  osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+           "osmtest_bind: "\r
+           "Using port with SM LID:0x%04X\n",\r
+           p_osmt->local_port.sm_lid);\r
+  p_osmt->max_lid = max_lid;\r
+\r
+  p_osmt->h_bind = osmv_bind_sa(p_osmt->p_vendor, &p_osmt->mad_pool, guid);\r
+\r
+  if( p_osmt->h_bind == OSM_BIND_INVALID_HANDLE )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_bind: ERR 0137: "\r
+             "Unable to bind to SA\n" );\r
+    status = IB_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_run( IN osmtest_t * const p_osmt )\r
+{\r
+  ib_api_status_t status = IB_SUCCESS;\r
+\r
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_run );\r
+\r
+  status = osmtest_validate_sa_class_port_info(p_osmt);\r
+  if( status != IB_SUCCESS )\r
+  {\r
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+             "osmtest_run: ERR 0138: "\r
+             "Could not obtain SA ClassPortInfo (%s)\n",\r
+             ib_get_err_str( status ) );\r
+    goto Exit;\r
+  }\r
+\r
+  if( p_osmt->opt.flow == 1 )\r
+  {\r
+    /*\r
+     * Creating an inventory file with all nodes, ports and paths\r
+     */\r
+    status = osmtest_create_inventory_file( p_osmt );\r
+    if( status != IB_SUCCESS )\r
+    {\r
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+               "osmtest_run: ERR 0139: "\r
+               "Inventory file create failed (%s)\n",\r
+               ib_get_err_str( status ) );\r
+      goto Exit;\r
+    }\r
+  }\r
+  else\r
+  {\r
+    if( p_osmt->opt.flow == 5 )\r
+    {\r
+      /*\r
+       * Stress SA - flood the it with queries\r
+       */\r
+      switch ( p_osmt->opt.stress )\r
+      {\r
+        case 0:\r
+        case 1:        /* small response SA query stress */\r
+          status = osmtest_stress_small_rmpp( p_osmt );\r
+          if( status != IB_SUCCESS )\r
+          {\r
+            osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                     "osmtest_run: ERR 0140: "\r
+                     "Small RMPP stress test failed (%s)\n",\r
+                     ib_get_err_str( status ) );\r
+            goto Exit;\r
+          }\r
+          break;\r
+        case 2:        /* large response SA query stress */\r
+          status = osmtest_stress_large_rmpp( p_osmt );\r
+          if( status != IB_SUCCESS )\r
+          {\r
+            osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                     "osmtest_run: ERR 0141: "\r
+                     "Large RMPP stress test failed (%s)\n",\r
+                     ib_get_err_str( status ) );\r
+            goto Exit;\r
+          }\r
+          break;\r
+        case 3:        /* large response Path Record SA query stress */\r
+          status = osmtest_create_db( p_osmt );\r
+          if( status != IB_SUCCESS )\r
+          {\r
+            osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                     "osmtest_run: ERR 0142: "\r
+                     "Database creation failed (%s)\n",\r
+                     ib_get_err_str( status ) );\r
+            goto Exit;\r
+          }\r
+\r
+          status = osmtest_stress_large_rmpp_pr( p_osmt );\r
+          if( status != IB_SUCCESS )\r
+          {\r
+            osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                     "osmtest_run: ERR 0143: "\r
+                     "Large RMPP stress test failed (%s)\n",\r
+                     ib_get_err_str( status ) );\r
+            goto Exit;\r
+          }\r
+          break;\r
+        default:\r
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                   "osmtest_run: ERR 0144: "\r
+                   "Unknown stress test value %u\n",\r
+                   p_osmt->opt.stress );\r
+          break;\r
+      }\r
+    }\r
+    else\r
+    {\r
+\r
+      /*\r
+       * Run normal validition tests.\r
+       */\r
+       if (p_osmt->opt.flow == 0 || p_osmt->opt.flow == 2)\r
+       {\r
+         /*\r
+          * Only validate the given inventory file\r
+          */ \r
+         status = osmtest_create_db( p_osmt );\r
+         if( status != IB_SUCCESS )\r
+         {\r
+           osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                    "osmtest_run: ERR 0145: "\r
+                    "Database creation failed (%s)\n",\r
+                    ib_get_err_str( status ) );\r
+           goto Exit;\r
+         }\r
+\r
+         status = osmtest_validate_against_db( p_osmt );\r
+         if( status != IB_SUCCESS )\r
+         {\r
+           osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                    "osmtest_run: ERR 0146: "\r
+                    "SA validation database failure (%s)\n",\r
+                    ib_get_err_str( status ) );\r
+           goto Exit;\r
+         }\r
+       }\r
+\r
+       if (p_osmt->opt.flow == 0)\r
+       {\r
+         status = osmtest_wrong_sm_key_ignored( p_osmt );\r
+         if( status != IB_SUCCESS )\r
+         {\r
+           osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                    "osmtest_run: ERR 0147: "\r
+                    "Try wrong SM_Key failed (%s)\n",\r
+                    ib_get_err_str( status ) );\r
+           goto Exit;\r
+         }\r
+       }\r
+\r
+       if (p_osmt->opt.flow == 0 || p_osmt->opt.flow == 3)\r
+       {\r
+         /*\r
+          * run service registration, deregistration, and lease test\r
+          */\r
+         status = osmt_run_service_records_flow( p_osmt );\r
+         if( status != IB_SUCCESS )\r
+         {\r
+           osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                    "osmtest_run: ERR 0148: "\r
+                    "Service Flow failed (%s)\n",\r
+                    ib_get_err_str( status ) );\r
+           goto Exit;\r
+         }\r
+       }\r
+\r
+       if (p_osmt->opt.flow == 0 || p_osmt->opt.flow == 4)\r
+       {\r
+          /* \r
+           * Run event forwarding test\r
+           */\r
+#ifdef OSM_VENDOR_INTF_MTL\r
+          status = osmt_run_inform_info_flow( p_osmt );\r
+\r
+          if( status != IB_SUCCESS )\r
+          {\r
+            osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                     "osmtest_run: ERR 0149: "\r
+                     "Inform Info Flow failed: (%s)\n",\r
+                     ib_get_err_str( status ) );\r
+            goto Exit;\r
+          }\r
+#else\r
+          osm_log (&p_osmt->log, OSM_LOG_INFO,\r
+                   "osmtest_run: The event forwarding flow "\r
+                   "is not implemented yet!\n");\r
+          status = IB_SUCCESS;\r
+          goto Exit;\r
+#endif\r
+        }\r
+\r
+        if (p_osmt->opt.flow == 7)\r
+        {\r
+          /* \r
+           * QoS info: dump VLArb and SLtoVL tables.\r
+           * Since it generates a huge file, we run it only\r
+           * if explicitly required to\r
+           */\r
+          status = osmtest_create_db( p_osmt );\r
+          if( status != IB_SUCCESS )\r
+          {\r
+            osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                     "osmtest_run: ERR 014A: "\r
+                     "Database creation failed (%s)\n",\r
+                     ib_get_err_str( status ) );\r
+            goto Exit;\r
+          }\r
+\r
+          status = osmt_run_slvl_and_vlarb_records_flow(p_osmt);\r
+          if( status != IB_SUCCESS )\r
+          {\r
+            osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                     "osmtest_run: ERR 0150: "\r
+                     "Failed to get SLtoVL and VL Arbitration Tables (%s)\n",\r
+                     ib_get_err_str( status ) );\r
+            goto Exit;\r
+          }\r
+        }\r
+\r
+        if (p_osmt->opt.flow == 8)\r
+        {\r
+          /*\r
+           * Run trap 64/65 flow (this flow requires running of external tool)\r
+           */\r
+#ifdef OSM_VENDOR_INTF_MTL\r
+          status = osmt_run_trap64_65_flow( p_osmt  );\r
+          if( status != IB_SUCCESS )\r
+          {\r
+            osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                     "osmtest_run: ERR 0151: "\r
+                     "Trap 64/65 Flow failed: (%s)\n",\r
+                     ib_get_err_str( status ) );\r
+            goto Exit;\r
+          }\r
+#else\r
+          osm_log (&p_osmt->log, OSM_LOG_INFO,\r
+                   "osmtest_run: The event forwarding flow "\r
+                   "is not implemented yet!\n");\r
+          status = IB_SUCCESS;\r
+          goto Exit;\r
+#endif\r
+        }\r
+\r
+        if (p_osmt->opt.flow == 0 || p_osmt->opt.flow == 6)\r
+        {\r
+          /*\r
+           * Multicast flow\r
+           */ \r
+          status = osmt_run_mcast_flow( p_osmt );\r
+          if( status != IB_SUCCESS )\r
+          {\r
+            osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+                     "osmtest_run: ERR 0152: "\r
+                     "Multicast Flow failed: (%s)\n",\r
+                     ib_get_err_str( status ) );\r
+            goto Exit;\r
+          }\r
+        }\r
+\r
+        osm_log( &p_osmt->log, OSM_LOG_INFO,\r
+                 "osmtest_run: "\r
+                 "\n\n***************** ALL TESTS PASS *****************\n\n" );\r
+\r
+      }\r
+   }\r
+\r
+ Exit:\r
+  OSM_LOG_EXIT( &p_osmt->log );\r
+  return ( status );\r
+}\r
+\r