]> git.openfabrics.org - ~shefty/rdma-win.git/commitdiff
New opensm component
authoreitan <eitan@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Tue, 27 Sep 2005 07:59:33 +0000 (07:59 +0000)
committereitan <eitan@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Tue, 27 Sep 2005 07:59:33 +0000 (07:59 +0000)
git-svn-id: svn://openib.tc.cornell.edu/gen1@99 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

249 files changed:
trunk/ulp/dirs
trunk/ulp/opensm/dirs [new file with mode: 0644]
trunk/ulp/opensm/user/dirs [new file with mode: 0644]
trunk/ulp/opensm/user/ibtrapgen/Makefile [new file with mode: 0644]
trunk/ulp/opensm/user/ibtrapgen/SOURCES [new file with mode: 0644]
trunk/ulp/opensm/user/ibtrapgen/ibtrapgen.c [new file with mode: 0644]
trunk/ulp/opensm/user/ibtrapgen/ibtrapgen.h [new file with mode: 0644]
trunk/ulp/opensm/user/ibtrapgen/main.c [new file with mode: 0644]
trunk/ulp/opensm/user/include/complib/cl_byteswap.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/complib/cl_signal_osd.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/iba/ib_types.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/iba/ib_types_extended.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/cl_dispatcher.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/cl_event_wheel.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_attrib_req.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_base.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_base.h.orig [new file with mode: 0755]
trunk/ulp/opensm/user/include/opensm/osm_db.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_db_pack.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_drop_mgr.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_errors.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_ft_config_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_fwd_tbl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_helper.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_inform.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_lid_mgr.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_lin_fwd_rcv.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_lin_fwd_rcv_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_lin_fwd_tbl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_link_mgr.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_log.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_mad_pool.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_madw.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_matrix.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_mcast_config_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_mcast_fwd_rcv.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_mcast_fwd_rcv_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_mcast_mgr.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_mcast_tbl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_mcm_info.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_mcm_port.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_mcmember.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_msgdef.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_mtl_bind.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_mtree.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_multicast.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_node.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_node_desc_rcv.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_node_desc_rcv_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_node_info_rcv.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_node_info_rcv_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_opensm.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_partition.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_path.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_pi_config_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_pkey.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_pkey_config_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_pkey_rcv.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_pkey_rcv_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_port.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_port_info_rcv.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_port_info_rcv_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_port_profile.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_rand_fwd_tbl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_remote_sm.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_req.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_req_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_resp.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_class_port_info.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_class_port_info_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_informinfo.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_informinfo_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_lft_record.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_lft_record_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_link_record.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_link_record_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_mad_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_mcmember_record.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_mcmember_record_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_node_record.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_node_record_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_path_record.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_path_record_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_pkey_record.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_pkey_record_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_portinfo_record.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_portinfo_record_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_response.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_service_record.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_service_record_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_slvl_record.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_slvl_record_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_sminfo_record.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_sminfo_record_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_vlarb_record.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sa_vlarb_record_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_service.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_slvl_map_rcv.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_slvl_map_rcv_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sm.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sm_info_get_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sm_mad_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sm_state_mgr.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sminfo_rcv.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sminfo_rcv_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_state_mgr.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_state_mgr_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_stats.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_subnet.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_subnet_config_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sw_info_rcv.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sw_info_rcv_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_sweep_fail_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_switch.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_trap_rcv.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_trap_rcv_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_ts_useraccess.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_ucast_mgr.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_ucast_updn.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_umadt.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_vl15intf.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_vl_arb_rcv.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/osm_vl_arb_rcv_ctrl.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/opensm/st.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/vendor/osm_vendor.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/vendor/osm_vendor_al.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/vendor/osm_vendor_api.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/vendor/osm_vendor_sa_api.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/vendor/osm_vendor_select.h [new file with mode: 0644]
trunk/ulp/opensm/user/include/vendor/winosm_common.h [new file with mode: 0644]
trunk/ulp/opensm/user/libopensm/Makefile [new file with mode: 0755]
trunk/ulp/opensm/user/libopensm/SOURCES [new file with mode: 0644]
trunk/ulp/opensm/user/libopensm/osm_helper.c [new file with mode: 0644]
trunk/ulp/opensm/user/libopensm/osm_log.c [new file with mode: 0644]
trunk/ulp/opensm/user/libopensm/osm_mad_pool.c [new file with mode: 0644]
trunk/ulp/opensm/user/libvendor/Makefile [new file with mode: 0644]
trunk/ulp/opensm/user/libvendor/SOURCES [new file with mode: 0644]
trunk/ulp/opensm/user/libvendor/osm_vendor_al.c [new file with mode: 0644]
trunk/ulp/opensm/user/libvendor/osm_vendor_mlx_sa.c [new file with mode: 0644]
trunk/ulp/opensm/user/libvendor/winosm_common.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/Makefile [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/SOURCES [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/cl_dispatcher.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/cl_event_wheel.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/main.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/opensm.rc [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_db_files.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_db_pack.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_drop_mgr.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_fwd_tbl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_inform.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_lid_mgr.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_lin_fwd_rcv.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_lin_fwd_rcv_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_lin_fwd_tbl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_link_mgr.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_matrix.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_mcast_fwd_rcv.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_mcast_fwd_rcv_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_mcast_mgr.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_mcast_tbl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_mcm_info.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_mcm_port.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_mtree.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_multicast.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_node.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_node_desc_rcv.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_node_desc_rcv_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_node_info_rcv.c [new file with mode: 0755]
trunk/ulp/opensm/user/opensm/osm_node_info_rcv_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_opensm.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_pkey.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_pkey_rcv.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_pkey_rcv_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_port.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_port_info_rcv.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_port_info_rcv_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_remote_sm.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_req.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_req_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_resp.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_class_port_info.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_class_port_info_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_informinfo.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_informinfo_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_lft_record.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_lft_record_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_link_record.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_link_record_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_mad_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_mcmember_record.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_mcmember_record_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_node_record.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_node_record_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_path_record.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_path_record_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_pkey_record.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_pkey_record_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_portinfo_record.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_portinfo_record_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_response.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_service_record.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_service_record_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_slvl_record.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_slvl_record_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_sminfo_record.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_sminfo_record_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_vlarb_record.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sa_vlarb_record_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_service.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_slvl_map_rcv.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_slvl_map_rcv_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sm.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sm_mad_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sm_state_mgr.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sminfo_rcv.c [new file with mode: 0755]
trunk/ulp/opensm/user/opensm/osm_sminfo_rcv_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_state_mgr.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_state_mgr_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_subnet.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sw_info_rcv.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sw_info_rcv_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_sweep_fail_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_switch.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_trap_rcv.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_trap_rcv_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_ucast_mgr.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_ucast_updn.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_vl15intf.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_vl_arb_rcv.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_vl_arb_rcv_ctrl.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/st.c [new file with mode: 0644]
trunk/ulp/opensm/user/osmtest/Makefile [new file with mode: 0644]
trunk/ulp/opensm/user/osmtest/SOURCES [new file with mode: 0644]
trunk/ulp/opensm/user/osmtest/error.h [new file with mode: 0644]
trunk/ulp/opensm/user/osmtest/main.c [new file with mode: 0644]
trunk/ulp/opensm/user/osmtest/osmt_inform.c [new file with mode: 0644]
trunk/ulp/opensm/user/osmtest/osmt_inform.h [new file with mode: 0644]
trunk/ulp/opensm/user/osmtest/osmt_mtl_regular_qp.c [new file with mode: 0644]
trunk/ulp/opensm/user/osmtest/osmt_mtl_regular_qp.h [new file with mode: 0644]
trunk/ulp/opensm/user/osmtest/osmt_multicast.c [new file with mode: 0644]
trunk/ulp/opensm/user/osmtest/osmt_service.c [new file with mode: 0644]
trunk/ulp/opensm/user/osmtest/osmt_slvl_vl_arb.c [new file with mode: 0644]
trunk/ulp/opensm/user/osmtest/osmtest.c [new file with mode: 0644]
trunk/ulp/opensm/user/osmtest/osmtest.h [new file with mode: 0644]
trunk/ulp/opensm/user/osmtest/osmtest_base.h [new file with mode: 0644]
trunk/ulp/opensm/user/osmtest/osmtest_subnet.h [new file with mode: 0644]

index d41ec66e7db3c2033d1c75bbe6ee70549cb25bbb..75d677acaecd603f18edbdc476c02bcca2d8446f 100644 (file)
@@ -1,5 +1,6 @@
 DIRS=\\r
        dapl    \\r
        ipoib   \\r
-       srp             \\r
+       srp     \\r
+       opensm  \\r
        wsd\r
diff --git a/trunk/ulp/opensm/dirs b/trunk/ulp/opensm/dirs
new file mode 100644 (file)
index 0000000..db5a897
--- /dev/null
@@ -0,0 +1,2 @@
+DIRS=\\r
+       user    \r
diff --git a/trunk/ulp/opensm/user/dirs b/trunk/ulp/opensm/user/dirs
new file mode 100644 (file)
index 0000000..d7822e5
--- /dev/null
@@ -0,0 +1,7 @@
+DIRS=\
+   libvendor \
+   libopensm \
+   opensm \
+   osmtest \
+   ibtrapgen
+
diff --git a/trunk/ulp/opensm/user/ibtrapgen/Makefile b/trunk/ulp/opensm/user/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/trunk/ulp/opensm/user/ibtrapgen/SOURCES b/trunk/ulp/opensm/user/ibtrapgen/SOURCES
new file mode 100644 (file)
index 0000000..54e5501
--- /dev/null
@@ -0,0 +1,67 @@
+!if $(FREEBUILD)
+TARGETNAME=ibtrapgen
+!else
+TARGETNAME=ibtrapgend
+!endif
+
+!if !defined(WINIBHOME)
+WINIBHOME=..\..\..\..
+!endif
+
+LIBPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)
+
+!if defined(OSM_TARGET)
+TARGETPATH=$(OSM_TARGET)\bin\user\obj$(BUILD_ALT_DIR)
+!else
+TARGETPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)
+!endif
+
+TARGETTYPE=PROGRAM
+UMTYPE=console
+USE_CRTDLL=1
+OVR_DIR=..\addon
+
+
+SOURCES=\
+       main.c \
+       ibtrapgen.c
+
+
+
+OSM_HOME=..
+
+TARGETLIBS=\
+!if $(FREEBUILD)
+                       $(LIBPATH)\*\ibal.lib \
+                       $(LIBPATH)\*\complib.lib \
+                       $(TARGETPATH)\*\osmv_ibal.lib \
+                       $(TARGETPATH)\*\opensm_ibal.lib \
+                       $(CRT_LIB_PATH)\msvcrt.lib
+
+!else
+                       $(LIBPATH)\*\ibald.lib \
+                       $(LIBPATH)\*\complibd.lib \
+                       $(TARGETPATH)\*\osmv_ibald.lib \
+                       $(TARGETPATH)\*\opensm_ibald.lib \
+                       $(CRT_LIB_PATH)\msvcrt.lib
+!endif
+
+#DO NOT TOUCH the order of search path , until ib_types.h merging process will be done
+INCLUDES= \
+       $(OSM_HOME)\include; \
+       $(OSM_HOME); \
+       $(WINIBHOME)\inc; \
+       $(WINIBHOME)\inc\user;
+
+# Could be any special flag needed for this project 
+USER_C_FLAGS=$(USER_C_FLAGS) /MD
+#Add preproccessor definitions
+C_DEFINES=$(C_DEFINES) -DWIN32 -D__WIN__ -D__i386__ -Dinline=__inline -DMT_LITTLE_ENDIAN -DOSM_VENDOR_INTF_AL
+!if !$(FREEBUILD)
+#C_DEFINES=$(C_DEFINES) -D_DEBUG -DDEBUG -DDBG
+C_DEFINES=$(C_DEFINES) 
+!endif
+
+LINKER_FLAGS= $(LINKER_FLAGS)
+MSC_WARNING_LEVEL= /W3
+
diff --git a/trunk/ulp/opensm/user/ibtrapgen/ibtrapgen.c b/trunk/ulp/opensm/user/ibtrapgen/ibtrapgen.c
new file mode 100644 (file)
index 0000000..c6bd3a2
--- /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.1 $
+ */
+
+#include <complib/cl_qmap.h>
+#include <complib/cl_debug.h>
+#include <vendor/osm_vendor_api.h>
+#include <vendor/osm_vendor_sa_api.h>
+#include "ibtrapgen.h"
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_helper.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 );
+  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%" 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_DEBUG,
+            "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_DIR;
+  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",p_ibtrapgen->p_opt->sm_lid);
+  mad_addr.dest_lid = cl_ntoh16(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/trunk/ulp/opensm/user/ibtrapgen/ibtrapgen.h b/trunk/ulp/opensm/user/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/trunk/ulp/opensm/user/ibtrapgen/main.c b/trunk/ulp/opensm/user/ibtrapgen/main.c
new file mode 100644 (file)
index 0000000..bb23326
--- /dev/null
@@ -0,0 +1,463 @@
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+  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;
+}
+
+/**********************************************************************
+ **********************************************************************/
+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/trunk/ulp/opensm/user/include/complib/cl_byteswap.h b/trunk/ulp/opensm/user/include/complib/cl_byteswap.h
new file mode 100644 (file)
index 0000000..2ba5a77
--- /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$
+ */
+
+
+
+/*
+ * 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/trunk/ulp/opensm/user/include/complib/cl_signal_osd.h b/trunk/ulp/opensm/user/include/complib/cl_signal_osd.h
new file mode 100644 (file)
index 0000000..dedd99a
--- /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 47 2005-05-30 18:00:40Z 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/trunk/ulp/opensm/user/include/iba/ib_types.h b/trunk/ulp/opensm/user/include/iba/ib_types.h
new file mode 100644 (file)
index 0000000..9bd0c18
--- /dev/null
@@ -0,0 +1,9548 @@
+/*
+ * 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 a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or 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 3155 2005-08-22 12:09:34Z yael $
+ */
+
+
+#if !defined(__IB_TYPES_H__)
+#define __IB_TYPES_H__
+
+#include <complib/cl_types.h>
+#include <complib/cl_byteswap.h>
+#include <complib/cl_memory.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 defined( WIN32 ) || defined( _WIN64 )
+    #if defined( EXPORT_AL_SYMBOLS )
+         #define AL_EXPORT     __declspec(dllexport)
+    #else
+         #define AL_EXPORT     __declspec(dllimport)
+    #endif
+
+    #ifdef CL_KERNEL
+        #define AL_API
+        #define AL_INLINE      static inline
+    #else
+        #define AL_API         __stdcall
+        #define AL_INLINE      AL_EXPORT inline
+        /* Defined for some unique access function that are defined only in osm ib_types */
+        #define OSM_INLINE static inline
+    #endif     /* CL_KERNEL */
+#else
+    #define AL_EXPORT  extern
+    #define AL_INLINE  static inline
+    #define OSM_INLINE static inline
+    #define AL_API
+    #define __ptr64
+#endif
+
+
+
+/****h* IBA Base/Constants
+* NAME
+*      Constants
+*
+* DESCRIPTION
+*      The following constants are used throughout the IBA code base.
+*
+*      Definitions are from the InfiniBand Architecture Specification v1.1
+*
+*********/
+
+/****d* IBA Base: Constants/MAD_BLOCK_SIZE
+* NAME
+*      MAD_BLOCK_SIZE
+*
+* DESCRIPTION
+*      Size of a non-RMPP MAD datagram.
+*
+* SOURCE
+*/
+#define MAD_BLOCK_SIZE                                         256
+/**********/
+
+/****d* IBA Base: Constants/MAD_RMPP_HDR_SIZE
+* NAME
+*      MAD_RMPP_HDR_SIZE
+*
+* DESCRIPTION
+*      Size of an RMPP header, including the common MAD header.
+*
+* SOURCE
+*/
+#define MAD_RMPP_HDR_SIZE                                      36
+/**********/
+
+/****d* IBA Base: Constants/MAD_RMPP_DATA_SIZE
+* NAME
+*      MAD_RMPP_DATA_SIZE
+*
+* DESCRIPTION
+*      Size of an RMPP transaction data section.
+*
+* SOURCE
+*/
+#define MAD_RMPP_DATA_SIZE             (MAD_BLOCK_SIZE - MAD_RMPP_HDR_SIZE)
+/**********/
+
+/****d* IBA Base: Constants/MAD_BLOCK_GRH_SIZE
+* NAME
+*      MAD_BLOCK_GRH_SIZE
+*
+* DESCRIPTION
+*      Size of a MAD datagram, including the GRH.
+*
+* SOURCE
+*/
+#define MAD_BLOCK_GRH_SIZE                                     296
+/**********/
+
+/****d* IBA Base: Constants/IB_LID_PERMISSIVE
+* NAME
+*      IB_LID_PERMISSIVE
+*
+* DESCRIPTION
+*      Permissive LID
+*
+* SOURCE
+*/
+#define IB_LID_PERMISSIVE                                      0xFFFF
+/**********/
+
+/****d* IBA Base: Constants/IB_DEFAULT_PKEY
+* NAME
+*      IB_DEFAULT_PKEY
+*
+* DESCRIPTION
+*      P_Key value for the default partition.
+*
+* SOURCE
+*/
+#define IB_DEFAULT_PKEY                                                0xFFFF
+/**********/
+
+/****d* IBA Base: Constants/IB_QP1_WELL_KNOWN_Q_KEY
+* NAME
+*      IB_QP1_WELL_KNOWN_Q_KEY
+*
+* DESCRIPTION
+*      Well-known Q_Key for QP1 privileged mode access (15.4.2).
+*
+* SOURCE
+*/
+#define IB_QP1_WELL_KNOWN_Q_KEY                                CL_NTOH32(0x80010000)
+/*********/
+
+#define IB_QP0                                                         0
+#define IB_QP1                                                         CL_NTOH32(1)
+
+#define IB_QP_PRIVILEGED_Q_KEY                         CL_NTOH32(0x80000000)
+
+/****d* IBA Base: Constants/IB_LID_UCAST_START
+* NAME
+*      IB_LID_UCAST_START
+*
+* DESCRIPTION
+*      Lowest valid unicast LID value.
+*
+* SOURCE
+*/
+#define IB_LID_UCAST_START_HO                          0x0001
+#define IB_LID_UCAST_START                                     (CL_HTON16(IB_LID_UCAST_START_HO))
+/**********/
+
+/****d* IBA Base: Constants/IB_LID_UCAST_END
+* NAME
+*      IB_LID_UCAST_END
+*
+* DESCRIPTION
+*      Highest valid unicast LID value.
+*
+* SOURCE
+*/
+#define IB_LID_UCAST_END_HO                                    0xBFFF
+#define IB_LID_UCAST_END                                       (CL_HTON16(IB_LID_UCAST_END_HO))
+/**********/
+
+/****d* IBA Base: Constants/IB_LID_MCAST_START
+* NAME
+*      IB_LID_MCAST_START
+*
+* DESCRIPTION
+*      Lowest valid multicast LID value.
+*
+* SOURCE
+*/
+#define IB_LID_MCAST_START_HO                          0xC000
+#define IB_LID_MCAST_START                                     (CL_HTON16(IB_LID_MCAST_START_HO))
+/**********/
+
+/****d* IBA Base: Constants/IB_LID_MCAST_END
+* NAME
+*      IB_LID_MCAST_END
+*
+* DESCRIPTION
+*      Highest valid multicast LID value.
+*
+* SOURCE
+*/
+#define IB_LID_MCAST_END_HO                                    0xFFFE
+#define IB_LID_MCAST_END                                       (CL_HTON16(IB_LID_MCAST_END_HO))
+/**********/
+
+/****d* IBA Base: Constants/IB_DEFAULT_SUBNET_PREFIX
+* NAME
+*      IB_DEFAULT_SUBNET_PREFIX
+*
+* DESCRIPTION
+*      Default subnet GID prefix.
+*
+* SOURCE
+*/
+#define IB_DEFAULT_SUBNET_PREFIX                       (CL_HTON64(0xFE80000000000000ULL))
+/**********/
+
+/****d* IBA Base: Constants/IB_NODE_NUM_PORTS_MAX
+* NAME
+*      IB_NODE_NUM_PORTS_MAX
+*
+* DESCRIPTION
+*      Maximum number of ports in a single node (14.2.5.7).
+* SOURCE
+*/
+#define IB_NODE_NUM_PORTS_MAX                          0xFE
+/**********/
+
+/****d* IBA Base: Constants/IB_INVALID_PORT_NUM
+* NAME
+*      IB_INVALID_PORT_NUM
+*
+* DESCRIPTION
+*      Value used to indicate an invalid port number (14.2.5.10).
+*
+* SOURCE
+*/
+#define IB_INVALID_PORT_NUM                                    0xFF
+/*********/
+
+/****d* IBA Base: Constants/IB_SUBNET_PATH_HOPS_MAX
+* NAME
+*      IB_SUBNET_PATH_HOPS_MAX
+*
+* DESCRIPTION
+*      Maximum number of directed route switch hops in a subnet (14.2.1.2).
+*
+* SOURCE
+*/
+#define IB_SUBNET_PATH_HOPS_MAX                                64
+/*********/
+
+/****d* IBA Base: Constants/IB_PKEY_MAX_BLOCKS
+* NAME
+*      IB_PKEY_MAX_BLOCKS
+*
+* DESCRIPTION
+*      Maximum number of PKEY blocks (14.2.5.7).
+*
+* SOURCE
+*/
+#define IB_PKEY_MAX_BLOCKS                                     2048
+/*********/
+
+/****d* IBA Base: Constants/IB_MCAST_MAX_BLOCK_ID
+* NAME
+*      IB_MCAST_MAX_BLOCK_ID
+*
+* DESCRIPTION
+*      Maximum number of Multicast port mask blocks
+*
+* SOURCE
+*/
+#define IB_MCAST_MAX_BLOCK_ID                          511
+/*********/
+
+/****d* IBA Base: Constants/IB_MCAST_BLOCK_ID_MASK_HO
+* NAME
+*      IB_MCAST_BLOCK_ID_MASK_HO
+*
+* DESCRIPTION
+*      Mask (host order) to recover the Multicast block ID.
+*
+* SOURCE
+*/
+#define IB_MCAST_BLOCK_ID_MASK_HO                      0x000001FF
+/*********/
+
+/****d* IBA Base: Constants/IB_MCAST_BLOCK_SIZE
+* NAME
+*      IB_MCAST_BLOCK_SIZE
+*
+* DESCRIPTION
+*      Number of port mask entries in a multicast forwarding table block.
+*
+* SOURCE
+*/
+#define IB_MCAST_BLOCK_SIZE                                    32
+/*********/
+
+/****d* IBA Base: Constants/IB_MCAST_MASK_SIZE
+* NAME
+*      IB_MCAST_MASK_SIZE
+*
+* DESCRIPTION
+*      Number of port mask bits in each entry in the multicast forwarding table.
+*
+* SOURCE
+*/
+#define IB_MCAST_MASK_SIZE                                     16
+/*********/
+
+/****d* IBA Base: Constants/IB_MCAST_POSITION_MASK_HO
+* NAME
+*      IB_MCAST_POSITION_MASK_HO
+*
+* DESCRIPTION
+*      Mask (host order) to recover the multicast block position.
+*
+* SOURCE
+*/
+#define IB_MCAST_POSITION_MASK_HO                              0xF0000000
+/*********/
+
+/****d* IBA Base: Constants/IB_MCAST_POSITION_MAX
+* NAME
+*      IB_MCAST_POSITION_MAX
+*
+* DESCRIPTION
+*      Maximum value for the multicast block position.
+*
+* SOURCE
+*/
+#define IB_MCAST_POSITION_MAX                          0xF
+/*********/
+
+/****d* IBA Base: Constants/IB_MCAST_POSITION_SHIFT
+* NAME
+*      IB_MCAST_POSITION_SHIFT
+*
+* DESCRIPTION
+*      Shift value to normalize the multicast block position value.
+*
+* SOURCE
+*/
+#define IB_MCAST_POSITION_SHIFT                                28
+/*********/
+
+/****d* IBA Base: Constants/IB_PKEY_ENTRIES_MAX
+* NAME
+*      IB_PKEY_ENTRIES_MAX
+*
+* DESCRIPTION
+*      Maximum number of PKEY entries per port (14.2.5.7).
+*
+* SOURCE
+*/
+#define IB_PKEY_ENTRIES_MAX (IB_PKEY_MAX_BLOCKS * IB_NUM_PKEY_ELEMENTS_IN_BLOCK)
+/*********/
+
+/****d* IBA Base: Constants/IB_PKEY_BASE_MASK
+* NAME
+*      IB_PKEY_BASE_MASK
+*
+* DESCRIPTION
+*      Masks for the base P_Key value given a P_Key Entry.
+*
+* SOURCE
+*/
+#define IB_PKEY_BASE_MASK                                      (CL_NTOH16(0x7FFF))
+/*********/
+
+/****d* IBA Base: Constants/IB_PKEY_TYPE_MASK
+* NAME
+*      IB_PKEY_TYPE_MASK
+*
+* DESCRIPTION
+*      Masks for the P_Key membership type given a P_Key Entry.
+*
+* SOURCE
+*/
+#define IB_PKEY_TYPE_MASK                                      (CL_NTOH16(0x8000))
+/*********/
+
+/****d* IBA Base: Constants/IB_MCLASS_SUBN_LID
+* NAME
+*      IB_MCLASS_SUBN_LID
+*
+* DESCRIPTION
+*      Subnet Management Class, Subnet Manager LID routed (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_SUBN_LID                                     0x01
+/**********/
+
+/****d* IBA Base: Constants/IB_MCLASS_SUBN_DIR
+* NAME
+*      IB_MCLASS_SUBN_DIR
+*
+* DESCRIPTION
+*      Subnet Management Class, Subnet Manager directed route (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_SUBN_DIR                                     0x81
+/**********/
+
+/****d* IBA Base: Constants/IB_MCLASS_SUBN_ADM
+* NAME
+*      IB_MCLASS_SUBN_ADM
+*
+* DESCRIPTION
+*      Subnet Management Class, Subnet Administration (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_SUBN_ADM                                     0x03
+/**********/
+
+/****d* IBA Base: Constants/IB_MCLASS_PERF
+* NAME
+*      IB_MCLASS_PERF
+*
+* DESCRIPTION
+*      Subnet Management Class, Performance Manager (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_PERF                                         0x04
+/**********/
+
+/****d* IBA Base: Constants/IB_MCLASS_BM
+* NAME
+*      IB_MCLASS_BM
+*
+* DESCRIPTION
+*      Subnet Management Class, Baseboard Manager (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_BM                                           0x05
+/**********/
+
+/****d* IBA Base: Constants/IB_MCLASS_DEV_MGMT
+* NAME
+*      IB_MCLASS_DEV_MGMT
+*
+* DESCRIPTION
+*      Subnet Management Class, Device Management (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_DEV_MGMT                                     0x06
+/**********/
+
+/****d* IBA Base: Constants/IB_MCLASS_COMM_MGMT
+* NAME
+*      IB_MCLASS_COMM_MGMT
+*
+* DESCRIPTION
+*      Subnet Management Class, Communication Management (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_COMM_MGMT                                    0x07
+/**********/
+
+/****d* IBA Base: Constants/IB_MCLASS_SNMP
+* NAME
+*      IB_MCLASS_SNMP
+*
+* DESCRIPTION
+*      Subnet Management Class, SNMP Tunneling (13.4.4)
+*
+* SOURCE
+*/
+#define IB_MCLASS_SNMP                                         0x08
+/**********/
+
+/****d* IBA Base: Constants/IB_MCLASS_VENDOR_LOW_RANGE_MIN
+* NAME
+*      IB_MCLASS_VENDOR_LOW_RANGE_MIN
+*
+* DESCRIPTION
+*      Subnet Management Class, Vendor Specific Low Range Start
+*
+* SOURCE
+*/
+#define IB_MCLASS_VENDOR_LOW_RANGE_MIN 0x09
+/**********/
+
+/****d* IBA Base: Constants/IB_MCLASS_VENDOR_LOW_RANGE_MAX
+* NAME
+*      IB_MCLASS_VENDOR_LOW_RANGE_MAX
+*
+* DESCRIPTION
+*      Subnet Management Class, Vendor Specific Low Range End
+*
+* SOURCE
+*/
+#define IB_MCLASS_VENDOR_LOW_RANGE_MAX 0x0f
+/**********/
+
+/****d* IBA Base: Constants/IB_MCLASS_VENDOR_HIGH_RANGE_MIN
+* NAME
+*      IB_MCLASS_VENDOR_HIGH_RANGE_MIN
+*
+* DESCRIPTION
+*      Subnet Management Class, Vendor Specific High Range Start
+*
+* SOURCE
+*/
+#define IB_MCLASS_VENDOR_HIGH_RANGE_MIN 0x30
+/**********/
+
+/****d* IBA Base: Constants/IB_MCLASS_VENDOR_HIGH_RANGE_MAX
+* NAME
+*      IB_MCLASS_VENDOR_HIGH_RANGE_MAX
+*
+* DESCRIPTION
+*      Subnet Management Class, Vendor Specific High Range End
+*
+* SOURCE
+*/
+#define IB_MCLASS_VENDOR_HIGH_RANGE_MAX 0x4f
+/**********/
+
+/****f* IBA Base: Types/ib_class_is_vendor_specific_low
+* NAME
+*      ib_class_is_vendor_specific_low
+*
+* DESCRIPTION
+*      Indicitates if the Class Code if a vendor specific class from 
+*  the low range
+*
+* SYNOPSIS
+*/
+AL_INLINE boolean_t     AL_API
+ib_class_is_vendor_specific_low(
+       IN              const   uint8_t class_code )
+{
+       return( (class_code >= IB_MCLASS_VENDOR_LOW_RANGE_MIN) &&
+           (class_code <= IB_MCLASS_VENDOR_LOW_RANGE_MAX)) ;
+}
+/*
+* PARAMETERS
+*      class_code
+*              [in] The Management Datagram Class Code
+*
+* RETURN VALUE
+*      TRUE if the class is in the Low range of Vendor Specific MADs 
+*      FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* IB_MCLASS_VENDOR_LOW_RANGE_MIN, IB_MCLASS_VENDOR_LOW_RANGE_MAX
+*********/
+
+/****f* IBA Base: Types/ib_class_is_vendor_specific_high
+* NAME
+*      ib_class_is_vendor_specific_high
+*
+* DESCRIPTION
+*      Indicitates if the Class Code if a vendor specific class from 
+*  the high range
+*
+* SYNOPSIS
+*/
+AL_INLINE boolean_t     AL_API
+ib_class_is_vendor_specific_high(
+       IN              const   uint8_t class_code )
+{
+       return( (class_code >= IB_MCLASS_VENDOR_HIGH_RANGE_MIN) &&
+           (class_code <= IB_MCLASS_VENDOR_HIGH_RANGE_MAX)) ;
+}
+/*
+* PARAMETERS
+*      class_code
+*              [in] The Management Datagram Class Code
+*
+* RETURN VALUE
+*      TRUE if the class is in the High range of Vendor Specific MADs 
+*      FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* IB_MCLASS_VENDOR_HIGH_RANGE_MIN, IB_MCLASS_VENDOR_HIGH_RANGE_MAX
+*********/
+
+
+/****f* IBA Base: Types/ib_class_is_vendor_specific
+* NAME
+*      ib_class_is_vendor_specific
+*
+* DESCRIPTION
+*      Indicitates if the Class Code if a vendor specific class
+*
+* SYNOPSIS
+*/
+AL_INLINE boolean_t     AL_API
+ib_class_is_vendor_specific(
+       IN              const   uint8_t class_code )
+{
+  return( ib_class_is_vendor_specific_low(class_code) ||
+                        ib_class_is_vendor_specific_high(class_code) );
+}
+/*
+* PARAMETERS
+*      class_code
+*              [in] The Management Datagram Class Code
+*
+* RETURN VALUE
+*      TRUE if the class is a Vendor Specific MAD
+*      FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*  ib_class_is_vendor_specific_low, ib_class_is_vendor_specific_high
+*********/
+
+/*
+ *     MAD methods
+ */
+/****d* IBA Base: Constants/IB_MAX_METHOD
+* NAME
+*      IB_MAX_METHOD
+*
+* DESCRIPTION
+*      Total number of methods available to a class, not including the R-bit.
+*
+* SOURCE
+*/
+#define IB_MAX_METHODS                                         128
+/**********/
+/****d* IBA Base: Constants/IB_MAD_METHOD_RESP_MASK
+* NAME
+*      IB_MAD_METHOD_RESP_MASK
+*
+* DESCRIPTION
+*      Response mask to extract 'R' bit from the method field. (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_RESP_MASK                                0x80
+/**********/
+/****d* IBA Base: Constants/IB_MAD_METHOD_GET
+* NAME
+*      IB_MAD_METHOD_GET
+*
+* DESCRIPTION
+*      Get() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_GET                                      0x01
+/**********/
+/****d* IBA Base: Constants/IB_MAD_METHOD_SET
+* NAME
+*      IB_MAD_METHOD_SET
+*
+* DESCRIPTION
+*      Set() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_SET                                      0x02
+/**********/
+/****d* IBA Base: Constants/IB_MAD_METHOD_GET_RESP
+* NAME
+*      IB_MAD_METHOD_GET_RESP
+*
+* DESCRIPTION
+*      GetResp() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_GET_RESP                         0x81
+/**********/
+
+#define IB_MAD_METHOD_DELETE                           0x15
+
+/****d* IBA Base: Constants/IB_MAD_METHOD_GETTABLE
+* NAME
+*      IB_MAD_METHOD_GETTABLE
+*
+* DESCRIPTION
+*      SubnAdmGetTable() Method (15.2.2)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_GETTABLE                         0x12
+
+/**********/
+/****d* IBA Base: Constants/IB_MAD_METHOD_GETTABLE_RESP
+* NAME
+*      IB_MAD_METHOD_GETTABLE_RESP
+*
+* DESCRIPTION
+*      SubnAdmGetTableResp() Method (15.2.2)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_GETTABLE_RESP                    0x92
+
+/**********/
+
+#define IB_MAD_METHOD_GETTRACETABLE                    0x13
+#define IB_MAD_METHOD_GETMULTI                         0x14
+#define IB_MAD_METHOD_GETMULTI_RESP                    0x94
+
+
+/****d* IBA Base: Constants/IB_MAD_METHOD_SEND
+* NAME
+*      IB_MAD_METHOD_SEND
+*
+* DESCRIPTION
+*      Send() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_SEND                                     0x03
+/**********/
+/****d* IBA Base: Constants/IB_MAD_METHOD_TRAP
+* NAME
+*      IB_MAD_METHOD_TRAP
+*
+* DESCRIPTION
+*      Trap() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_TRAP                                     0x05
+/**********/
+/****d* IBA Base: Constants/IB_MAD_METHOD_REPORT
+* NAME
+*      IB_MAD_METHOD_REPORT
+*
+* DESCRIPTION
+*      Report() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_REPORT                           0x06
+/**********/
+/****d* IBA Base: Constants/IB_MAD_METHOD_REPORT_RESP
+* NAME
+*      IB_MAD_METHOD_REPORT_RESP
+*
+* DESCRIPTION
+*      ReportResp() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_REPORT_RESP                      0x86
+/**********/
+/****d* IBA Base: Constants/IB_MAD_METHOD_TRAP_REPRESS
+* NAME
+*      IB_MAD_METHOD_TRAP_REPRESS
+*
+* DESCRIPTION
+*      TrapRepress() Method (13.4.5)
+*
+* SOURCE
+*/
+#define IB_MAD_METHOD_TRAP_REPRESS                     0x07
+/**********/
+/****d* IBA Base: Constants/IB_MAD_STATUS_BUSY
+* NAME
+*      IB_MAD_STATUS_BUSY
+*
+* DESCRIPTION
+*      Temporarily busy, MAD discarded (13.4.7)
+*
+* SOURCE
+*/
+#define IB_MAD_STATUS_BUSY                                     (CL_HTON16(0x0001))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_STATUS_REDIRECT
+* NAME
+*      IB_MAD_STATUS_REDIRECT
+*
+* DESCRIPTION
+*      QP Redirection required (13.4.7)
+*
+* SOURCE
+*/
+#define IB_MAD_STATUS_REDIRECT                         (CL_HTON16(0x0002))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_STATUS_UNSUP_CLASS_VER
+* NAME
+*      IB_MAD_STATUS_UNSUP_CLASS_VER
+*
+* DESCRIPTION
+*      Unsupported class version (13.4.7)
+*
+* SOURCE
+*/
+#define IB_MAD_STATUS_UNSUP_CLASS_VER          (CL_HTON16(0x0004))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_STATUS_UNSUP_METHOD
+* NAME
+*      IB_MAD_STATUS_UNSUP_METHOD
+*
+* DESCRIPTION
+*      Unsupported method (13.4.7)
+*
+* SOURCE
+*/
+#define IB_MAD_STATUS_UNSUP_METHOD                     (CL_HTON16(0x0008))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_STATUS_UNSUP_METHOD_ATTR
+* NAME
+*      IB_MAD_STATUS_UNSUP_METHOD_ATTR
+*
+* DESCRIPTION
+*      Unsupported method/attribute combination (13.4.7)
+*
+* SOURCE
+*/
+#define IB_MAD_STATUS_UNSUP_METHOD_ATTR                (CL_HTON16(0x000C))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_STATUS_INVALID_FIELD
+* NAME
+*      IB_MAD_STATUS_INVALID_FIELD
+*
+* DESCRIPTION
+*      Attribute contains one or more invalid fields (13.4.7)
+*
+* SOURCE
+*/
+#define IB_MAD_STATUS_INVALID_FIELD                    (CL_HTON16(0x001C))
+/**********/
+
+#define IB_MAD_STATUS_CLASS_MASK                       (CL_HTON16(0xFF00))
+
+#define IB_SA_MAD_STATUS_SUCCESS                       (CL_HTON16(0x0000))
+#define IB_SA_MAD_STATUS_NO_RESOURCES          (CL_HTON16(0x0100))
+#define IB_SA_MAD_STATUS_REQ_INVALID           (CL_HTON16(0x0200))
+#define IB_SA_MAD_STATUS_NO_RECORDS                    (CL_HTON16(0x0300))
+#define IB_SA_MAD_STATUS_TOO_MANY_RECORDS      (CL_HTON16(0x0400))
+#define IB_SA_MAD_STATUS_INVALID_GID           (CL_HTON16(0x0500))
+#define IB_SA_MAD_STATUS_INSUF_COMPS           (CL_HTON16(0x0600))
+
+#define IB_DM_MAD_STATUS_NO_IOC_RESP           (CL_HTON16(0x0100))
+#define IB_DM_MAD_STATUS_NO_SVC_ENTRIES                (CL_HTON16(0x0200))
+#define IB_DM_MAD_STATUS_IOC_FAILURE           (CL_HTON16(0x8000))
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_CLASS_PORT_INFO
+* NAME
+*      IB_MAD_ATTR_CLASS_PORT_INFO
+*
+* DESCRIPTION
+*      ClassPortInfo attribute (13.4.8)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_CLASS_PORT_INFO                    (CL_NTOH16(0x0001))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_NOTICE
+* NAME
+*      IB_MAD_ATTR_NOTICE
+*
+* DESCRIPTION
+*      Notice attribute (13.4.8)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_NOTICE                                     (CL_NTOH16(0x0002))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_INFORM_INFO
+* NAME
+*      IB_MAD_ATTR_INFORM_INFO
+*
+* DESCRIPTION
+*      InformInfo attribute (13.4.8)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_INFORM_INFO                                (CL_NTOH16(0x0003))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_NODE_DESC
+* NAME
+*      IB_MAD_ATTR_NODE_DESC
+*
+* DESCRIPTION
+*      NodeDescription attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_NODE_DESC                          (CL_NTOH16(0x0010))
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORT_SMPL_CTRL
+* NAME
+*      IB_MAD_ATTR_PORT_SMPL_CTRL
+*
+* DESCRIPTION
+*      NodeDescription attribute (16.1.2)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PORT_SMPL_CTRL                     (CL_NTOH16(0x0010))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_NODE_INFO
+* NAME
+*      IB_MAD_ATTR_NODE_INFO
+*
+* DESCRIPTION
+*      NodeInfo attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_NODE_INFO                          (CL_NTOH16(0x0011))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORT_SMPL_RSLT
+* NAME
+*      IB_MAD_ATTR_PORT_SMPL_RSLT
+*
+* DESCRIPTION
+*      NodeInfo attribute (16.1.2)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PORT_SMPL_RSLT                     (CL_NTOH16(0x0011))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_SWITCH_INFO
+* NAME
+*      IB_MAD_ATTR_SWITCH_INFO
+*
+* DESCRIPTION
+*      SwitchInfo attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SWITCH_INFO                                (CL_NTOH16(0x0012))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORT_CNTRS
+* NAME
+*      IB_MAD_ATTR_PORT_CNTRS
+*
+* DESCRIPTION
+*      SwitchInfo attribute (16.1.2)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PORT_CNTRS                         (CL_NTOH16(0x0012))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_GUID_INFO
+* NAME
+*      IB_MAD_ATTR_GUID_INFO
+*
+* DESCRIPTION
+*      GUIDInfo attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_GUID_INFO                          (CL_NTOH16(0x0014))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORT_INFO
+* NAME
+*      IB_MAD_ATTR_PORT_INFO
+*
+* DESCRIPTION
+*      PortInfo attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PORT_INFO                          (CL_NTOH16(0x0015))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_P_KEY_TABLE
+* NAME
+*      IB_MAD_ATTR_P_KEY_TABLE
+*
+* DESCRIPTION
+*      PartitionTable attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_P_KEY_TABLE                                (CL_NTOH16(0x0016))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_SLVL_TABLE
+* NAME
+*      IB_MAD_ATTR_SLVL_TABLE
+*
+* DESCRIPTION
+*      SL VL Mapping Table attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SLVL_TABLE                         (CL_NTOH16(0x0017))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_VL_ARBITRATION
+* NAME
+*      IB_MAD_ATTR_VL_ARBITRATION
+*
+* DESCRIPTION
+*      VL Arbitration Table attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_VL_ARBITRATION                     (CL_NTOH16(0x0018))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_LIN_FWD_TBL
+* NAME
+*      IB_MAD_ATTR_LIN_FWD_TBL
+*
+* DESCRIPTION
+*      Switch linear forwarding table
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_LIN_FWD_TBL                                (CL_NTOH16(0x0019))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_RND_FWD_TBL
+* NAME
+*      IB_MAD_ATTR_RND_FWD_TBL
+*
+* DESCRIPTION
+*      Switch random forwarding table
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_RND_FWD_TBL                                (CL_NTOH16(0x001A))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_MCAST_FWD_TBL
+* NAME
+*      IB_MAD_ATTR_MCAST_FWD_TBL
+*
+* DESCRIPTION
+*      Switch multicast forwarding table
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_MCAST_FWD_TBL                      (CL_NTOH16(0x001B))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_NODE_RECORD
+* NAME
+*      IB_MAD_ATTR_NODE_RECORD
+*
+* DESCRIPTION
+*      NodeRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_NODE_RECORD                                (CL_NTOH16(0x0011))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORTINFO_RECORD
+* NAME
+*      IB_MAD_ATTR_PORTINFO_RECORD
+*
+* DESCRIPTION
+*      PortInfoRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PORTINFO_RECORD                    (CL_NTOH16(0x0012))
+/**********/
+
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_LINK_RECORD
+* NAME
+*      IB_MAD_ATTR_LINK_RECORD
+*
+* DESCRIPTION
+*      LinkRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_LINK_RECORD                                (CL_NTOH16(0x0020))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_SM_INFO
+* NAME
+*      IB_MAD_ATTR_SM_INFO
+*
+* DESCRIPTION
+*      SMInfo attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SM_INFO                                    (CL_NTOH16(0x0020))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_SMINFO_RECORD
+* NAME
+*      IB_MAD_ATTR_SMINFO_RECORD
+*
+* DESCRIPTION
+*      SmInfoRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SMINFO_RECORD                      (CL_NTOH16(0x0018))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_VENDOR_DIAG
+* NAME
+*      IB_MAD_ATTR_VENDOR_DIAG
+*
+* DESCRIPTION
+*      VendorDiag attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_VENDOR_DIAG                                (CL_NTOH16(0x0030))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_LED_INFO
+* NAME
+*      IB_MAD_ATTR_LED_INFO
+*
+* DESCRIPTION
+*      LedInfo attribute (14.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_LED_INFO                           (CL_NTOH16(0x0031))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_SERVICE_RECORD
+* NAME
+*      IB_MAD_ATTR_SERVICE_RECORD
+*
+* DESCRIPTION
+*      ServiceRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SERVICE_RECORD                     (CL_NTOH16(0x0031))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_LFT_RECORD
+* NAME
+*      IB_MAD_ATTR_LFT_RECORD
+*
+* DESCRIPTION
+*      LinearForwardingRecord attribute (15.2.5.6)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_LFT_RECORD                 (CL_NTOH16(0x0015))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_PKEYTBL_RECORD
+* NAME
+*      IB_MAD_ATTR_PKEYTBL_RECORD
+*
+* DESCRIPTION
+*      P-KEY table attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PKEY_TBL_RECORD                    (CL_NTOH16(0x0033))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_PATH_RECORD
+* NAME
+*      IB_MAD_ATTR_PATH_RECORD
+*
+* DESCRIPTION
+*      PathRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PATH_RECORD                                (CL_NTOH16(0x0035))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_VLARB_RECORD
+* NAME
+*      IB_MAD_ATTR_VLARB_RECORD
+*
+* DESCRIPTION
+*      VL Arbitration Table attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_VLARB_RECORD                       (CL_NTOH16(0x0036))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_SLVL_RECORD
+* NAME
+*      IB_MAD_ATTR_SLVL_RECORD
+*
+* DESCRIPTION
+*      VSLtoL Map Table attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SLVL_RECORD                                (CL_NTOH16(0x0013))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_MCMEMBER_RECORD
+* NAME
+*      IB_MAD_ATTR_MCMEMBER_RECORD
+*
+* DESCRIPTION
+*      MCMemberRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_MCMEMBER_RECORD                    (CL_NTOH16(0x0038))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_TRACE_RECORD
+* NAME
+*      IB_MAD_ATTR_MTRACE_RECORD
+*
+* DESCRIPTION
+*      TraceRecord attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_TRACE_RECORD                       (CL_NTOH16(0x0039))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_MULTIPATH_RECORD
+* NAME
+*      IB_MAD_ATTR_MULTIPATH_RECORD
+*
+* DESCRIPTION
+*      MultiPath attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_MULTIPATH_RECORD                   (CL_NTOH16(0x003A))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_SVC_ASSOCIATION_RECORD
+* NAME
+*      IB_MAD_ATTR_SVC_ASSOCIATION_RECORD
+*
+* DESCRIPTION
+*      Service Association attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SVC_ASSOCIATION_RECORD             (CL_NTOH16(0x003B))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_IO_UNIT_INFO
+* NAME
+*      IB_MAD_ATTR_IO_UNIT_INFO
+*
+* DESCRIPTION
+*      IOUnitInfo attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_IO_UNIT_INFO                       (CL_NTOH16(0x0010))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_IO_CONTROLLER_PROFILE
+* NAME
+*      IB_MAD_ATTR_IO_CONTROLLER_PROFILE
+*
+* DESCRIPTION
+*      IOControllerProfile attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_IO_CONTROLLER_PROFILE      (CL_NTOH16(0x0011))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_SERVICE_ENTRIES
+* NAME
+*      IB_MAD_ATTR_SERVICE_ENTRIES
+*
+* DESCRIPTION
+*      ServiceEntries attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SERVICE_ENTRIES                    (CL_NTOH16(0x0012))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_DIAGNOSTIC_TIMEOUT
+* NAME
+*      IB_MAD_ATTR_DIAGNOSTIC_TIMEOUT
+*
+* DESCRIPTION
+*      DiagnosticTimeout attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_DIAGNOSTIC_TIMEOUT         (CL_NTOH16(0x0020))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_PREPARE_TO_TEST
+* NAME
+*      IB_MAD_ATTR_PREPARE_TO_TEST
+*
+* DESCRIPTION
+*      PrepareToTest attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_PREPARE_TO_TEST                    (CL_NTOH16(0x0021))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_TEST_DEVICE_ONCE
+* NAME
+*      IB_MAD_ATTR_TEST_DEVICE_ONCE
+*
+* DESCRIPTION
+*      TestDeviceOnce attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_TEST_DEVICE_ONCE           (CL_NTOH16(0x0022))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_TEST_DEVICE_LOOP
+* NAME
+*      IB_MAD_ATTR_TEST_DEVICE_LOOP
+*
+* DESCRIPTION
+*      TestDeviceLoop attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_TEST_DEVICE_LOOP           (CL_NTOH16(0x0023))
+/**********/
+/****d* IBA Base: Constants/IB_MAD_ATTR_DIAG_CODE
+* NAME
+*      IB_MAD_ATTR_DIAG_CODE
+*
+* DESCRIPTION
+*      DiagCode attribute (16.3.3)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_DIAG_CODE                          (CL_NTOH16(0x0024))
+/**********/
+
+/****d* IBA Base: Constants/IB_MAD_ATTR_SVC_ASSOCIATION_RECORD
+* NAME
+*      IB_MAD_ATTR_SVC_ASSOCIATION_RECORD
+*
+* DESCRIPTION
+*      Service Association attribute (15.2.5)
+*
+* SOURCE
+*/
+#define IB_MAD_ATTR_SVC_ASSOCIATION_RECORD     (CL_NTOH16(0x003B))
+/**********/
+/****d* IBA Base: Constants/IB_NODE_TYPE_CA
+* NAME
+*      IB_NODE_TYPE_CA
+*
+* DESCRIPTION
+*      Encoded generic node type used in MAD attributes (13.4.8.2)
+*
+* SOURCE
+*/
+#define IB_NODE_TYPE_CA                                                0x01
+/**********/
+/****d* IBA Base: Constants/IB_NODE_TYPE_SWITCH
+* NAME
+*      IB_NODE_TYPE_SWITCH
+*
+* DESCRIPTION
+*      Encoded generic node type used in MAD attributes (13.4.8.2)
+*
+* SOURCE
+*/
+#define IB_NODE_TYPE_SWITCH                                    0x02
+/**********/
+/****d* IBA Base: Constants/IB_NODE_TYPE_ROUTER
+* NAME
+*      IB_NODE_TYPE_ROUTER
+*
+* DESCRIPTION
+*      Encoded generic node type used in MAD attributes (13.4.8.2)
+*
+* SOURCE
+*/
+#define IB_NODE_TYPE_ROUTER                                    0x03
+/**********/
+
+/****d* IBA Base: Constants/IB_NOTICE_NODE_TYPE_CA
+* NAME
+*      IB_NOTICE_NODE_TYPE_CA
+*
+* DESCRIPTION
+*      Encoded generic node type used in MAD attributes (13.4.8.2)
+*
+* SOURCE
+*/
+#define IB_NOTICE_NODE_TYPE_CA                         (CL_NTOH32(0x000001))
+/**********/
+/****d* IBA Base: Constants/IB_NOTICE_NODE_TYPE_SWITCH
+* NAME
+*      IB_NOTICE_NODE_TYPE_SWITCH
+*
+* DESCRIPTION
+*      Encoded generic node type used in MAD attributes (13.4.8.2)
+*
+* SOURCE
+*/
+#define IB_NOTICE_NODE_TYPE_SWITCH                     (CL_NTOH32(0x000002))
+/**********/
+/****d* IBA Base: Constants/IB_NOTICE_NODE_TYPE_ROUTER
+* NAME
+*      IB_NOTICE_NODE_TYPE_ROUTER
+*
+* DESCRIPTION
+*      Encoded generic node type used in MAD attributes (13.4.8.2)
+*
+* SOURCE
+*/
+#define IB_NOTICE_NODE_TYPE_ROUTER                     (CL_NTOH32(0x000003))
+/**********/
+/****d* IBA Base: Constants/IB_NOTICE_NODE_TYPE_SUBN_MGMT
+* NAME
+*      IB_NOTICE_NODE_TYPE_SUBN_MGMT
+*
+* DESCRIPTION
+*      Encoded generic node type used in MAD attributes (13.4.8.2).
+*      Note that this value is not defined for the NodeType field
+*      of the NodeInfo attribute (14.2.5.3).
+*
+* SOURCE
+*/
+#define IB_NOTICE_NODE_TYPE_SUBN_MGMT          (CL_NTOH32(0x000004))
+/**********/
+
+/****d* IBA Base: Constants/IB_MTU_LEN_TYPE
+* NAME
+*      IB_MTU_LEN_TYPE
+*
+* DESCRIPTION
+*      Encoded path MTU.
+*              1: 256
+*              2: 512
+*              3: 1024
+*              4: 2048
+*              5: 4096
+*              others: reserved
+*
+* SOURCE
+*/
+#define IB_MTU_LEN_256                                                 1
+#define IB_MTU_LEN_512                                                 2
+#define IB_MTU_LEN_1024                                                        3
+#define IB_MTU_LEN_2048                                                        4
+#define IB_MTU_LEN_4096                                                        5
+#define IB_MAX_MTU                        5
+/**********/
+
+/****d* IBA Base: Constants/IB_PATH_SELECTOR_TYPE
+* NAME
+*      IB_PATH_SELECTOR_TYPE
+*
+* DESCRIPTION
+*      Path selector.
+*              0: greater than rate specified
+*              1: less than rate specified
+*              2: exactly the rate specified
+*              3: largest rate available
+*
+* SOURCE
+*/
+#define IB_PATH_SELECTOR_GREATER_THAN          0
+#define IB_PATH_SELECTOR_LESS_THAN                     1
+#define IB_PATH_SELECTOR_EXACTLY                       2
+#define IB_PATH_SELECTOR_LARGEST                       3
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_STATE_NOTACTIVE
+* NAME
+*      IB_SMINFO_STATE_NOTACTIVE
+*
+* DESCRIPTION
+*      Encoded state value used in the SMInfo attribute.
+*
+* SOURCE
+*/
+#define IB_SMINFO_STATE_NOTACTIVE                      0
+/**********/
+/****d* IBA Base: Constants/IB_SMINFO_STATE_DISCOVERING
+* NAME
+*      IB_SMINFO_STATE_DISCOVERING
+*
+* DESCRIPTION
+*      Encoded state value used in the SMInfo attribute.
+*
+* SOURCE
+*/
+#define IB_SMINFO_STATE_DISCOVERING                    1
+/**********/
+/****d* IBA Base: Constants/IB_SMINFO_STATE_STANDBY
+* NAME
+*      IB_SMINFO_STATE_STANDBY
+*
+* DESCRIPTION
+*      Encoded state value used in the SMInfo attribute.
+*
+* SOURCE
+*/
+#define IB_SMINFO_STATE_STANDBY                                2
+/**********/
+/****d* IBA Base: Constants/IB_SMINFO_STATE_MASTER
+* NAME
+*      IB_SMINFO_STATE_MASTER
+*
+* DESCRIPTION
+*      Encoded state value used in the SMInfo attribute.
+*
+* SOURCE
+*/
+#define IB_SMINFO_STATE_MASTER                         3
+/**********/
+/****d* IBA Base: Constants/IB_PATH_REC_SELECTOR_MASK
+* NAME
+*      IB_PATH_REC_SELECTOR_MASK
+*
+* DESCRIPTION
+*      Mask for the selector field for path record MTU, rate
+*      and packet lifetime.
+*
+* SOURCE
+*/
+#define IB_PATH_REC_SELECTOR_MASK                      0xC0
+/**********/
+/****d* IBA Base: Constants/IB_PATH_REC_BASE_MASK
+* NAME
+*      IB_PATH_REC_BASE_MASK
+*
+* DESCRIPTION
+*      Mask for the base value field for path record MTU, rate
+*      and packet lifetime.
+*
+* SOURCE
+*/
+#define IB_PATH_REC_BASE_MASK                          0x3F
+/**********/
+
+/****h* IBA Base/Type Definitions
+* NAME
+*      Type Definitions
+*
+* DESCRIPTION
+*      Definitions are from the InfiniBand Architecture Specification v1.1
+*
+*********/
+/****d* IBA Base: Types/ib_net16_t
+* NAME
+*      ib_net16_t
+*
+* DESCRIPTION
+*      Defines the network ordered type for 16-bit values.
+*
+* SOURCE
+*/
+typedef uint16_t       ib_net16_t;
+/**********/
+/****d* IBA Base: Types/ib_net32_t
+* NAME
+*      ib_net32_t
+*
+* DESCRIPTION
+*      Defines the network ordered type for 32-bit values.
+*
+* SOURCE
+*/
+typedef uint32_t       ib_net32_t;
+/**********/
+/****d* IBA Base: Types/ib_net64_t
+* NAME
+*      ib_net64_t
+*
+* DESCRIPTION
+*      Defines the network ordered type for 64-bit values.
+*
+* SOURCE
+*/
+typedef uint64_t       ib_net64_t;
+/**********/
+/****d* IBA Base: Types/ib_gid_prefix_t
+* NAME
+*      ib_gid_prefix_t
+*
+* DESCRIPTION
+*
+* SOURCE
+*/
+typedef ib_net64_t             ib_gid_prefix_t;
+/**********/
+
+/****d* IBA Base: Constants/ib_link_states_t
+* NAME
+*      ib_link_states_t
+*
+* DESCRIPTION
+*      Defines the link states of a port.
+*
+* SOURCE
+*/
+#define IB_LINK_NO_CHANGE 0
+#define IB_LINK_DOWN      1
+#define IB_LINK_INIT        2
+#define IB_LINK_ARMED     3
+#define IB_LINK_ACTIVE    4
+#define IB_LINK_ACT_DEFER 5
+/**********/
+
+static const char* const __ib_node_type_str[] =
+{
+       "UNKNOWN",
+       "Channel Adapter",
+       "Switch",
+       "Router",
+       "Subnet Management"
+};
+
+/****f* IBA Base: Types/ib_get_node_type_str
+* NAME
+*      ib_get_node_type_str
+*
+* DESCRIPTION
+*      Returns a string for the specified node type.
+*
+* SYNOPSIS
+*/
+AL_INLINE const char*    AL_API
+ib_get_node_type_str(
+       IN uint32_t node_type )
+{
+       if( node_type >= IB_NOTICE_NODE_TYPE_ROUTER )
+               node_type = 0;
+       return( __ib_node_type_str[node_type] );
+}
+/*
+* PARAMETERS
+*      node_type
+*              [in] Encoded node type as returned in the NodeInfo attribute.
+
+* RETURN VALUES
+*      Pointer to the node type string.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_node_info_t
+*********/
+
+static const char* const __ib_port_state_str[] =
+{
+       "No State Change (NOP)",
+       "DOWN",
+       "INIT",
+       "ARMED",
+       "ACTIVE",
+       "ACTDEFER",
+       "UNKNOWN"
+};
+
+/****f* IBA Base: Types/ib_get_port_state_str
+* NAME
+*      ib_get_port_state_str
+*
+* DESCRIPTION
+*      Returns a string for the specified port state.
+*
+* SYNOPSIS
+*/
+AL_INLINE const char*    AL_API
+ib_get_port_state_str(
+       IN                              uint8_t                                         port_state )
+{
+       if( port_state > IB_LINK_ACTIVE )
+               port_state = IB_LINK_ACTIVE + 1;
+       return( __ib_port_state_str[port_state] );
+}
+/*
+* PARAMETERS
+*      node_type
+*              [in] Encoded port state as returned in the PortInfo attribute.
+
+* RETURN VALUES
+*      Pointer to the port state string.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_port_info_t
+*********/
+
+/****f* IBA Base: Types/ib_get_port_state_from_str
+* NAME
+*      ib_get_port_state_from_str
+*
+* DESCRIPTION
+*      Returns a string for the specified port state.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t    AL_API
+ib_get_port_state_from_str(
+       IN                              char*                                           p_port_state_str )
+{
+       if( !strncmp(p_port_state_str,"No State Change (NOP)",12) )
+               return(0);
+       else if( !strncmp(p_port_state_str, "DOWN",4) )
+               return(1);
+       else if( !strncmp(p_port_state_str, "INIT", 4) )
+               return(2);
+       else if( !strncmp(p_port_state_str,"ARMED" , 5) )
+               return(3);
+       else if( !strncmp(p_port_state_str, "ACTIVE", 6) )
+               return(4);
+       else if( !strncmp(p_port_state_str, "ACTDEFER", 8) )
+               return(5);
+       return(6);
+}
+/*
+* PARAMETERS
+*      p_port_state_str
+*              [in] A string matching one returned by ib_get_port_state_str
+*
+* RETURN VALUES
+*      The appropriate code.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_port_info_t
+*********/
+
+/****d* IBA Base: Constants/Join States
+* NAME
+*      Join States
+*
+* DESCRIPTION
+*      Defines the join state flags for multicast group management.
+*
+* SOURCE
+*/
+#define IB_JOIN_STATE_FULL                     1
+#define IB_JOIN_STATE_NON                      2
+#define IB_JOIN_STATE_SEND_ONLY                4
+/**********/
+
+/****f* IBA Base: Types/ib_pkey_get_base
+* NAME
+*      ib_pkey_get_base
+*
+* DESCRIPTION
+*      Returns the base P_Key value with the membership bit stripped.
+*
+* SYNOPSIS
+*/
+AL_INLINE ib_net16_t     AL_API
+ib_pkey_get_base(
+       IN              const   ib_net16_t                                      pkey )
+{
+       return( (ib_net16_t)(pkey & IB_PKEY_BASE_MASK) );
+}
+/*
+* PARAMETERS
+*      pkey
+*              [in] P_Key value
+*
+* RETURN VALUE
+*      Returns the base P_Key value with the membership bit stripped.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* IBA Base: Types/ib_pkey_is_full_member
+* NAME
+*      ib_pkey_is_full_member
+*
+* DESCRIPTION
+*      Indicitates if the port is a full member of the parition.
+*
+* SYNOPSIS
+*/
+AL_INLINE boolean_t     AL_API
+ib_pkey_is_full_member(
+       IN              const   ib_net16_t                                      pkey )
+{
+       return( (pkey & IB_PKEY_TYPE_MASK) == IB_PKEY_TYPE_MASK );
+}
+/*
+* PARAMETERS
+*      pkey
+*              [in] P_Key value
+*
+* RETURN VALUE
+*      TRUE if the port is a full member of the partition.
+*      FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* ib_pkey_get_base, ib_net16_t
+*********/
+
+/****f* IBA Base: Types/ib_pkey_is_invalid
+* NAME
+*      ib_pkey_is_invalid
+*
+* DESCRIPTION
+*      Returns TRUE if the given P_Key is an invalid P_Key
+*  C10-116: the CI shall regard a P_Key as invalid if its low-order
+*           15 bits are all zero...
+*
+* SYNOPSIS
+*/
+OSM_INLINE boolean_t     AL_API
+ib_pkey_is_invalid(
+       IN              const   ib_net16_t                                      pkey )
+{
+  if (ib_pkey_get_base(pkey) == 0x0000)
+    return TRUE;
+
+  return FALSE;
+}
+/*
+* PARAMETERS
+*      pkey
+*              [in] P_Key value
+*
+* RETURN VALUE
+*      Returns the base P_Key value with the membership bit stripped.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****d* IBA Base: Types/ib_gid_t
+* NAME
+*      ib_gid_t
+*
+* DESCRIPTION
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef union _ib_gid
+{
+       uint8_t                                 raw[16];
+       struct _ib_gid_unicast
+       {
+               ib_gid_prefix_t         prefix;
+               ib_net64_t                      interface_id;
+
+       } PACK_SUFFIX unicast;
+
+       struct _ib_gid_multicast
+       {
+               uint8_t                         header[2];
+               uint8_t                         raw_group_id[14];
+
+       } PACK_SUFFIX multicast;
+
+}      PACK_SUFFIX ib_gid_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*      raw
+*              GID represented as an unformated byte array.
+*
+*      unicast
+*              Typical unicast representation with subnet prefix and
+*              port GUID.
+*
+*      multicast
+*              Representation for multicast use.
+*
+* SEE ALSO
+*********/
+
+AL_INLINE boolean_t     AL_API
+ib_gid_is_multicast(
+       IN              const   ib_gid_t*                                       p_gid )
+{
+       return( p_gid->raw[0] == 0xFF );
+}
+
+/****f* IBA Base: Types/ib_gid_set_default
+* NAME
+*      ib_gid_set_default
+*
+* DESCRIPTION
+*      Sets a GID to the default value.
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_gid_set_default(
+       IN                              ib_gid_t* const                         p_gid,
+       IN              const   ib_net64_t                                      interface_id )
+{
+       p_gid->unicast.prefix = IB_DEFAULT_SUBNET_PREFIX;
+       p_gid->unicast.interface_id = interface_id;
+}
+/*
+* PARAMETERS
+*      p_gid
+*              [in] Pointer to the GID object.
+*
+*      interface_id
+*              [in] Manufacturer assigned EUI64 value of a port.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_gid_t
+*********/
+/****f* IBA Base: Types/ib_gid_get_subnet_prefix
+* NAME
+*      ib_gid_get_subnet_prefix
+*
+* DESCRIPTION
+*      Gets the subnet prefix from a GID.
+*
+* SYNOPSIS
+*/
+AL_INLINE ib_net64_t     AL_API
+ib_gid_get_subnet_prefix(
+       IN              const   ib_gid_t* const                         p_gid )
+{
+       return( p_gid->unicast.prefix );
+}
+/*
+* PARAMETERS
+*      p_gid
+*              [in] Pointer to the GID object.
+*
+* RETURN VALUES
+*      64-bit subnet prefix value.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_gid_t
+*********/
+/****f* IBA Base: Types/ib_gid_is_link_local
+* NAME
+*      ib_gid_is_link_local
+*
+* DESCRIPTION
+*      Returns TRUE if the unicast GID scoping indicates link local,
+*      FALSE otherwise.
+*
+* SYNOPSIS
+*/
+AL_INLINE boolean_t     AL_API
+ib_gid_is_link_local(
+       IN              const   ib_gid_t* const                         p_gid )
+{
+       return( ib_gid_get_subnet_prefix( p_gid ) == IB_DEFAULT_SUBNET_PREFIX );
+}
+/*
+* PARAMETERS
+*      p_gid
+*              [in] Pointer to the GID object.
+*
+* RETURN VALUES
+*      Returns TRUE if the unicast GID scoping indicates link local,
+*      FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_gid_t
+*********/
+/****f* IBA Base: Types/ib_gid_is_site_local
+* NAME
+*      ib_gid_is_site_local
+*
+* DESCRIPTION
+*      Returns TRUE if the unicast GID scoping indicates site local,
+*      FALSE otherwise.
+*
+* SYNOPSIS
+*/
+AL_INLINE boolean_t     AL_API
+ib_gid_is_site_local(
+       IN              const   ib_gid_t* const                         p_gid )
+{
+       return( ( ib_gid_get_subnet_prefix( p_gid ) &
+               CL_HTON64( 0xFFFFFFFFFFFF0000ULL ) ) == CL_HTON64( 0xFEC0000000000000ULL ) );
+}
+/*
+* PARAMETERS
+*      p_gid
+*              [in] Pointer to the GID object.
+*
+* RETURN VALUES
+*      Returns TRUE if the unicast GID scoping indicates link local,
+*      FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_gid_t
+*********/
+/****f* IBA Base: Types/ib_gid_get_guid
+* NAME
+*      ib_gid_get_guid
+*
+* DESCRIPTION
+*      Gets the guid from a GID.
+*
+* SYNOPSIS
+*/
+AL_INLINE ib_net64_t     AL_API
+ib_gid_get_guid(
+       IN              const   ib_gid_t* const                         p_gid )
+{
+       return( p_gid->unicast.interface_id );
+}
+/*
+* PARAMETERS
+*      p_gid
+*              [in] Pointer to the GID object.
+*
+* RETURN VALUES
+*      64-bit GUID value.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_gid_t
+*********/
+
+/****s* IBA Base: Types/ib_path_rec_t
+* NAME
+*      ib_path_rec_t
+*
+* DESCRIPTION
+*      Path records encapsulate the properties of a given
+*      route between two end-points on a subnet.
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_path_rec
+{
+       uint8_t                                 resv0[8];
+       ib_gid_t                                dgid;
+       ib_gid_t                                sgid;
+       ib_net16_t                              dlid;
+       ib_net16_t                              slid;
+       ib_net32_t                              hop_flow_raw;
+       uint8_t                                 tclass;
+       uint8_t                                 num_path; 
+       ib_net16_t                              pkey;
+       ib_net16_t                              sl;
+       uint8_t                                 mtu;
+       uint8_t                                 rate;
+       uint8_t                                 pkt_life;
+       uint8_t                                 preference;
+       uint8_t                                 resv2[6];
+
+}      PACK_SUFFIX ib_path_rec_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*      resv0
+*              Reserved bytes.
+*
+*      dgid
+*              GID of destination port.
+*
+*      sgid
+*              GID of source port.
+*
+*      dlid
+*              LID of destination port.
+*
+*      slid
+*              LID of source port.
+*
+*      hop_flow_raw
+*              Global routing parameters: hop count, flow label and raw bit.
+*
+*      tclass
+*              Another global routing parameter.
+*
+*      num_path
+*     Reversible path - 1 bit to say if path is reversible.
+*              Num-Paths [6:0] In queries, maximum number of paths to return.
+*              In responses, undefined.
+*
+*      pkey
+*              Partition key (P_Key) to use on this path.
+*
+*      resv1
+*              Reserved byte.
+*
+*      sl
+*              Service level to use on this path.
+*
+*      mtu
+*              MTU and MTU selector fields to use on this path
+*
+*      rate
+*              Rate and rate selector fields to use on this path.
+*
+*      pkt_life
+*              Packet lifetime
+*
+*      preference
+*              Indicates the relative merit of this path versus other path
+*              records returned from the SA.  Lower numbers are better.
+*
+*      resv2
+*              Reserved bytes.
+* SEE ALSO
+*********/
+
+/* Path Record Component Masks */
+#define  IB_PR_COMPMASK_DGID              (CL_HTON64(((uint64_t)1)<<2))
+#define  IB_PR_COMPMASK_SGID              (CL_HTON64(((uint64_t)1)<<3))
+#define  IB_PR_COMPMASK_DLID              (CL_HTON64(((uint64_t)1)<<4))
+#define  IB_PR_COMPMASK_SLID              (CL_HTON64(((uint64_t)1)<<5))
+#define  IB_PR_COMPMASK_RAWTRAFFIC         (CL_HTON64(((uint64_t)1)<<6))
+#define  IB_PR_COMPMASK_RESV0             (CL_HTON64(((uint64_t)1)<<7))
+#define  IB_PR_COMPMASK_FLOWLABEL         (CL_HTON64(((uint64_t)1)<<8))
+#define  IB_PR_COMPMASK_HOPLIMIT          (CL_HTON64(((uint64_t)1)<<9))
+#define  IB_PR_COMPMASK_TCLASS            (CL_HTON64(((uint64_t)1)<<10))
+#define  IB_PR_COMPMASK_REVERSIBLE        (CL_HTON64(((uint64_t)1)<<11))
+#define  IB_PR_COMPMASK_NUMBPATH          (CL_HTON64(((uint64_t)1)<<12))
+#define  IB_PR_COMPMASK_PKEY              (CL_HTON64(((uint64_t)1)<<13))
+#define  IB_PR_COMPMASK_RESV1             (CL_HTON64(((uint64_t)1)<<14))
+#define  IB_PR_COMPMASK_SL                (CL_HTON64(((uint64_t)1)<<15))
+#define  IB_PR_COMPMASK_MTUSELEC          (CL_HTON64(((uint64_t)1)<<16))
+#define  IB_PR_COMPMASK_MTU               (CL_HTON64(((uint64_t)1)<<17))
+#define  IB_PR_COMPMASK_RATESELEC         (CL_HTON64(((uint64_t)1)<<18))
+#define  IB_PR_COMPMASK_RATE              (CL_HTON64(((uint64_t)1)<<19))
+#define  IB_PR_COMPMASK_PKTLIFETIMESELEC  (CL_HTON64(((uint64_t)1)<<20))
+#define  IB_PR_COMPMASK_PKTLIFETIME       (CL_HTON64(((uint64_t)1)<<21))
+
+/* Link Record Component Masks */
+#define IB_LR_COMPMASK_FROM_LID           (CL_HTON64(((uint64_t)1)<<0))
+#define IB_LR_COMPMASK_FROM_PORT          (CL_HTON64(((uint64_t)1)<<1))
+#define IB_LR_COMPMASK_TO_PORT            (CL_HTON64(((uint64_t)1)<<2))
+#define  IB_LR_COMPMASK_TO_LID            (CL_HTON64(((uint64_t)1)<<3))
+
+/* VL Arbitration Record MASKs */
+#define IB_VLA_COMPMASK_LID               (CL_HTON64(((uint64_t)1)<<0))
+#define IB_VLA_COMPMASK_OUT_PORT          (CL_HTON64(((uint64_t)1)<<1))
+#define IB_VLA_COMPMASK_BLOCK             (CL_HTON64(((uint64_t)1)<<2))
+/* SLtoVL Mapping Record Masks */
+#define IB_SLVL_COMPMASK_LID              (CL_HTON64(((uint64_t)1)<<0))
+#define IB_SLVL_COMPMASK_IN_PORT          (CL_HTON64(((uint64_t)1)<<1))
+#define IB_SLVL_COMPMASK_OUT_PORT         (CL_HTON64(((uint64_t)1)<<2))
+/* P_Key Table Record Masks */
+#define IB_PKEY_COMPMASK_LID              (CL_HTON64(((uint64_t)1)<<0))
+#define IB_PKEY_COMPMASK_BLOCK            (CL_HTON64(((uint64_t)1)<<1))
+#define IB_PKEY_COMPMASK_PORT             (CL_HTON64(((uint64_t)1)<<2))
+/* LFT Record MASKS */
+#define IB_LFTR_COMPMASK_LID              (CL_HTON64(((uint64_t)1)<<0))
+#define IB_LFTR_COMPMASK_BLOCK            (CL_HTON64(((uint64_t)1)<<1))
+/* ModeInfo Record MASKS */
+#define IB_NR_COMPMASK_LID                (CL_HTON64(((uint64_t)1)<<0))
+#define IB_NR_COMPMASK_RESERVED1          (CL_HTON64(((uint64_t)1)<<1))
+#define IB_NR_COMPMASK_BASEVERSION        (CL_HTON64(((uint64_t)1)<<2))
+#define IB_NR_COMPMASK_CLASSVERSION       (CL_HTON64(((uint64_t)1)<<3))
+#define  IB_NR_COMPMASK_NODETYPE          (CL_HTON64(((uint64_t)1)<<4))
+#define  IB_NR_COMPMASK_NUMPORTS          (CL_HTON64(((uint64_t)1)<<5))
+#define  IB_NR_COMPMASK_SYSIMAGEGUID      (CL_HTON64(((uint64_t)1)<<6))
+#define  IB_NR_COMPMASK_NODEGUID          (CL_HTON64(((uint64_t)1)<<7))
+#define  IB_NR_COMPMASK_PORTGUID          (CL_HTON64(((uint64_t)1)<<8))
+#define  IB_NR_COMPMASK_PARTCAP           (CL_HTON64(((uint64_t)1)<<9))
+#define  IB_NR_COMPMASK_DEVID             (CL_HTON64(((uint64_t)1)<<10))
+#define  IB_NR_COMPMASK_REV               (CL_HTON64(((uint64_t)1)<<11))
+#define  IB_NR_COMPMASK_PORTNUM           (CL_HTON64(((uint64_t)1)<<12))
+#define  IB_NR_COMPMASK_VENDID            (CL_HTON64(((uint64_t)1)<<13))
+#define  IB_NR_COMPMASK_NODEDESC          (CL_HTON64(((uint64_t)1)<<14))
+/* Service Record Component Mask Sec 15.2.5.14 Ver 1.1*/
+#define IB_SR_COMPMASK_SID                (CL_HTON64(((uint64_t)1)<<0))
+#define IB_SR_COMPMASK_SGID               (CL_HTON64(((uint64_t)1)<<1))
+#define IB_SR_COMPMASK_SPKEY              (CL_HTON64(((uint64_t)1)<<2))
+#define IB_SR_COMPMASK_RES1               (CL_HTON64(((uint64_t)1)<<3))
+#define IB_SR_COMPMASK_SLEASE             (CL_HTON64(((uint64_t)1)<<4))
+#define IB_SR_COMPMASK_SKEY               (CL_HTON64(((uint64_t)1)<<5))
+#define IB_SR_COMPMASK_SNAME              (CL_HTON64(((uint64_t)1)<<6))
+#define IB_SR_COMPMASK_SDATA8_0           (CL_HTON64(((uint64_t)1)<<7))
+#define IB_SR_COMPMASK_SDATA8_1           (CL_HTON64(((uint64_t)1)<<8))
+#define IB_SR_COMPMASK_SDATA8_2           (CL_HTON64(((uint64_t)1)<<9))
+#define IB_SR_COMPMASK_SDATA8_3           (CL_HTON64(((uint64_t)1)<<10))
+#define IB_SR_COMPMASK_SDATA8_4           (CL_HTON64(((uint64_t)1)<<11))
+#define IB_SR_COMPMASK_SDATA8_5           (CL_HTON64(((uint64_t)1)<<12))
+#define IB_SR_COMPMASK_SDATA8_6           (CL_HTON64(((uint64_t)1)<<13))
+#define IB_SR_COMPMASK_SDATA8_7           (CL_HTON64(((uint64_t)1)<<14))
+#define IB_SR_COMPMASK_SDATA8_8           (CL_HTON64(((uint64_t)1)<<15))
+#define IB_SR_COMPMASK_SDATA8_9           (CL_HTON64(((uint64_t)1)<<16))
+#define IB_SR_COMPMASK_SDATA8_10       (CL_HTON64(((uint64_t)1)<<17))
+#define IB_SR_COMPMASK_SDATA8_11       (CL_HTON64(((uint64_t)1)<<18))
+#define IB_SR_COMPMASK_SDATA8_12       (CL_HTON64(((uint64_t)1)<<19))
+#define IB_SR_COMPMASK_SDATA8_13       (CL_HTON64(((uint64_t)1)<<20))
+#define IB_SR_COMPMASK_SDATA8_14       (CL_HTON64(((uint64_t)1)<<21))
+#define IB_SR_COMPMASK_SDATA8_15       (CL_HTON64(((uint64_t)1)<<22))
+#define IB_SR_COMPMASK_SDATA16_0       (CL_HTON64(((uint64_t)1)<<23))
+#define IB_SR_COMPMASK_SDATA16_1       (CL_HTON64(((uint64_t)1)<<24))
+#define IB_SR_COMPMASK_SDATA16_2       (CL_HTON64(((uint64_t)1)<<25))
+#define IB_SR_COMPMASK_SDATA16_3       (CL_HTON64(((uint64_t)1)<<26))
+#define IB_SR_COMPMASK_SDATA16_4       (CL_HTON64(((uint64_t)1)<<27))
+#define IB_SR_COMPMASK_SDATA16_5       (CL_HTON64(((uint64_t)1)<<28))
+#define IB_SR_COMPMASK_SDATA16_6       (CL_HTON64(((uint64_t)1)<<29))
+#define IB_SR_COMPMASK_SDATA16_7       (CL_HTON64(((uint64_t)1)<<30))
+#define IB_SR_COMPMASK_SDATA32_0       (CL_HTON64(((uint64_t)1)<<31))
+#define IB_SR_COMPMASK_SDATA32_1       (CL_HTON64(((uint64_t)1)<<32))
+#define IB_SR_COMPMASK_SDATA32_2       (CL_HTON64(((uint64_t)1)<<33))
+#define IB_SR_COMPMASK_SDATA32_3       (CL_HTON64(((uint64_t)1)<<34))
+#define IB_SR_COMPMASK_SDATA64_0       (CL_HTON64(((uint64_t)1)<<35))
+#define IB_SR_COMPMASK_SDATA64_1       (CL_HTON64(((uint64_t)1)<<36))
+/* Port Info Record Component Masks */
+#define IB_PIR_COMPMASK_LID               (CL_HTON64(((uint64_t)1)<<0))
+#define IB_PIR_COMPMASK_PORTNUM           (CL_HTON64(((uint64_t)1)<<1))
+#define IB_PIR_COMPMASK_RESV1             (CL_HTON64(((uint64_t)1)<<2))
+#define IB_PIR_COMPMASK_MKEY              (CL_HTON64(((uint64_t)1)<<3))
+#define  IB_PIR_COMPMASK_GIDPRE           (CL_HTON64(((uint64_t)1)<<4))
+#define  IB_PIR_COMPMASK_BASELID          (CL_HTON64(((uint64_t)1)<<5))
+#define  IB_PIR_COMPMASK_SMLID            (CL_HTON64(((uint64_t)1)<<6))
+#define  IB_PIR_COMPMASK_CAPMASK          (CL_HTON64(((uint64_t)1)<<7))
+#define  IB_PIR_COMPMASK_DIAGCODE         (CL_HTON64(((uint64_t)1)<<8))
+#define  IB_PIR_COMPMASK_MKEYLEASEPRD     (CL_HTON64(((uint64_t)1)<<9))
+#define  IB_PIR_COMPMASK_LOCALPORTNUM     (CL_HTON64(((uint64_t)1)<<10))
+#define  IB_PIR_COMPMASK_LINKWIDTHENABLED (CL_HTON64(((uint64_t)1)<<11))
+#define  IB_PIR_COMPMASK_LNKWIDTHSUPPORT  (CL_HTON64(((uint64_t)1)<<12))
+#define  IB_PIR_COMPMASK_LNKWIDTHACTIVE   (CL_HTON64(((uint64_t)1)<<13))
+#define  IB_PIR_COMPMASK_LNKSPEEDSUPPORT  (CL_HTON64(((uint64_t)1)<<14))
+#define  IB_PIR_COMPMASK_PORTSTATE        (CL_HTON64(((uint64_t)1)<<15))
+#define  IB_PIR_COMPMASK_PORTPHYSTATE     (CL_HTON64(((uint64_t)1)<<16))
+#define  IB_PIR_COMPMASK_LINKDWNDFLTSTATE (CL_HTON64(((uint64_t)1)<<17))
+#define  IB_PIR_COMPMASK_MKEYPROTBITS     (CL_HTON64(((uint64_t)1)<<18))
+#define  IB_PIR_COMPMASK_RESV2            (CL_HTON64(((uint64_t)1)<<19))
+#define  IB_PIR_COMPMASK_LMC              (CL_HTON64(((uint64_t)1)<<20))
+#define  IB_PIR_COMPMASK_LINKSPEEDACTIVE  (CL_HTON64(((uint64_t)1)<<21))
+#define  IB_PIR_COMPMASK_LINKSPEEDENABLE  (CL_HTON64(((uint64_t)1)<<22))
+#define  IB_PIR_COMPMASK_NEIGHBORMTU      (CL_HTON64(((uint64_t)1)<<23))
+#define  IB_PIR_COMPMASK_MASTERSMSL       (CL_HTON64(((uint64_t)1)<<24))
+#define  IB_PIR_COMPMASK_VLCAP            (CL_HTON64(((uint64_t)1)<<25))
+#define  IB_PIR_COMPMASK_INITTYPE         (CL_HTON64(((uint64_t)1)<<26))
+#define  IB_PIR_COMPMASK_VLHIGHLIMIT      (CL_HTON64(((uint64_t)1)<<27))
+#define  IB_PIR_COMPMASK_VLARBHIGHCAP     (CL_HTON64(((uint64_t)1)<<28))
+#define  IB_PIR_COMPMASK_VLARBLOWCAP      (CL_HTON64(((uint64_t)1)<<29))
+#define  IB_PIR_COMPMASK_INITTYPEREPLY    (CL_HTON64(((uint64_t)1)<<30))
+#define  IB_PIR_COMPMASK_MTUCAP           (CL_HTON64(((uint64_t)1)<<31))
+#define  IB_PIR_COMPMASK_VLSTALLCNT       (CL_HTON64(((uint64_t)1)<<32))
+#define  IB_PIR_COMPMASK_HOQLIFE          (CL_HTON64(((uint64_t)1)<<33))
+#define  IB_PIR_COMPMASK_OPVLS            (CL_HTON64(((uint64_t)1)<<34))
+#define  IB_PIR_COMPMASK_PARENFIN         (CL_HTON64(((uint64_t)1)<<35))
+#define  IB_PIR_COMPMASK_PARENFOUT        (CL_HTON64(((uint64_t)1)<<36))
+#define  IB_PIR_COMPMASK_FILTERRAWIN      (CL_HTON64(((uint64_t)1)<<37))
+#define  IB_PIR_COMPMASK_FILTERRAWOUT     (CL_HTON64(((uint64_t)1)<<38))
+#define  IB_PIR_COMPMASK_MKEYVIO          (CL_HTON64(((uint64_t)1)<<39))
+#define  IB_PIR_COMPMASK_PKEYVIO          (CL_HTON64(((uint64_t)1)<<40))
+#define  IB_PIR_COMPMASK_QKEYVIO          (CL_HTON64(((uint64_t)1)<<41))
+#define  IB_PIR_COMPMASK_GUIDCAP          (CL_HTON64(((uint64_t)1)<<42))
+#define  IB_PIR_COMPMASK_RESV3            (CL_HTON64(((uint64_t)1)<<43))
+#define  IB_PIR_COMPMASK_SUBNTO           (CL_HTON64(((uint64_t)1)<<44))
+#define  IB_PIR_COMPMASK_RESV4            (CL_HTON64(((uint64_t)1)<<45))
+#define  IB_PIR_COMPMASK_RESPTIME         (CL_HTON64(((uint64_t)1)<<46))
+#define  IB_PIR_COMPMASK_LOCALPHYERR      (CL_HTON64(((uint64_t)1)<<47))
+#define  IB_PIR_COMPMASK_OVERRUNERR       (CL_HTON64(((uint64_t)1)<<48))
+/* Multicast Member Record Component Masks */
+#define IB_MCR_COMPMASK_GID         (CL_HTON64(((uint64_t)1)<<0))
+#define IB_MCR_COMPMASK_MGID        (CL_HTON64(((uint64_t)1)<<0))
+#define IB_MCR_COMPMASK_PORT_GID    (CL_HTON64(((uint64_t)1)<<1))
+#define IB_MCR_COMPMASK_QKEY        (CL_HTON64(((uint64_t)1)<<2))
+#define IB_MCR_COMPMASK_MLID        (CL_HTON64(((uint64_t)1)<<3))
+#define IB_MCR_COMPMASK_MTU_SEL     (CL_HTON64(((uint64_t)1)<<4))
+#define IB_MCR_COMPMASK_MTU         (CL_HTON64(((uint64_t)1)<<5))
+#define IB_MCR_COMPMASK_TCLASS      (CL_HTON64(((uint64_t)1)<<6))
+#define IB_MCR_COMPMASK_PKEY        (CL_HTON64(((uint64_t)1)<<7))
+#define IB_MCR_COMPMASK_RATE_SEL    (CL_HTON64(((uint64_t)1)<<8))
+#define IB_MCR_COMPMASK_RATE        (CL_HTON64(((uint64_t)1)<<9))
+#define IB_MCR_COMPMASK_LIFE_SEL    (CL_HTON64(((uint64_t)1)<<10))
+#define IB_MCR_COMPMASK_LIFE        (CL_HTON64(((uint64_t)1)<<11))
+#define IB_MCR_COMPMASK_SL          (CL_HTON64(((uint64_t)1)<<12))
+#define IB_MCR_COMPMASK_FLOW        (CL_HTON64(((uint64_t)1)<<13))
+#define IB_MCR_COMPMASK_HOP         (CL_HTON64(((uint64_t)1)<<14))
+#define IB_MCR_COMPMASK_SCOPE       (CL_HTON64(((uint64_t)1)<<15))
+#define IB_MCR_COMPMASK_JOIN_STATE  (CL_HTON64(((uint64_t)1)<<16))
+#define IB_MCR_COMPMASK_PROXY       (CL_HTON64(((uint64_t)1)<<17))
+
+/****f* IBA Base: Types/ib_path_rec_init_local
+* NAME
+*      ib_path_rec_init_local
+*
+* DESCRIPTION
+*      Initializes a subnet local path record.
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_path_rec_init_local(
+       IN                              ib_path_rec_t* const            p_rec,
+       IN                              ib_gid_t* const         p_dgid,
+       IN                              ib_gid_t* const         p_sgid,
+       IN                              ib_net16_t                      dlid,
+       IN                              ib_net16_t                      slid,
+       IN                              uint8_t                         num_path,
+       IN                              ib_net16_t                      pkey,
+       IN                              uint8_t                         sl,
+       IN                              uint8_t                         mtu_selector,
+       IN                              uint8_t                         mtu,
+       IN                              uint8_t                         rate_selector,
+       IN                              uint8_t                         rate,
+       IN                              uint8_t                         pkt_life_selector,
+       IN                              uint8_t                         pkt_life,
+       IN                              uint8_t                         preference )
+{
+       p_rec->dgid = *p_dgid;
+       p_rec->sgid = *p_sgid;
+       p_rec->dlid = dlid;
+       p_rec->slid = slid;
+       p_rec->num_path = num_path;
+       p_rec->pkey = pkey;
+       /* Lower 4 bits of path rec's SL are reserved. */
+       p_rec->sl = cl_ntoh16( sl );
+       p_rec->mtu = (uint8_t)((mtu & IB_PATH_REC_BASE_MASK) |
+                       (uint8_t)(mtu_selector << 6));
+       p_rec->rate = (uint8_t)((rate & IB_PATH_REC_BASE_MASK) |
+                       (uint8_t)(rate_selector << 6));
+       p_rec->pkt_life = (uint8_t)((pkt_life & IB_PATH_REC_BASE_MASK) |
+                       (uint8_t)(pkt_life_selector << 6));
+       p_rec->preference = preference;
+
+       /* Clear global routing fields for local path records */
+       p_rec->hop_flow_raw = 0;
+       p_rec->tclass = 0;
+
+       *((uint64_t*)p_rec->resv0) = 0;
+       *((uint32_t*)p_rec->resv2) = 0;
+       *((uint16_t*)p_rec->resv2 + 2) = 0;
+}
+/*
+* PARAMETERS
+*      p_rec
+*              [in] Pointer to the path record object.
+*
+*      dgid
+*              [in] GID of destination port.
+*
+*      sgid
+*              [in] GID of source port.
+*
+*      dlid
+*              [in] LID of destination port.
+*
+*      slid
+*              [in] LID of source port.
+*
+*      num_path
+*     [in] Reversible path - 1 bit to say if path is reversible.
+*              Num-Paths [6:0] In queries, maximum number of paths to return.
+*              In responses, undefined.
+*
+*      pkey
+*              [in] Partition key (P_Key) to use on this path.
+*
+*      sl
+*              [in] Service level to use on this path.  Lower 4-bits are valid.
+*
+*      mtu_selector
+*              [in] Encoded MTU selector value to use on this path
+*
+*      mtu
+*              [in] Encoded MTU to use on this path
+*
+*      rate_selector
+*              [in] Encoded rate selector value to use on this path.
+*
+*      rate
+*              [in] Encoded rate to use on this path.
+*
+*      pkt_life_selector
+*              [in] Encoded Packet selector value lifetime for this path.
+*
+*      pkt_life
+*              [in] Encoded Packet lifetime for this path.
+*
+*      preference
+*              [in] Indicates the relative merit of this path versus other path
+*              records returned from the SA.  Lower numbers are better.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_gid_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_num_path
+* NAME
+*      ib_path_rec_num_path
+*
+* DESCRIPTION
+*      Get max number of paths to return.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_path_rec_num_path(
+       IN              const   ib_path_rec_t* const            p_rec )
+{
+       return( p_rec->num_path &0x7F );
+}
+/*
+* PARAMETERS
+*      p_rec
+*              [in] Pointer to the path record object.
+*
+* RETURN VALUES
+*      Maximum number of paths toreturn for each unique SGID_DGID combination.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_sl
+* NAME
+*      ib_path_rec_sl
+*
+* DESCRIPTION
+*      Get path service level.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_path_rec_sl(
+       IN              const   ib_path_rec_t* const            p_rec )
+{
+       return( (uint8_t)((cl_ntoh16( p_rec->sl )) & 0xF) );
+}
+/*
+* PARAMETERS
+*      p_rec
+*              [in] Pointer to the path record object.
+*
+* RETURN VALUES
+*      Encoded path MTU.
+*              1: 256
+*              2: 512
+*              3: 1024
+*              4: 2048
+*              5: 4096
+*              others: reserved
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_mtu
+* NAME
+*      ib_path_rec_mtu
+*
+* DESCRIPTION
+*      Get encoded path MTU.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_path_rec_mtu(
+       IN              const   ib_path_rec_t* const            p_rec )
+{
+       return( (uint8_t)(p_rec->mtu & IB_PATH_REC_BASE_MASK) );
+}
+/*
+* PARAMETERS
+*      p_rec
+*              [in] Pointer to the path record object.
+*
+* RETURN VALUES
+*      Encoded path MTU.
+*              1: 256
+*              2: 512
+*              3: 1024
+*              4: 2048
+*              5: 4096
+*              others: reserved
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_mtu_sel
+* NAME
+*      ib_path_rec_mtu_sel
+*
+* DESCRIPTION
+*      Get encoded path MTU selector.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_path_rec_mtu_sel(
+       IN              const   ib_path_rec_t* const            p_rec )
+{
+       return( (uint8_t)((p_rec->mtu & IB_PATH_REC_SELECTOR_MASK) >> 6) );
+}
+/*
+* PARAMETERS
+*      p_rec
+*              [in] Pointer to the path record object.
+*
+* RETURN VALUES
+*      Encoded path MTU selector value (for queries).
+*              0: greater than MTU specified
+*              1: less than MTU specified
+*              2: exactly the MTU specified
+*              3: largest MTU available
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_rate
+* NAME
+*      ib_path_rec_rate
+*
+* DESCRIPTION
+*      Get encoded path rate.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_path_rec_rate(
+       IN              const   ib_path_rec_t* const            p_rec )
+{
+       return( (uint8_t)(p_rec->rate & IB_PATH_REC_BASE_MASK) );
+}
+/*
+* PARAMETERS
+*      p_rec
+*              [in] Pointer to the path record object.
+*
+* RETURN VALUES
+*      Encoded path rate.
+*              2: 2.5 Gb/sec.
+*              3: 10 Gb/sec.
+*              4: 30 Gb/sec.
+*              others: reserved
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_rate_sel
+* NAME
+*      ib_path_rec_rate_sel
+*
+* DESCRIPTION
+*      Get encoded path rate selector.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_path_rec_rate_sel(
+       IN              const   ib_path_rec_t* const            p_rec )
+{
+       return( (uint8_t)((p_rec->rate & IB_PATH_REC_SELECTOR_MASK) >> 6) );
+}
+/*
+* PARAMETERS
+*      p_rec
+*              [in] Pointer to the path record object.
+*
+* RETURN VALUES
+*      Encoded path rate selector value (for queries).
+*              0: greater than rate specified
+*              1: less than rate specified
+*              2: exactly the rate specified
+*              3: largest rate available
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_pkt_life
+* NAME
+*      ib_path_rec_pkt_life
+*
+* DESCRIPTION
+*      Get encoded path pkt_life.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_path_rec_pkt_life(
+       IN              const   ib_path_rec_t* const            p_rec )
+{
+       return( (uint8_t)(p_rec->pkt_life & IB_PATH_REC_BASE_MASK) );
+}
+/*
+* PARAMETERS
+*      p_rec
+*              [in] Pointer to the path record object.
+*
+* RETURN VALUES
+*      Encoded path pkt_life = 4.096 Âµsec * 2 PacketLifeTime.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_pkt_life_sel
+* NAME
+*      ib_path_rec_pkt_life_sel
+*
+* DESCRIPTION
+*      Get encoded path pkt_lifetime selector.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_path_rec_pkt_life_sel(
+       IN              const   ib_path_rec_t* const            p_rec )
+{
+       return( (uint8_t)((p_rec->pkt_life & IB_PATH_REC_SELECTOR_MASK) >> 6 ));
+}
+/*
+* PARAMETERS
+*      p_rec
+*              [in] Pointer to the path record object.
+*
+* RETURN VALUES
+*      Encoded path pkt_lifetime selector value (for queries).
+*              0: greater than rate specified
+*              1: less than rate specified
+*              2: exactly the rate specified
+*              3: smallest packet lifetime available
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_flow_lbl
+* NAME
+*      ib_path_rec_flow_lbl
+*
+* DESCRIPTION
+*      Get flow label.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint32_t     AL_API
+ib_path_rec_flow_lbl(
+       IN              const   ib_path_rec_t* const            p_rec )
+{
+       return( ((cl_ntoh32(p_rec->hop_flow_raw) >> 8) & 0x000FFFFF) );
+}
+/*
+* PARAMETERS
+*      p_rec
+*              [in] Pointer to the path record object.
+*
+* RETURN VALUES
+*      Flow label of the path record.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_path_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_path_rec_hop_limit
+* NAME
+*      ib_path_rec_hop_limit
+*
+* DESCRIPTION
+*      Get hop limit.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_path_rec_hop_limit(
+       IN              const   ib_path_rec_t* const            p_rec )
+{
+       return( (uint8_t)(p_rec->hop_flow_raw & 0x000000FF ) );
+}
+/*
+* PARAMETERS
+*      p_rec
+*              [in] Pointer to the path record object.
+*
+* RETURN VALUES
+*      Hop limit of the path record.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_path_rec_t
+*********/
+
+/****s* IBA Base: Constants/IB_CLASS_CAP_TRAP
+* NAME
+*      IB_CLASS_CAP_TRAP
+*
+* DESCRIPTION
+*      ClassPortInfo CapabilityMask bits.  This bit will be set
+*      if the class supports Trap() MADs (13.4.8.1).
+*
+* SEE ALSO
+*      ib_class_port_info_t, IB_CLASS_CAP_GETSET
+*
+* SOURCE
+*/
+#define IB_CLASS_CAP_TRAP                                      0x0001
+/*********/
+/****s* IBA Base: Constants/IB_CLASS_CAP_GETSET
+* NAME
+*      IB_CLASS_CAP_GETSET
+*
+* DESCRIPTION
+*      ClassPortInfo CapabilityMask bits.  This bit will be set
+*      if the class supports Get(Notice) and Set(Notice) MADs (13.4.8.1).
+*
+* SEE ALSO
+*      ib_class_port_info_t, IB_CLASS_CAP_TRAP
+*
+* SOURCE
+*/
+#define IB_CLASS_CAP_GETSET                                    0x0002
+/*********/
+/****s* IBA Base: Constants/IB_CLASS_CAP_GETSET
+* NAME
+*      IB_CLASS_CAP_GETSET
+*
+* DESCRIPTION
+*      Mask bits to extract the reponse time value from the
+*      resp_time_val field of ib_class_port_info_t.
+*
+* SEE ALSO
+*      ib_class_port_info_t
+*
+* SOURCE
+*/
+#define IB_CLASS_RESP_TIME_MASK                                0x1F
+/*********/
+/****s* IBA Base: Types/ib_class_port_info_t
+* NAME
+*      ib_class_port_info_t
+*
+* DESCRIPTION
+*      IBA defined ClassPortInfo attribute (13.4.8.1)
+*      route between two end-points on a subnet.
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_class_port_info
+{
+       uint8_t                                 base_ver;
+       uint8_t                                 class_ver;
+       ib_net16_t                              cap_mask;
+       ib_net32_t                              resp_time_val;
+       ib_gid_t                                redir_gid;
+       ib_net32_t                              redir_tc_sl_fl;
+       ib_net16_t                              redir_lid;
+       ib_net16_t                              redir_pkey;
+       ib_net32_t                              redir_qp;
+       ib_net32_t                              redir_qkey;
+       ib_gid_t                                trap_gid;
+       ib_net32_t                              trap_tc_sl_fl;
+       ib_net16_t                              trap_lid;
+       ib_net16_t                              trap_pkey;
+       ib_net32_t                              trap_hop_qp;
+       ib_net32_t                              trap_qkey;
+
+}      PACK_SUFFIX ib_class_port_info_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*      base_ver
+*              Maximum supported MAD Base Version.
+*
+*      class_ver
+*              Maximum supported management class version.
+*
+*      cap_mask
+*              Supported capabilities of this management class.
+*
+*      resp_time_value
+*              Maximum expected response time.
+*
+*      redr_gid
+*              GID to use for redirection, or zero
+*
+*      recdir_tc_sl_fl
+*              Traffic class, service level and flow label the requester
+*              should use if the service is redirected.
+*
+*      redir_lid
+*              LID used for redirection, or zero
+*
+*      redir_pkey
+*              P_Key used for redirection
+*
+*      redir_qp
+*              QP number used for redirection
+*
+*      redir_qkey
+*              Q_Key associated with the redirected QP.  This shall be the
+*              well known Q_Key value.
+*
+*      trap_gid
+*              GID value used for trap messages from this service.
+*
+*      trap_tc_sl_fl
+*              Traffic class, service level and flow label used for
+*              trap messages originated by this service.
+*
+*      trap_lid
+*              LID used for trap messages, or zero
+*
+*      trap_pkey
+*              P_Key used for trap messages
+*
+*      trap_hop_qp
+*              Hop limit (upper 8 bits) and QP number used for trap messages
+*
+*      trap_qkey
+*              Q_Key associated with the trap messages QP.
+*
+* SEE ALSO
+*      IB_CLASS_CAP_GETSET, IB_CLASS_CAP_TRAP
+*
+*********/
+/****s* IBA Base: Types/ib_sm_info_t
+* NAME
+*      ib_sm_info_t
+*
+* DESCRIPTION
+*      SMInfo structure (14.2.5.13).
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_sm_info
+{
+       ib_net64_t                      guid;
+       ib_net64_t                      sm_key;
+       ib_net32_t                      act_count;
+       uint8_t                         pri_state;
+
+}      PACK_SUFFIX ib_sm_info_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*      guid
+*              Port GUID for this SM.
+*
+*      sm_key
+*              SM_Key of this SM.
+*
+*      act_count
+*              Activity counter used as a heartbeat.
+*
+*      pri_state
+*              Priority and State information
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_sminfo_get_priority
+* NAME
+*      ib_sminfo_get_priority
+*
+* DESCRIPTION
+*      Returns the priority value.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_sminfo_get_priority(
+       IN              const   ib_sm_info_t* const                     p_smi )
+{
+       return( (uint8_t)((p_smi->pri_state & 0xF0)>>4) );
+}
+/*
+* PARAMETERS
+*      p_smi
+*              [in] Pointer to the SMInfo Attribute.
+*
+* RETURN VALUES
+*      Returns the priority value.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_sminfo_get_state
+* NAME
+*      ib_sminfo_get_state
+*
+* DESCRIPTION
+*      Returns the state value.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_sminfo_get_state(
+       IN              const   ib_sm_info_t* const                     p_smi )
+{
+       return( (uint8_t)(p_smi->pri_state & 0x0F) );
+}
+/*
+* PARAMETERS
+*      p_smi
+*              [in] Pointer to the SMInfo Attribute.
+*
+* RETURN VALUES
+*      Returns the state value.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****s* IBA Base: Types/ib_mad_t
+* NAME
+*      ib_mad_t
+*
+* DESCRIPTION
+*      IBA defined MAD header (13.4.3)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_mad
+{
+       uint8_t                                 base_ver;
+       uint8_t                                 mgmt_class;
+       uint8_t                                 class_ver;
+       uint8_t                                 method;
+       ib_net16_t                              status;
+       ib_net16_t                              class_spec;
+       ib_net64_t                              trans_id;
+       ib_net16_t                              attr_id;
+       ib_net16_t                              resv;
+       ib_net32_t                              attr_mod;
+}      PACK_SUFFIX ib_mad_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*      base_ver
+*              MAD base format.
+*
+*      mgmt_class
+*              Class of operation.
+*
+*      class_ver
+*              Version of MAD class-specific format.
+*
+*      method
+*              Method to perform, including 'R' bit.
+*
+*      status
+*              Status of operation.
+*
+*      class_spec
+*              Reserved for subnet management.
+*
+*      trans_id
+*              Transaction ID.
+*
+*      attr_id
+*              Attribute ID.
+*
+*      resv
+*              Reserved field.
+*
+*      attr_mod
+*              Attribute modifier.
+*
+* SEE ALSO
+*********/
+
+
+/****s* IBA Base: Types/ib_rmpp_mad_t
+* NAME
+*      ib_rmpp_mad_t
+*
+* DESCRIPTION
+*      IBA defined MAD RMPP header (13.6.2.1)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_rmpp_mad
+{
+       ib_mad_t                                common_hdr;
+
+       uint8_t                                 rmpp_version;
+       uint8_t                                 rmpp_type;
+       uint8_t                                 rmpp_flags;
+       uint8_t                                 rmpp_status;
+
+       ib_net32_t                              seg_num;
+       ib_net32_t                              paylen_newwin;
+
+}      PACK_SUFFIX ib_rmpp_mad_t;
+#include <complib/cl_packoff.h>
+/*
+* SEE ALSO
+*      ib_mad_t
+*********/
+
+
+/****f* IBA Base: Types/ib_mad_init_new
+* NAME
+*      ib_mad_init_new
+*
+* DESCRIPTION
+*      Initializes a MAD common header.
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_mad_init_new(
+       IN                              ib_mad_t* const                         p_mad,
+       IN              const   uint8_t                                         mgmt_class,
+       IN              const   uint8_t                                         class_ver,
+       IN              const   uint8_t                                         method,
+       IN              const   ib_net64_t                                      trans_id,
+       IN              const   ib_net16_t                                      attr_id,
+       IN              const   ib_net32_t                                      attr_mod )
+{
+       CL_ASSERT( p_mad );
+       p_mad->base_ver = 1;
+       p_mad->mgmt_class = mgmt_class;
+       p_mad->class_ver = class_ver;
+       p_mad->method = method;
+       p_mad->status = 0;
+       p_mad->class_spec = 0;
+       p_mad->trans_id = trans_id;
+       p_mad->attr_id = attr_id;
+       p_mad->resv = 0;
+       p_mad->attr_mod = attr_mod;
+}
+/*
+* PARAMETERS
+*      p_mad
+*              [in] Pointer to the MAD common header.
+*
+*      mgmt_class
+*              [in] Class of operation.
+*
+*      class_ver
+*              [in] Version of MAD class-specific format.
+*
+*      method
+*              [in] Method to perform, including 'R' bit.
+*
+*      trans_Id
+*              [in] Transaction ID.
+*
+*      attr_id
+*              [in] Attribute ID.
+*
+*      attr_mod
+*              [in] Attribute modifier.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_mad_t
+*********/
+
+/****f* IBA Base: Types/ib_mad_init_response
+* NAME
+*      ib_mad_init_response
+*
+* DESCRIPTION
+*      Initializes a MAD common header as a response.
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_mad_init_response(
+       IN              const   ib_mad_t* const                         p_req_mad,
+       IN                              ib_mad_t* const                         p_mad,
+       IN              const   ib_net16_t                                      status )
+{
+       CL_ASSERT( p_req_mad );
+       CL_ASSERT( p_mad );
+       *p_mad = *p_req_mad;
+       p_mad->status = status;
+       if( p_mad->method == IB_MAD_METHOD_SET )
+               p_mad->method = IB_MAD_METHOD_GET;
+       p_mad->method |= IB_MAD_METHOD_RESP_MASK;
+}
+/*
+* PARAMETERS
+*      p_req_mad
+*              [in] Pointer to the MAD common header in the original request MAD.
+*
+*      p_mad
+*              [in] Pointer to the MAD common header to initialize.
+*
+*      status
+*              [in] MAD Status value to return;
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*      p_req_mad and p_mad may point to the same MAD.
+*
+* SEE ALSO
+*      ib_mad_t
+*********/
+
+/****f* IBA Base: Types/ib_mad_is_response
+* NAME
+*      ib_mad_is_response
+*
+* DESCRIPTION
+*      Returns TRUE if the MAD is a response ('R' bit set),
+*      FALSE otherwise.
+*
+* SYNOPSIS
+*/
+AL_INLINE boolean_t     AL_API
+ib_mad_is_response(
+       IN              const   ib_mad_t* const                         p_mad )
+{
+       CL_ASSERT( p_mad );
+       return( (p_mad->method & IB_MAD_METHOD_RESP_MASK) ==
+                       IB_MAD_METHOD_RESP_MASK );
+}
+/*
+* PARAMETERS
+*      p_mad
+*              [in] Pointer to the MAD.
+*
+* RETURN VALUES
+*      Returns TRUE if the MAD is a response ('R' bit set),
+*      FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_mad_t
+*********/
+
+
+#define IB_RMPP_TYPE_DATA                      1
+#define IB_RMPP_TYPE_ACK                       2
+#define IB_RMPP_TYPE_STOP                      3
+#define IB_RMPP_TYPE_ABORT                     4
+
+#define IB_RMPP_NO_RESP_TIME           0x1F
+#define IB_RMPP_FLAG_ACTIVE                    0x01
+#define IB_RMPP_FLAG_FIRST                     0x02
+#define IB_RMPP_FLAG_LAST                      0x04
+
+#define IB_RMPP_STATUS_SUCCESS         0
+#define IB_RMPP_STATUS_RESX                    1               /* resources exhausted */
+#define IB_RMPP_STATUS_T2L                     118             /* time too long */
+#define IB_RMPP_STATUS_BAD_LEN         119             /* incon. last and payload len */
+#define IB_RMPP_STATUS_BAD_SEG         120             /* incon. first and segment no */
+#define IB_RMPP_STATUS_BADT                    121             /* bad rmpp type */
+#define IB_RMPP_STATUS_W2S                     122             /* newwindowlast too small */
+#define IB_RMPP_STATUS_S2B                     123             /* segment no too big */
+#define IB_RMPP_STATUS_BAD_STATUS      124             /* illegal status */
+#define IB_RMPP_STATUS_UNV                     125             /* unsupported version */
+#define IB_RMPP_STATUS_TMR                     126             /* too many retries */
+#define IB_RMPP_STATUS_UNSPEC          127             /* unspecified */
+
+
+/****f* IBA Base: Types/ib_rmpp_is_flag_set
+* NAME
+*      ib_rmpp_is_flag_set
+*
+* DESCRIPTION
+*      Returns TRUE if the MAD has the given RMPP flag set.
+*
+* SYNOPSIS
+*/
+AL_INLINE boolean_t     AL_API
+ib_rmpp_is_flag_set(
+       IN              const   ib_rmpp_mad_t* const            p_rmpp_mad,
+       IN              const   uint8_t                                         flag )
+{
+       CL_ASSERT( p_rmpp_mad );
+       return( (p_rmpp_mad->rmpp_flags & flag) == flag );
+}
+/*
+* PARAMETERS
+*      ib_rmpp_mad_t
+*              [in] Pointer to a MAD with an RMPP header.
+*
+*      flag
+*              [in] The RMPP flag being examined.
+*
+* RETURN VALUES
+*      Returns TRUE if the MAD has the given RMPP flag set.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_mad_t, ib_rmpp_mad_t
+*********/
+
+AL_INLINE void     AL_API
+ib_rmpp_set_resp_time(
+       IN                              ib_rmpp_mad_t* const            p_rmpp_mad,
+       IN              const   uint8_t                                         resp_time )
+{
+       CL_ASSERT( p_rmpp_mad );
+       p_rmpp_mad->rmpp_flags |= (resp_time << 3);
+}
+
+
+AL_INLINE uint8_t     AL_API
+ib_rmpp_get_resp_time(
+       IN              const   ib_rmpp_mad_t* const            p_rmpp_mad )
+{
+       CL_ASSERT( p_rmpp_mad );
+       return( (uint8_t)(p_rmpp_mad->rmpp_flags >> 3) );
+}
+
+
+/****d* IBA Base: Constants/IB_SMP_DIRECTION
+* NAME
+*      IB_SMP_DIRECTION
+*
+* DESCRIPTION
+*      The Direction bit for directed route SMPs.
+*
+* SOURCE
+*/
+#define IB_SMP_DIRECTION_HO                    0x8000
+#define IB_SMP_DIRECTION                       (CL_HTON16(IB_SMP_DIRECTION_HO))
+/**********/
+
+/****d* IBA Base: Constants/IB_SMP_STATUS_MASK
+* NAME
+*      IB_SMP_STATUS_MASK
+*
+* DESCRIPTION
+*      Mask value for extracting status from a directed route SMP.
+*
+* SOURCE
+*/
+#define IB_SMP_STATUS_MASK_HO          0x7FFF
+#define IB_SMP_STATUS_MASK                     (CL_HTON16(IB_SMP_STATUS_MASK_HO))
+/**********/
+
+/****s* IBA Base: Types/ib_smp_t
+* NAME
+*      ib_smp_t
+*
+* DESCRIPTION
+*      IBA defined SMP. (14.2.1.2)
+*
+* SYNOPSIS
+*/
+#define IB_SMP_DATA_SIZE 64
+#include <complib/cl_packon.h>
+typedef struct _ib_smp
+{
+       uint8_t                                 base_ver;
+       uint8_t                                 mgmt_class;
+       uint8_t                                 class_ver;
+       uint8_t                                 method;
+       ib_net16_t                              status;
+       uint8_t                                 hop_ptr;
+       uint8_t                                 hop_count;
+       ib_net64_t                              trans_id;
+       ib_net16_t                              attr_id;
+       ib_net16_t                              resv;
+       ib_net32_t                              attr_mod;
+       ib_net64_t                              m_key;
+       ib_net16_t                              dr_slid;
+       ib_net16_t                              dr_dlid;
+       uint32_t                                resv1[7];
+       uint8_t                                 data[IB_SMP_DATA_SIZE];
+       uint8_t                                 initial_path[IB_SUBNET_PATH_HOPS_MAX];
+       uint8_t                                 return_path[IB_SUBNET_PATH_HOPS_MAX];
+
+}      PACK_SUFFIX ib_smp_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*      base_ver
+*              MAD base format.
+*
+*      mgmt_class
+*              Class of operation.
+*
+*      class_ver
+*              Version of MAD class-specific format.
+*
+*      method
+*              Method to perform, including 'R' bit.
+*
+*      status
+*              Status of operation.
+*
+*      hop_ptr
+*              Hop pointer for directed route MADs.
+*
+*      hop_count
+*              Hop count for directed route MADs.
+*
+*      trans_Id
+*              Transaction ID.
+*
+*      attr_id
+*              Attribute ID.
+*
+*      resv
+*              Reserved field.
+*
+*      attr_mod
+*              Attribute modifier.
+*
+*      m_key
+*              Management key value.
+*
+*      dr_slid
+*              Directed route source LID.
+*
+*      dr_dlid
+*              Directed route destination LID.
+*
+*      resv0
+*              Reserved for 64 byte alignment.
+*
+*      data
+*              MAD data payload.
+*
+*      initial_path
+*              Outbound port list.
+*
+*      return_path
+*              Inbound port list.
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_smp_get_status
+* NAME
+*      ib_smp_get_status
+*
+* DESCRIPTION
+*      Returns the SMP status value in network order.
+*
+* SYNOPSIS
+*/
+AL_INLINE ib_net16_t     AL_API
+ib_smp_get_status(
+       IN              const   ib_smp_t* const                         p_smp )
+{
+       return( (ib_net16_t)(p_smp->status & IB_SMP_STATUS_MASK) );
+}
+/*
+* PARAMETERS
+*      p_smp
+*              [in] Pointer to the SMP packet.
+*
+* RETURN VALUES
+*      Returns the SMP status value in network order.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_smp_t
+*********/
+
+/****f* IBA Base: Types/ib_smp_is_response
+* NAME
+*      ib_smp_is_response
+*
+* DESCRIPTION
+*      Returns TRUE if the SMP is a response MAD, FALSE otherwise.
+*
+* SYNOPSIS
+*/
+AL_INLINE boolean_t     AL_API
+ib_smp_is_response(
+       IN              const   ib_smp_t* const                         p_smp )
+{
+       return( ib_mad_is_response( (const ib_mad_t*)p_smp ) );
+}
+/*
+* PARAMETERS
+*      p_smp
+*              [in] Pointer to the SMP packet.
+*
+* RETURN VALUES
+*      Returns TRUE if the SMP is a response MAD, FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_smp_t
+*********/
+/****f* IBA Base: Types/ib_smp_is_d
+* NAME
+*      ib_smp_is_d
+*
+* DESCRIPTION
+*      Returns TRUE if the SMP 'D' (direction) bit is set.
+*
+* SYNOPSIS
+*/
+AL_INLINE boolean_t     AL_API
+ib_smp_is_d(
+       IN              const   ib_smp_t* const                         p_smp )
+{
+       return( (p_smp->status & IB_SMP_DIRECTION) == IB_SMP_DIRECTION );
+}
+/*
+* PARAMETERS
+*      p_smp
+*              [in] Pointer to the SMP packet.
+*
+* RETURN VALUES
+*      Returns TRUE if the SMP 'D' (direction) bit is set.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_smp_t
+*********/
+
+/****f* IBA Base: Types/ib_smp_init_new
+* NAME
+*      ib_smp_init_new
+*
+* DESCRIPTION
+*      Initializes a MAD common header.
+*
+* TODO
+*      This is too big for inlining, but leave it here for now
+*      since there is not yet another convient spot.
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_smp_init_new(
+       IN                              ib_smp_t* const                         p_smp,
+       IN              const   uint8_t                                         method,
+       IN              const   ib_net64_t                                      trans_id,
+       IN              const   ib_net16_t                                      attr_id,
+       IN              const   ib_net32_t                                      attr_mod,
+       IN              const   uint8_t                                         hop_count,
+       IN              const   ib_net64_t                                      m_key,
+       IN              const   uint8_t*                                        path_out,
+       IN              const   ib_net16_t                                      dr_slid,
+       IN              const   ib_net16_t                                      dr_dlid )
+{
+       CL_ASSERT( p_smp );
+       CL_ASSERT( hop_count < IB_SUBNET_PATH_HOPS_MAX );
+       p_smp->base_ver = 1;
+       p_smp->mgmt_class = IB_MCLASS_SUBN_DIR;
+       p_smp->class_ver = 1;
+       p_smp->method = method;
+       p_smp->status = 0;
+       p_smp->hop_ptr = 0;
+       p_smp->hop_count = hop_count;
+       p_smp->trans_id = trans_id;
+       p_smp->attr_id = attr_id;
+       p_smp->resv = 0;
+       p_smp->attr_mod = attr_mod;
+       p_smp->m_key = m_key;
+       p_smp->dr_slid = dr_slid;
+       p_smp->dr_dlid = dr_dlid;
+
+       cl_memclr( p_smp->resv1,
+                       sizeof(p_smp->resv1) +
+                       sizeof(p_smp->data) +
+                       sizeof(p_smp->initial_path) +
+                       sizeof(p_smp->return_path) );
+
+       /* copy the path */
+       cl_memcpy( &p_smp->initial_path, path_out,
+                       sizeof( p_smp->initial_path ) );
+}
+/*
+* PARAMETERS
+*      p_smp
+*              [in] Pointer to the SMP packet.
+*
+*      method
+*              [in] Method to perform, including 'R' bit.
+*
+*      trans_Id
+*              [in] Transaction ID.
+*
+*      attr_id
+*              [in] Attribute ID.
+*
+*      attr_mod
+*              [in] Attribute modifier.
+*
+*      hop_count
+*              [in] Number of hops in the path.
+*
+*      m_key
+*              [in] Management key for this SMP.
+*
+*      path_out
+*              [in] Port array for outbound path.
+*
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*      Payload area is initialized to zero.
+*
+*
+* SEE ALSO
+*      ib_mad_t
+*********/
+/****f* IBA Base: Types/ib_smp_get_payload_ptr
+* NAME
+*      ib_smp_get_payload_ptr
+*
+* DESCRIPTION
+*      Gets a pointer to the SMP payload area.
+*
+* SYNOPSIS
+*/
+AL_INLINE void*     AL_API
+ib_smp_get_payload_ptr(
+       IN              const   ib_smp_t* const                         p_smp )
+{
+       return( (void*)p_smp->data );
+}
+/*
+* PARAMETERS
+*      p_smp
+*              [in] Pointer to the SMP packet.
+*
+* RETURN VALUES
+*      Pointer to SMP payload area.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_mad_t
+*********/
+
+/****s* IBA Base: Types/ib_node_info_t
+* NAME
+*      ib_node_info_t
+*
+* DESCRIPTION
+*      IBA defined NodeInfo. (14.2.5.3)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_node_info
+{
+       uint8_t                         base_version;
+       uint8_t                         class_version;
+       uint8_t                         node_type;
+       uint8_t                         num_ports;
+       ib_net64_t                      sys_guid;
+       ib_net64_t                      node_guid;
+       ib_net64_t                      port_guid;
+       ib_net16_t                      partition_cap;
+       ib_net16_t                      device_id;
+       ib_net32_t                      revision;
+       ib_net32_t                      port_num_vendor_id;
+
+}      PACK_SUFFIX ib_node_info_t;
+#include <complib/cl_packoff.h>
+/************/
+/****s* IBA Base: Types/ib_sa_mad_t
+* NAME
+*      ib_sa_mad_t
+*
+* DESCRIPTION
+*      IBA defined SA MAD format. (15.2.1)
+*
+* SYNOPSIS
+*/
+#define IB_SA_DATA_SIZE 200
+
+#include <complib/cl_packon.h>
+typedef struct _ib_sa_mad
+{
+       uint8_t                                 base_ver;
+       uint8_t                                 mgmt_class;
+       uint8_t                                 class_ver;
+       uint8_t                                 method;
+       ib_net16_t                              status;
+       ib_net16_t                              resv;
+       ib_net64_t                              trans_id;
+       ib_net16_t                              attr_id;
+       ib_net16_t                              resv1;
+       ib_net32_t                              attr_mod;
+
+       uint8_t                                 rmpp_version;
+       uint8_t                                 rmpp_type;
+       uint8_t                                 rmpp_flags;
+       uint8_t                                 rmpp_status;
+
+       ib_net32_t                              seg_num;
+       ib_net32_t                              paylen_newwin;
+
+       ib_net64_t                              sm_key;
+
+       ib_net16_t                              attr_offset;
+       ib_net16_t                              resv3;
+
+       ib_net64_t                              comp_mask;
+
+       uint8_t                                 data[IB_SA_DATA_SIZE];
+}      PACK_SUFFIX ib_sa_mad_t;
+#include <complib/cl_packoff.h>
+/**********/
+#define IB_SA_MAD_HDR_SIZE (sizeof(ib_sa_mad_t) - IB_SA_DATA_SIZE)
+
+
+
+AL_INLINE uint32_t     AL_API
+ib_get_attr_size(
+       IN              const   ib_net16_t                                      attr_offset )
+{
+       return( ((uint32_t)cl_ntoh16( attr_offset )) << 3 );
+}
+
+AL_INLINE ib_net16_t     AL_API
+ib_get_attr_offset(
+       IN              const   uint32_t                                        attr_size )
+{
+       return( cl_hton16( (uint16_t)(attr_size >> 3) ) );
+}
+
+
+/****f* IBA Base: Types/ib_sa_mad_get_payload_ptr
+* NAME
+*      ib_sa_mad_get_payload_ptr
+*
+* DESCRIPTION
+*      Gets a pointer to the SA MAD's payload area.
+*
+* SYNOPSIS
+*/
+AL_INLINE void*     AL_API
+ib_sa_mad_get_payload_ptr(
+       IN              const   ib_sa_mad_t* const                      p_sa_mad )
+{
+       return( (void*)p_sa_mad->data );
+}
+/*
+* PARAMETERS
+*      p_smp
+*              [in] Pointer to the SA MAD packet.
+*
+* RETURN VALUES
+*      Pointer to SA MAD payload area.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_mad_t
+*********/
+
+#define IB_NODE_INFO_PORT_NUM_MASK             (CL_NTOH32(0xFF000000))
+#define IB_NODE_INFO_VEND_ID_MASK              (CL_NTOH32(0x00FFFFFF))
+#if CPU_LE
+       #define IB_NODE_INFO_PORT_NUM_SHIFT 0
+#else
+       #define IB_NODE_INFO_PORT_NUM_SHIFT 24
+#endif
+
+/****f* IBA Base: Types/ib_node_info_get_local_port_num
+* NAME
+*      ib_node_info_get_local_port_num
+*
+* DESCRIPTION
+*      Gets a the local port number from the NodeInfo attribute.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_node_info_get_local_port_num(
+       IN              const   ib_node_info_t* const           p_ni )
+{
+       return( (uint8_t)(( p_ni->port_num_vendor_id &
+                       IB_NODE_INFO_PORT_NUM_MASK )
+                       >> IB_NODE_INFO_PORT_NUM_SHIFT ));
+}
+/*
+* PARAMETERS
+*      p_ni
+*              [in] Pointer to a NodeInfo attribute.
+*
+* RETURN VALUES
+*      Local port number that returned the attribute.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_node_info_t
+*********/
+/****f* IBA Base: Types/ib_node_info_get_vendor_id
+* NAME
+*      ib_node_info_get_vendor_id
+*
+* DESCRIPTION
+*      Gets the VendorID from the NodeInfo attribute.
+*
+* SYNOPSIS
+*/
+AL_INLINE ib_net32_t     AL_API
+ib_node_info_get_vendor_id(
+       IN              const   ib_node_info_t* const           p_ni )
+{
+       return( (ib_net32_t)( p_ni->port_num_vendor_id &
+                       IB_NODE_INFO_VEND_ID_MASK ) );
+}
+/*
+* PARAMETERS
+*      p_ni
+*              [in] Pointer to a NodeInfo attribute.
+*
+* RETURN VALUES
+*      VendorID that returned the attribute.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_node_info_t
+*********/
+
+#define IB_NODE_DESCRIPTION_SIZE 64
+
+#include <complib/cl_packon.h>
+typedef struct _ib_node_desc
+{
+       // Node String is an array of UTF-8 character that
+       // describes the node in text format
+       // Note that this string is NOT NULL TERMINATED!
+       uint8_t         description[IB_NODE_DESCRIPTION_SIZE];
+
+}      PACK_SUFFIX ib_node_desc_t;
+#include <complib/cl_packoff.h>
+
+#include <complib/cl_packon.h>
+typedef struct _ib_node_record_t
+{
+       ib_net16_t              lid;
+       ib_net16_t              resv;
+       ib_node_info_t  node_info;
+       ib_node_desc_t  node_desc;
+       uint8_t                 pad[4];
+
+}      PACK_SUFFIX ib_node_record_t;
+#include <complib/cl_packoff.h>
+
+/****s* IBA Base: Types/ib_port_info_t
+* NAME
+*      ib_port_info_t
+*
+* DESCRIPTION
+*      IBA defined PortInfo. (14.2.5.6)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_port_info
+{
+       ib_net64_t                      m_key;
+       ib_net64_t                      subnet_prefix;
+       ib_net16_t                      base_lid;
+       ib_net16_t                      master_sm_base_lid;
+       ib_net32_t                      capability_mask;
+       ib_net16_t                      diag_code;
+       ib_net16_t                      m_key_lease_period;
+       uint8_t                         local_port_num;
+       uint8_t                         link_width_enabled;
+       uint8_t                         link_width_supported;
+       uint8_t                         link_width_active;
+  uint8_t                              state_info1; /* LinkSpeedSupported and PortState */
+  uint8_t                              state_info2; /* PortPhysState and LinkDownDefaultState */
+       uint8_t                         mkey_lmc;
+  uint8_t                              link_speed;      /* LinkSpeedEnabled and LinkSpeedActive */
+       uint8_t                         mtu_smsl;
+       uint8_t                         vl_cap;          /* VLCap and InitType */
+       uint8_t                         vl_high_limit;
+       uint8_t                         vl_arb_high_cap;
+       uint8_t                         vl_arb_low_cap;
+       uint8_t                         mtu_cap;
+       uint8_t                         vl_stall_life;
+       uint8_t                         vl_enforce;
+       ib_net16_t                      m_key_violations;
+       ib_net16_t                      p_key_violations;
+       ib_net16_t                      q_key_violations;
+       uint8_t                         guid_cap;
+       uint8_t                         subnet_timeout; /* cli_rereg(1b), resrv(
+2b), timeout(5b) */
+       uint8_t                         resp_time_value;
+       uint8_t                         error_threshold;
+
+}      PACK_SUFFIX ib_port_info_t;
+#include <complib/cl_packoff.h>
+/************/
+
+#define IB_PORT_STATE_MASK                                                     0x0F
+#define IB_PORT_LMC_MASK                                                       0x07
+#define IB_PORT_MPB_MASK                                                       0xC0
+#define IB_PORT_MPB_SHIFT                                                      6
+#define IB_PORT_LINK_SPEED_SHIFT                                       4
+#define IB_PORT_LINK_SPEED_SUPPORTED_MASK                      0xF0
+#define IB_PORT_LINK_SPEED_ACTIVE_MASK       0xF0
+#define IB_PORT_LINK_SPEED_ENABLED_MASK      0x0F
+#define IB_PORT_PHYS_STATE_MASK              0xF0
+#define IB_PORT_PHYS_STATE_SHIFT                                       4
+#define IB_PORT_LNKDWNDFTSTATE_MASK          0x0F
+
+#define IB_PORT_CAP_RESV0         (CL_NTOH32(0x00000001))
+#define IB_PORT_CAP_IS_SM         (CL_NTOH32(0x00000002))
+#define IB_PORT_CAP_HAS_NOTICE    (CL_NTOH32(0x00000004))
+#define IB_PORT_CAP_HAS_TRAP      (CL_NTOH32(0x00000008))
+#define IB_PORT_CAP_HAS_IPD       (CL_NTOH32(0x00000010))
+#define IB_PORT_CAP_HAS_AUTO_MIG  (CL_NTOH32(0x00000020))
+#define IB_PORT_CAP_HAS_SL_MAP    (CL_NTOH32(0x00000040))
+#define IB_PORT_CAP_HAS_NV_MKEY   (CL_NTOH32(0x00000080))
+#define IB_PORT_CAP_HAS_NV_PKEY   (CL_NTOH32(0x00000100))
+#define IB_PORT_CAP_HAS_LED_INFO  (CL_NTOH32(0x00000200))
+#define IB_PORT_CAP_SM_DISAB      (CL_NTOH32(0x00000400))
+#define IB_PORT_CAP_HAS_SYS_IMG_GUID  (CL_NTOH32(0x00000800))
+#define IB_PORT_CAP_HAS_PKEY_SW_EXT_PORT_TRAP (CL_NTOH32(0x00001000))
+#define IB_PORT_CAP_RESV13        (CL_NTOH32(0x00002000))
+#define IB_PORT_CAP_RESV14        (CL_NTOH32(0x00004000))
+#define IB_PORT_CAP_RESV15        (CL_NTOH32(0x00008000))
+#define IB_PORT_CAP_HAS_COM_MGT   (CL_NTOH32(0x00010000))
+#define IB_PORT_CAP_HAS_SNMP      (CL_NTOH32(0x00020000))
+#define IB_PORT_CAP_REINIT        (CL_NTOH32(0x00040000))
+#define IB_PORT_CAP_HAS_DEV_MGT   (CL_NTOH32(0x00080000))
+#define IB_PORT_CAP_HAS_VEND_CLS  (CL_NTOH32(0x00100000))
+#define IB_PORT_CAP_HAS_DR_NTC    (CL_NTOH32(0x00200000))
+#define IB_PORT_CAP_HAS_CAP_NTC   (CL_NTOH32(0x00400000))
+#define IB_PORT_CAP_HAS_BM        (CL_NTOH32(0x00800000))
+#define IB_PORT_CAP_HAS_LINK_RT_LATENCY (CL_NTOH32(0x01000000))
+#define IB_PORT_CAP_HAS_CLIENT_REREG (CL_NTOH32(0x02000000))
+#define IB_PORT_CAP_RESV26        (CL_NTOH32(0x04000000))
+#define IB_PORT_CAP_RESV27        (CL_NTOH32(0x08000000))
+#define IB_PORT_CAP_RESV28        (CL_NTOH32(0x10000000))
+#define IB_PORT_CAP_RESV29        (CL_NTOH32(0x20000000))
+#define IB_PORT_CAP_RESV30        (CL_NTOH32(0x40000000))
+#define IB_PORT_CAP_RESV31        (CL_NTOH32(0x80000000))
+
+/****f* IBA Base: Types/ib_port_info_get_port_state
+* NAME
+*      ib_port_info_get_port_state
+*
+* DESCRIPTION
+*      Returns the port state.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_port_info_get_port_state(
+       IN              const   ib_port_info_t* const           p_pi )
+{
+       return( (uint8_t)(p_pi->state_info1 & IB_PORT_STATE_MASK) );
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*      Port state.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* IBA Base: Types/ib_port_info_set_port_state
+* NAME
+*      ib_port_info_set_port_state
+*
+* DESCRIPTION
+*      Sets the port state.
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_port_info_set_port_state(
+       IN                              ib_port_info_t* const           p_pi,
+       IN              const   uint8_t                                         port_state )
+{
+       p_pi->state_info1 = (uint8_t)((p_pi->state_info1 & 0xF0) | port_state );
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+*      port_state
+*              [in] Port state value to set.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* IBA Base: Types/ib_port_info_get_vl_cap
+* NAME
+*      ib_port_info_get_vl_cap
+*
+* DESCRIPTION
+*      Gets the VL Capability of a port.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_port_info_get_vl_cap(
+       IN const ib_port_info_t* const p_pi)
+{
+       return((p_pi->vl_cap >> 4) & 0x0F);
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*      VL_CAP field
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* IBA Base: Types/ib_port_info_get_op_vls
+* NAME
+*      ib_port_info_get_op_vls
+*
+* DESCRIPTION
+*      Gets the operational VLs on a port.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_port_info_get_op_vls(
+       IN const ib_port_info_t* const p_pi)
+{
+       return((p_pi->vl_enforce >> 4) & 0x0F);
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*      OP_VLS field
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* IBA Base: Types/ib_port_info_set_op_vls
+* NAME
+*      ib_port_info_set_op_vls
+*
+* DESCRIPTION
+*      Sets the operational VLs on a port.
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_port_info_set_op_vls(
+       IN                              ib_port_info_t* const           p_pi,
+       IN              const   uint8_t                                         op_vls )
+{
+       p_pi->vl_enforce = (uint8_t)((p_pi->vl_enforce & 0x0F) | (op_vls << 4) );
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+*      op_vls
+*              [in] Encoded operation VLs value.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* IBA Base: Types/ib_port_info_set_state_no_change
+* NAME
+*      ib_port_info_set_state_no_change
+*
+* DESCRIPTION
+*      Sets the port state fields to the value for "no change".
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_port_info_set_state_no_change(
+       IN                              ib_port_info_t* const           p_pi )
+{
+       ib_port_info_set_port_state( p_pi, 0 );
+       p_pi->state_info2 = 0;
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_link_speed_sup
+* NAME
+*      ib_port_info_get_link_speed_sup
+*
+* DESCRIPTION
+*      Returns the encoded value for the link speed supported.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_port_info_get_link_speed_sup(
+       IN              const   ib_port_info_t* const           p_pi )
+{
+       return( (uint8_t)((p_pi->state_info1 &
+                       IB_PORT_LINK_SPEED_SUPPORTED_MASK) >>
+                       IB_PORT_LINK_SPEED_SHIFT) );
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*      Returns the encoded value for the link speed supported.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_link_speed_sup
+* NAME
+*      ib_port_info_set_link_speed_sup
+*
+* DESCRIPTION
+*      Given an integer of the supported link speed supported.
+*      Set the appropriate bits in state_info1
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_port_info_set_link_speed_sup(
+       IN                              uint8_t const                           speed,
+       IN                              ib_port_info_t*                         p_pi )
+{
+       p_pi->state_info1 =
+               ( ~IB_PORT_LINK_SPEED_SUPPORTED_MASK & p_pi->state_info1 ) |
+               ( IB_PORT_LINK_SPEED_SUPPORTED_MASK &
+                       (speed << IB_PORT_LINK_SPEED_SHIFT) );
+}
+/*
+* PARAMETERS
+*      speed
+*              [in] Supported Speeds Code.
+*
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*      This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_port_phys_state
+* NAME
+*      ib_port_info_get_port_phys_state
+*
+* DESCRIPTION
+*      Returns the encoded value for the port physical state.
+*
+* SYNOPSIS
+*/
+OSM_INLINE uint8_t     AL_API
+ib_port_info_get_port_phys_state(
+       IN              const   ib_port_info_t* const           p_pi )
+{
+       return( (uint8_t)((p_pi->state_info2 &
+                      IB_PORT_PHYS_STATE_MASK) >>
+                     IB_PORT_PHYS_STATE_SHIFT) );
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*      Returns the encoded value for the port physical state.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_port_phys_state.
+* NAME
+*      ib_port_info_set_port_phys_state
+*
+* DESCRIPTION
+*      Given an integer of the port physical state,
+*      Set the appropriate bits in state_info2
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_port_info_set_port_phys_state(
+       IN                              uint8_t const                           phys_state,
+       IN                              ib_port_info_t*                         p_pi )
+{
+       p_pi->state_info2 =
+               ( ~IB_PORT_PHYS_STATE_MASK & p_pi->state_info2 ) |
+               ( IB_PORT_PHYS_STATE_MASK &
+        (phys_state << IB_PORT_PHYS_STATE_SHIFT) );
+}
+/*
+* PARAMETERS
+*      phys_state
+*              [in] port physical state.
+*
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*      This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_link_down_def_state
+* NAME
+*      ib_port_info_get_link_down_def_state
+*
+* DESCRIPTION
+*      Returns the link down default state.
+*
+* SYNOPSIS
+*/
+OSM_INLINE uint8_t     AL_API
+ib_port_info_get_link_down_def_state(
+       IN              const   ib_port_info_t* const           p_pi )
+{
+       return( (uint8_t)(p_pi->state_info2 & IB_PORT_LNKDWNDFTSTATE_MASK) );
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*      link down default state of the port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_link_down_def_state
+* NAME
+*      ib_port_info_set_link_down_def_state
+*
+* DESCRIPTION
+*      Sets the link down default state of the port.
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_port_info_set_link_down_def_state(
+       IN                              ib_port_info_t* const           p_pi,
+       IN              const   uint8_t                                         link_dwn_state )
+{
+       p_pi->state_info2 = (uint8_t)((p_pi->state_info2 & 0xF0) | link_dwn_state );
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+*      link_dwn_state
+*              [in] Link down default state of the port.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_link_speed_active
+* NAME
+*      ib_port_info_get_link_speed_active
+*
+* DESCRIPTION
+*      Returns the Link Speed Active value assigned to this port.
+*
+* SYNOPSIS
+*/
+OSM_INLINE uint8_t    AL_API
+ib_port_info_get_link_speed_active(
+       IN              const   ib_port_info_t* const           p_pi )
+{
+  return( (uint8_t)((p_pi->link_speed &
+                     IB_PORT_LINK_SPEED_ACTIVE_MASK) >>
+                    IB_PORT_LINK_SPEED_SHIFT) );
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*      Returns the link speed active value assigned to this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+#define IB_LINK_WIDTH_ACTIVE_1X                        1
+#define IB_LINK_WIDTH_ACTIVE_4X                        2
+#define IB_LINK_WIDTH_ACTIVE_12X               8
+#define IB_LINK_SPEED_ACTIVE_2_5       1
+#define IB_LINK_SPEED_ACTIVE_5         2
+#define IB_LINK_SPEED_ACTIVE_10        4
+
+/* following v1 ver1.2 p901 */
+#define IB_MAX_RATE                    10
+#define IB_PATH_RECORD_RATE_2_5_GBS            2
+#define IB_PATH_RECORD_RATE_10_GBS             3
+#define IB_PATH_RECORD_RATE_30_GBS             4
+#define IB_PATH_RECORD_RATE_5_GBS              5
+#define IB_PATH_RECORD_RATE_20_GBS             6
+#define IB_PATH_RECORD_RATE_40_GBS             7
+#define IB_PATH_RECORD_RATE_60_GBS             8
+#define IB_PATH_RECORD_RATE_80_GBS             9
+#define IB_PATH_RECORD_RATE_120_GBS            10
+
+/****f* IBA Base: Types/ib_port_info_compute_rate
+* NAME
+*      ib_port_info_compute_rate
+*
+* DESCRIPTION
+*      Returns the encoded value for the path rate.
+*
+* SYNOPSIS
+*/
+
+AL_INLINE uint8_t     AL_API
+ib_port_info_compute_rate(
+       IN              const   ib_port_info_t* const           p_pi )
+{
+  switch (ib_port_info_get_link_speed_active(p_pi))
+  {
+  case IB_LINK_SPEED_ACTIVE_2_5:
+    switch(p_pi->link_width_active)
+    {
+    case IB_LINK_WIDTH_ACTIVE_1X:
+      return IB_PATH_RECORD_RATE_2_5_GBS;
+
+    case IB_LINK_WIDTH_ACTIVE_4X:
+      return IB_PATH_RECORD_RATE_10_GBS;
+
+    case IB_LINK_WIDTH_ACTIVE_12X:
+      return IB_PATH_RECORD_RATE_30_GBS;
+
+    default:
+      return IB_PATH_RECORD_RATE_2_5_GBS;
+    }
+    break;
+  case IB_LINK_SPEED_ACTIVE_5:
+    switch (p_pi->link_width_active)
+    {
+    case IB_LINK_WIDTH_ACTIVE_1X:
+      return IB_PATH_RECORD_RATE_5_GBS;
+      
+    case IB_LINK_WIDTH_ACTIVE_4X:
+      return IB_PATH_RECORD_RATE_20_GBS;
+      
+    case IB_LINK_WIDTH_ACTIVE_12X:
+      return IB_PATH_RECORD_RATE_60_GBS;
+      
+    default:
+      return IB_PATH_RECORD_RATE_5_GBS;
+    }
+    break;
+  case IB_LINK_SPEED_ACTIVE_10:
+    switch (p_pi->link_width_active)
+    {
+    case IB_LINK_WIDTH_ACTIVE_1X:
+      return IB_PATH_RECORD_RATE_10_GBS;
+      
+    case IB_LINK_WIDTH_ACTIVE_4X:
+      return IB_PATH_RECORD_RATE_40_GBS;
+      
+    case IB_LINK_WIDTH_ACTIVE_12X:
+      return IB_PATH_RECORD_RATE_120_GBS;
+      
+    default:
+      return IB_PATH_RECORD_RATE_10_GBS;
+    }
+    break;
+  default:
+    return IB_PATH_RECORD_RATE_2_5_GBS;
+  }
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*      Returns the encoded value for the link speed supported.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_path_get_ipd
+* NAME
+*      ib_path_get_ipd
+*
+* DESCRIPTION
+*      Returns the encoded value for the inter packet delay.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_path_get_ipd(
+       IN                              uint8_t                                         local_link_width_supported,
+       IN                              uint8_t                                         path_rec_rate )
+{
+       uint8_t ipd = 0;
+
+       switch(local_link_width_supported)
+       {
+               //link_width_supported = 1: 1x
+               case 1:
+                       break;
+
+               //link_width_supported = 3: 1x or 4x
+               case 3:
+                       switch(path_rec_rate & 0x3F)
+                       {
+                               case IB_PATH_RECORD_RATE_2_5_GBS:
+                                       ipd = 3;
+                                       break;
+                               default:
+                                       break;
+                       }
+                       break;
+
+               //link_width_supported = 11: 1x or 4x or 12x
+               case 11:
+                       switch(path_rec_rate & 0x3F)
+                       {
+                               case IB_PATH_RECORD_RATE_2_5_GBS:
+                                       ipd = 11;
+                                       break;
+                               case IB_PATH_RECORD_RATE_10_GBS:
+                                       ipd = 2;
+                                       break;
+                               default:
+                                       break;
+                       }
+                       break;
+
+               default:
+                       break;
+       }
+
+       return ipd;
+}
+/*
+* PARAMETERS
+*      local_link_width_supported
+*              [in] link with supported for this port
+*
+*      path_rec_rate
+*              [in] rate field of the path record
+*
+* RETURN VALUES
+*      Returns the ipd
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+/****f* IBA Base: Types/ib_port_info_get_mtu_cap
+* NAME
+*      ib_port_info_get_mtu_cap
+*
+* DESCRIPTION
+*      Returns the encoded value for the maximum MTU supported by this port.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_port_info_get_mtu_cap(
+       IN              const   ib_port_info_t* const           p_pi )
+{
+       return( (uint8_t)(p_pi->mtu_cap & 0x0F) );
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*      Returns the LMC value assigned to this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* IBA Base: Types/ib_port_info_get_neighbor_mtu
+* NAME
+*      ib_port_info_get_neighbor_mtu
+*
+* DESCRIPTION
+*      Returns the encoded value for the neighbor MTU at this port.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_port_info_get_neighbor_mtu(
+       IN const ib_port_info_t* const p_pi )
+{
+       return( (uint8_t)((p_pi->mtu_smsl & 0xF0) >> 4) );
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*      Returns the encoded value for the neighbor MTU at this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* IBA Base: Types/ib_port_info_set_neighbor_mtu
+* NAME
+*      ib_port_info_set_neighbor_mtu
+*
+* DESCRIPTION
+*      Sets the Neighbor MTU value in the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_port_info_set_neighbor_mtu(
+       IN                              ib_port_info_t* const           p_pi,
+       IN              const   uint8_t                                         mtu )
+{
+       CL_ASSERT( mtu <= 5 );
+       CL_ASSERT( mtu != 0 );
+       p_pi->mtu_smsl = (uint8_t)((p_pi->mtu_smsl & 0x0F) | (mtu << 4));
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+*      mtu
+*              [in] Encoded MTU value to set
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_timeout
+* NAME
+*      ib_port_info_set_timeout
+*
+* DESCRIPTION
+*      Sets the encoded subnet timeout value in the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_port_info_set_timeout(
+       IN                              ib_port_info_t* const           p_pi,
+       IN              const   uint8_t                                         timeout )
+{
+       CL_ASSERT( timeout <= 0x1F );
+       p_pi->subnet_timeout = 
+     (uint8_t)(
+       (p_pi->subnet_timeout & 0x80) | (timeout & 0x1F));
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+*      timeout
+*              [in] Encoded timeout value to set
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_client_rereg
+* NAME
+*      ib_port_info_set_client_rereg
+*
+* DESCRIPTION
+*      Sets the encoded client reregistration bit value in the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+OSM_INLINE void     AL_API
+ib_port_info_set_client_rereg(
+       IN                              ib_port_info_t* const   p_pi,
+       IN              const   uint8_t                                         client_rereg )
+{
+       CL_ASSERT( client_rereg <= 0x1 );
+       p_pi->subnet_timeout = 
+     (uint8_t)(
+       (p_pi->subnet_timeout & 0x1F) | ((client_rereg << 7) & 0x80));
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+*      client_rereg
+*              [in] Client reregistration value to set either 1 or 0
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_timeout
+* NAME
+*      ib_port_info_get_timeout
+*
+* DESCRIPTION
+*      Gets the encoded subnet timeout value in the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+OSM_INLINE uint8_t     AL_API
+ib_port_info_get_timeout(
+  IN                           ib_port_info_t const*   p_pi )
+{
+  return(p_pi->subnet_timeout & 0x1F );
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*      The encoded timeout value
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_client_rereg
+* NAME
+*      ib_port_info_get_client_rereg
+*
+* DESCRIPTION
+*      Gets the encoded client reregistration bit value in the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_port_info_get_client_rereg(
+  IN                           ib_port_info_t const* p_pi )
+{
+  return ( (p_pi->subnet_timeout & 0x80 ) >> 7);
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+*      client_rereg
+*              [in] Client reregistration value to get either 1 or 0
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_hoq_lifetime
+* NAME
+*      ib_port_info_set_hoq_lifetime
+*
+* DESCRIPTION
+*      Sets the Head of Queue Lifetime for which a packet can live in the head 
+*  of VL queue
+*
+* SYNOPSIS
+*/
+OSM_INLINE void     AL_API
+ib_port_info_set_hoq_lifetime(
+  IN           ib_port_info_t* const           p_pi,
+  IN           const   uint8_t                                 hoq_life )
+{
+  p_pi->vl_stall_life = (uint8_t)((hoq_life & 0x1f) |
+                                                                                        (p_pi->vl_stall_life & 0xe0));
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+*      hoq_life
+*              [in] Encoded lifetime value to set
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_hoq_lifetime
+* NAME
+*      ib_port_info_get_hoq_lifetime
+*
+* DESCRIPTION
+*      Gets the Head of Queue Lifetime for which a packet can live in the head 
+*  of VL queue
+*
+* SYNOPSIS
+*/
+OSM_INLINE uint8_t     AL_API
+ib_port_info_get_hoq_lifetime(
+  IN           const ib_port_info_t* const             p_pi )
+{
+  return( (uint8_t)(p_pi->vl_stall_life & 0x1f) );
+}
+
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*     Encoded lifetime value
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_vl_stall_count
+* NAME
+*      ib_port_info_set_vl_stall_count
+*
+* DESCRIPTION
+*      Sets the VL Stall Count which define the number of contigious
+*  HLL (hoq) drops that will put the VL into stalled mode.
+*
+* SYNOPSIS
+*/
+OSM_INLINE void     AL_API
+ib_port_info_set_vl_stall_count(
+  IN           ib_port_info_t* const           p_pi,
+  IN           const   uint8_t                                 vl_stall_count )
+{
+  p_pi->vl_stall_life = (uint8_t)((p_pi->vl_stall_life & 0x1f) |
+                                                                                        ((vl_stall_count << 5) & 0xe0));
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+*      vl_stall_count 
+*              [in] value to set
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_vl_stall_count
+ * NAME
+ *     ib_port_info_get_vl_stall_count
+ *
+ * DESCRIPTION
+ *     Gets the VL Stall Count which define the number of contigious 
+ *  HLL (hoq) drops that will put the VL into stalled mode
+ *
+ * SYNOPSIS
+ */
+AL_INLINE uint8_t     AL_API
+ib_port_info_get_vl_stall_count(
+  IN           const ib_port_info_t* const             p_pi )
+{
+  return( (uint8_t)(p_pi->vl_stall_life & 0xe0) >> 5);
+}
+
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*     vl stall count
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_lmc
+* NAME
+*      ib_port_info_get_lmc
+*
+* DESCRIPTION
+*      Returns the LMC value assigned to this port.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_port_info_get_lmc(
+  IN           const ib_port_info_t* const             p_pi )
+{
+       return( (uint8_t)(p_pi->mkey_lmc & IB_PORT_LMC_MASK) );
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*      Returns the LMC value assigned to this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_lmc
+* NAME
+*      ib_port_info_set_lmc
+*
+* DESCRIPTION
+*      Sets the LMC value in the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_port_info_set_lmc(
+       IN                              ib_port_info_t* const           p_pi,
+       IN              const   uint8_t                                         lmc )
+{
+       CL_ASSERT( lmc <= 0x7 );
+       p_pi->mkey_lmc = (uint8_t)((p_pi->mkey_lmc & 0xF8) | lmc);
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+*      lmc
+*              [in] LMC value to set, must be less than 7.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_link_speed_enabled
+* NAME
+*      ib_port_info_get_link_speed_enabled
+*
+* DESCRIPTION
+*      Returns the link speed enabled value assigned to this port.
+*
+* SYNOPSIS
+*/
+OSM_INLINE uint8_t     AL_API
+ib_port_info_get_link_speed_enabled(
+       IN              const   ib_port_info_t* const           p_pi )
+{
+       return( (uint8_t)(p_pi->link_speed & IB_PORT_LINK_SPEED_ENABLED_MASK) );
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*      Port state.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+/****f* IBA Base: Types/ib_port_info_set_link_speed_enabled
+* NAME
+*      ib_port_info_set_link_speed_enabled
+*
+* DESCRIPTION
+*      Sets the link speed enabled value in the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_port_info_set_link_speed_enabled(
+       IN                              ib_port_info_t* const           p_pi,
+       IN              const   uint8_t                                         link_speed_enabled )
+{
+       p_pi->link_speed = (uint8_t)((p_pi->link_speed & 0xF0) | link_speed_enabled );
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+*      link_speed_enabled
+*              [in] link speed enabled value to set.
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_get_mpb
+* NAME
+*      ib_port_info_get_mpb
+*
+* DESCRIPTION
+*      Returns the M_Key protect bits assigned to this port.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_port_info_get_mpb(
+       IN              const   ib_port_info_t* const           p_pi )
+{
+       return( (uint8_t)((p_pi->mkey_lmc & IB_PORT_MPB_MASK) >>
+                       IB_PORT_MPB_SHIFT) );
+}
+/*
+* PARAMETERS
+*      p_ni
+*              [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*      Returns the M_Key protect bits assigned to this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_mpb
+* NAME
+*      ib_port_info_set_mpb
+*
+* DESCRIPTION
+*      Set the M_Key protect bits of this port.
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_port_info_set_mpb(
+       IN                              ib_port_info_t*                         p_pi,
+       IN                              uint8_t                                         mpb )
+{
+       p_pi->mkey_lmc =
+               (~IB_PORT_MPB_MASK & p_pi->mkey_lmc) |
+               ( IB_PORT_MPB_MASK & (mpb << IB_PORT_MPB_SHIFT) );
+}
+/*
+* PARAMETERS
+*      mpb
+*              [in] M_Key protect bits
+*      p_ni
+*              [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_port_info_set_phy_and_overrun_err_thd
+* NAME
+*      ib_port_info_set_phy_and_overrun_err_thd
+*
+* DESCRIPTION
+*      Sets the Phy Link and Credits Overrun Errors Threshold
+*
+* SYNOPSIS
+*/
+OSM_INLINE void     AL_API
+ib_port_info_set_phy_and_overrun_err_thd(
+  IN           ib_port_info_t* const           p_pi,
+  IN           uint8_t                         phy_threshold,
+  IN           uint8_t                         overrun_threshold )
+{
+  p_pi->error_threshold = 
+        (uint8_t)( ((phy_threshold & 0x0F) << 4) | (overrun_threshold & 0x0F) );
+}
+/*
+* PARAMETERS
+*      p_pi
+*              [in] Pointer to a PortInfo attribute.
+*
+*      phy_threshold
+*              [in] Physical Link Errors Threshold above which Trap 129 is generated 
+*
+*  overrun_threshold
+*     [in] Credits overrun Errors Threshold above which Trap 129 is generated 
+*
+* RETURN VALUES
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+typedef uint8_t                ib_svc_name_t[64];
+
+#include <complib/cl_packon.h>
+typedef struct _ib_service_record
+{
+       ib_net64_t              service_id;
+       ib_gid_t                service_gid;
+       ib_net16_t              service_pkey;
+       ib_net16_t              resv;
+       ib_net32_t              service_lease;
+       uint8_t                 service_key[16];
+       ib_svc_name_t   service_name;
+       uint8_t                 service_data8[16];
+       ib_net16_t              service_data16[8];
+       ib_net32_t              service_data32[4];
+       ib_net64_t              service_data64[2];
+
+}      PACK_SUFFIX ib_service_record_t;
+#include <complib/cl_packoff.h>
+
+#include <complib/cl_packon.h>
+typedef struct _ib_portinfo_record
+{
+       ib_net16_t              lid;
+       uint8_t                 port_num;
+       uint8_t                 resv;
+       ib_port_info_t  port_info;
+       uint8_t                 pad[6];
+
+}      PACK_SUFFIX ib_portinfo_record_t;
+#include <complib/cl_packoff.h>
+
+#include <complib/cl_packon.h>
+typedef struct _ib_link_record
+{
+       ib_net16_t              from_lid;
+       uint8_t                 from_port_num;
+       uint8_t                 to_port_num;
+       ib_net16_t              to_lid;
+       uint8_t                 pad[2];
+
+}      PACK_SUFFIX ib_link_record_t;
+#include <complib/cl_packoff.h>
+
+#include <complib/cl_packon.h>
+typedef struct _ib_sminfo_record
+{
+       ib_net16_t              lid;
+       uint16_t                resv0;
+       ib_sm_info_t    sm_info;
+       uint8_t                 pad[7];
+
+}      PACK_SUFFIX ib_sminfo_record_t;
+#include <complib/cl_packoff.h>
+
+/****s* IBA Base: Types/ib_lft_record_t
+* NAME
+*      ib_lft_record_t
+*
+* DESCRIPTION
+*      IBA defined LinearForwardingTable. (14.2.5.6)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_lft_record
+{
+       ib_net16_t              lid;
+       ib_net16_t              block_num;
+       uint32_t                   resv0;
+       uint8_t       lft[64];
+}      PACK_SUFFIX ib_lft_record_t;
+#include <complib/cl_packoff.h>
+/************/
+
+/****s* IBA Base: Types/ib_switch_info_t
+* NAME
+*      ib_switch_info_t
+*
+* DESCRIPTION
+*      IBA defined SwitchInfo. (14.2.5.4)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_switch_info
+{
+       ib_net16_t                      lin_cap;
+       ib_net16_t                      rand_cap;
+       ib_net16_t                      mcast_cap;
+       ib_net16_t                      lin_top;
+       uint8_t                         def_port;
+       uint8_t                         def_mcast_pri_port;
+       uint8_t                         def_mcast_not_port;
+       uint8_t                         life_state;
+       ib_net16_t                      lids_per_port;
+       ib_net16_t                      enforce_cap;
+       uint8_t                         flags;
+
+}      PACK_SUFFIX ib_switch_info_t;
+#include <complib/cl_packoff.h>
+/************/
+
+#include <complib/cl_packon.h>
+typedef struct _ib_switch_info_record
+{
+       ib_net16_t                      lid;
+       uint16_t                        resv0;
+       ib_switch_info_t        switch_info;
+       uint8_t                         pad[3];
+
+}      PACK_SUFFIX ib_switch_info_record_t;
+#include <complib/cl_packoff.h>
+
+#define IB_SWITCH_PSC 0x04
+
+/****f* IBA Base: Types/ib_switch_info_get_state_change
+* NAME
+*      ib_switch_info_get_state_change
+*
+* DESCRIPTION
+*      Returns the value of the state change flag.
+*
+* SYNOPSIS
+*/
+AL_INLINE boolean_t     AL_API
+ib_switch_info_get_state_change(
+       IN              const   ib_switch_info_t* const         p_si )
+{
+       return( (p_si->life_state & IB_SWITCH_PSC) == IB_SWITCH_PSC );
+}
+/*
+* PARAMETERS
+*      p_si
+*              [in] Pointer to a SwitchInfo attribute.
+*
+* RETURN VALUES
+*      Returns the value of the state change flag.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_switch_info_clear_state_change
+* NAME
+*      ib_switch_info_clear_state_change
+*
+* DESCRIPTION
+*      Clears the switch's state change bit.
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_switch_info_clear_state_change(
+       IN                              ib_switch_info_t* const         p_si )
+{
+       p_si->life_state = (uint8_t)(p_si->life_state & 0xFB);
+}
+/*
+* PARAMETERS
+*      p_ni
+*              [in] Pointer to a PortInfo attribute.
+*
+* RETURN VALUES
+*      Returns the LMC value assigned to this port.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+/****f* IBA Base: Types/ib_switch_info_is_enhanced_port_0
+* NAME
+*      ib_switch_info_is_enhanced_port_0
+*
+* DESCRIPTION
+*      Returns TRUE if the enhancedPort0 bit is on (meaning the switch
+*  port zero supports enhanced functions).
+*  Returns FALSE otherwise.
+*
+* SYNOPSIS
+*/
+OSM_INLINE boolean_t     AL_API
+ib_switch_info_is_enhanced_port_0(
+       IN              const   ib_switch_info_t* const         p_si )
+{
+       return( (p_si->flags & 0x08) == 0x08 );
+}
+/*
+* PARAMETERS
+*      p_si
+*              [in] Pointer to a SwitchInfo attribute.
+*
+* RETURN VALUES
+*      Returns TRUE if the switch supports enhanced port 0. FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****s* IBA Base: Types/ib_guid_info_t
+* NAME
+*      ib_guid_info_t
+*
+* DESCRIPTION
+*      IBA defined GuidInfo. (14.2.5.5)
+*
+* SYNOPSIS
+*/
+#define        GUID_TABLE_MAX_ENTRIES          8
+
+#include <complib/cl_packon.h>
+typedef struct _ib_guid_info
+{
+       ib_net64_t                      guid[GUID_TABLE_MAX_ENTRIES];
+
+}      PACK_SUFFIX ib_guid_info_t;
+#include <complib/cl_packoff.h>
+/************/
+
+#define IB_NUM_PKEY_ELEMENTS_IN_BLOCK          32
+/****s* IBA Base: Types/ib_pkey_table_t
+* NAME
+*      ib_pkey_table_t
+*
+* DESCRIPTION
+*      IBA defined PKey table. (14.2.5.7)
+*
+* SYNOPSIS
+*/
+
+#include <complib/cl_packon.h>
+typedef struct _ib_pkey_table
+{
+       ib_net16_t                      pkey_entry[IB_NUM_PKEY_ELEMENTS_IN_BLOCK];
+
+}      PACK_SUFFIX ib_pkey_table_t;
+#include <complib/cl_packoff.h>
+/************/
+
+/****s* IBA Base: Types/ib_pkey_table_record_t
+* NAME
+*      ib_pkey_table_record_t
+*
+* DESCRIPTION
+*      IBA defined P_Key Table Record for SA Query. (15.2.5.11)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_pkey_table_record
+{
+       ib_net16_t                      lid; // for CA: lid of port, for switch lid of port 0
+       uint16_t                                block_num;
+   uint8_t                             port_num; // for swithc: port number, for CA: reserved
+       uint8_t                         reserved1;
+       uint16_t                        reserved2;
+       ib_pkey_table_t pkey_tbl;
+
+}      PACK_SUFFIX ib_pkey_table_record_t;
+#include <complib/cl_packoff.h>
+/************/
+
+#define IB_MAX_NUM_VLS 16
+/****s* IBA Base: Types/ib_slvl_table_t
+* NAME
+*      ib_slvl_table_t
+*
+* DESCRIPTION
+*      IBA defined SL2VL Mapping Table Attribute. (14.2.5.8)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_slvl_table
+{
+       uint8_t raw_vl_by_sl[IB_MAX_NUM_VLS/2];
+}      PACK_SUFFIX ib_slvl_table_t;
+#include <complib/cl_packoff.h>
+/************/
+
+/****s* IBA Base: Types/ib_slvl_table_record_t
+* NAME
+*      ib_slvl_table_record_t
+*
+* DESCRIPTION
+*      IBA defined Sl to VL Mapping Table Record for SA Query. (15.2.5.4)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_slvl_table_record
+{
+       ib_net16_t              lid; // for CA: lid of port, for switch lid of port 0
+       uint8_t                 in_port_num;    // reserved for CA's
+       uint8_t                 out_port_num;   // reserved for CA's
+       uint32_t                resv;
+       ib_slvl_table_t slvl_tbl;
+
+}      PACK_SUFFIX ib_slvl_table_record_t;
+#include <complib/cl_packoff.h>
+/************/
+
+/****f* IBA Base: Types/ib_slvl_table_set
+* NAME
+*      ib_slvl_table_set
+*
+* DESCRIPTION
+*      Set slvl table entry.
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_slvl_table_set(
+  IN           ib_slvl_table_t*        p_slvl_tbl,
+  IN           uint8_t                 sl_index,
+  IN     uint8_t                 vl )
+{
+  uint8_t idx = sl_index/2;
+  CL_ASSERT(vl <= 15);
+  CL_ASSERT(sl_index <= 15);
+
+  if (sl_index%2)
+  {
+    /* this is an odd sl. Need to update the ls bits */
+    p_slvl_tbl->raw_vl_by_sl[idx] = ( p_slvl_tbl->raw_vl_by_sl[idx] & 0xF0 ) | vl ;
+  }
+  else
+  {
+    /* this is an even sl. Need to update the ms bits */
+    p_slvl_tbl->raw_vl_by_sl[idx] = ( vl << 4 ) | ( p_slvl_tbl->raw_vl_by_sl[idx] & 0x0F );
+  }
+}
+/*
+* PARAMETERS
+*      p_slvl_tbl
+*              [in] pointer to ib_slvl_table_t object.
+*
+*      sl_index
+*              [in] the sl index in the table to be updated.
+*
+*      vl
+*              [in] the vl value to update for that sl.
+*
+* RETURN VALUES
+*      None
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_slvl_table_t
+*********/
+
+/****f* IBA Base: Types/ib_slvl_table_get
+* NAME
+*      ib_slvl_table_get
+*
+* DESCRIPTION
+*      Get slvl table entry.
+*
+* SYNOPSIS
+*/
+OSM_INLINE uint8_t     AL_API
+ib_slvl_table_get(
+  IN           const ib_slvl_table_t*        p_slvl_tbl,
+  IN           uint8_t                 sl_index )
+{
+  uint8_t idx = sl_index/2;
+  CL_ASSERT(sl_index <= 15);
+
+  if (sl_index%2)
+  {
+    /* this is an odd sl. Need to return the ls bits. */
+    return ( p_slvl_tbl->raw_vl_by_sl[idx] & 0x0F );
+  }
+  else
+  {
+    /* this is an even sl. Need to return the ms bits. */
+    return ( (p_slvl_tbl->raw_vl_by_sl[idx] & 0xF0) >> 4 );
+  }
+}
+/*
+* PARAMETERS
+*      p_slvl_tbl
+*              [in] pointer to ib_slvl_table_t object.
+*
+*      sl_index
+*              [in] the sl index in the table whose value should be returned.
+*
+* RETURN VALUES
+*      vl that is updated for that sl.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_slvl_table_t
+*********/
+
+/****s* IBA Base: Types/ib_vl_arb_element_t
+* NAME
+*      ib_vl_arb_element_t
+*
+* DESCRIPTION
+*      IBA defined VL Arbitration Table Element. (14.2.5.9)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_vl_arb_element
+{
+  uint8_t vl;
+  uint8_t weight;
+
+}      PACK_SUFFIX ib_vl_arb_element_t;
+#include <complib/cl_packoff.h>
+/************/
+
+#define IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK 32
+/****s* IBA Base: Types/ib_vl_arb_table_t
+* NAME
+*      ib_vl_arb_table_t
+*
+* DESCRIPTION
+*      IBA defined VL Arbitration Table. (14.2.5.9)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_vl_arb_table
+{
+       ib_vl_arb_element_t vl_entry[IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK];
+
+}      PACK_SUFFIX ib_vl_arb_table_t;
+#include <complib/cl_packoff.h>
+/************/
+
+/****s* IBA Base: Types/ib_vl_arb_table_record_t
+* NAME
+*      ib_vl_arb_table_record_t
+*
+* DESCRIPTION
+*      IBA defined VL Arbitration Table Record for SA Query. (15.2.5.9)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_vl_arb_table_record
+{
+       ib_net16_t                      lid; // for CA: lid of port, for switch lid of port 0
+       uint8_t                         port_num;
+       uint8_t                         block_num;
+       uint32_t                        reserved;
+       ib_vl_arb_table_t       vl_arb_tbl;
+
+}      PACK_SUFFIX ib_vl_arb_table_record_t;
+#include <complib/cl_packoff.h>
+/************/
+
+/*
+ *     Global route header information received with unreliable datagram messages
+ */
+#include <complib/cl_packon.h>
+typedef struct _ib_grh
+{
+       ib_net32_t                              ver_class_flow;
+       ib_net16_t                              resv1;
+       uint8_t                                 resv2;
+       uint8_t                                 hop_limit;
+       ib_gid_t                                src_gid;
+       ib_gid_t                                dest_gid;
+
+}      PACK_SUFFIX ib_grh_t;
+#include <complib/cl_packoff.h>
+
+/****f* IBA Base: Types/ib_grh_get_ver_class_flow
+* NAME
+*      ib_grh_get_ver_class_flow
+*
+* DESCRIPTION
+*      Get encoded version, traffic class and flow label in grh
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_grh_get_ver_class_flow(
+       IN              const   ib_net32_t                                      ver_class_flow,
+               OUT                     uint8_t* const                          p_ver,
+               OUT                     uint8_t* const                          p_tclass,
+               OUT                     uint32_t* const                         p_flow_lbl )
+{
+       ib_net32_t tmp_ver_class_flow;
+
+       if (p_ver)
+               *p_ver = (uint8_t)(ver_class_flow & 0x0f);
+
+       tmp_ver_class_flow = ver_class_flow >> 4;
+
+       if (p_tclass)
+               *p_tclass = (uint8_t)(tmp_ver_class_flow & 0xff);
+
+       tmp_ver_class_flow = tmp_ver_class_flow >> 8;
+
+       if (p_flow_lbl)
+               *p_flow_lbl = tmp_ver_class_flow & 0xfffff;
+}
+/*
+* PARAMETERS
+*      ver_class_flow
+*              [in] the version, traffic class and flow label info.
+*
+* RETURN VALUES
+*      p_ver
+*              [out] pointer to the version info.
+*
+*      p_tclass
+*              [out] pointer to the traffic class info.
+*
+*      p_flow_lbl
+*              [out] pointer to the flow label info
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_grh_t
+*********/
+
+/****f* IBA Base: Types/ib_grh_set_ver_class_flow
+* NAME
+*      ib_grh_set_ver_class_flow
+*
+* DESCRIPTION
+*      Set encoded version, traffic class and flow label in grh
+*
+* SYNOPSIS
+*/
+AL_INLINE ib_net32_t     AL_API
+ib_grh_set_ver_class_flow(
+       IN              const   uint8_t                                         ver,
+       IN              const   uint8_t                                         tclass,
+       IN              const   uint32_t                                        flow_lbl )
+{
+       ib_net32_t              ver_class_flow;
+
+       ver_class_flow = flow_lbl;
+       ver_class_flow = ver_class_flow << 8;
+       ver_class_flow = ver_class_flow | tclass;
+       ver_class_flow = ver_class_flow << 4;
+       ver_class_flow = ver_class_flow | ver;
+       return (ver_class_flow);
+}
+/*
+* PARAMETERS
+*      ver
+*              [in] the version info.
+*
+*      tclass
+*              [in] the traffic class info.
+*
+*      flow_lbl
+*              [in] the flow label info
+*
+* RETURN VALUES
+*      ver_class_flow
+*              [out] the version, traffic class and flow label info.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_grh_t
+*********/
+
+/****s* IBA Base: Types/ib_member_rec_t
+* NAME
+*      ib_member_rec_t
+*
+* DESCRIPTION
+*      Multicast member record, used to create, join, and leave multicast
+*      groups.
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_member_rec
+{
+       ib_gid_t                                mgid;
+       ib_gid_t                                port_gid;
+       ib_net32_t                              qkey;
+       ib_net16_t                              mlid;
+       uint8_t                                 mtu;
+       uint8_t                                 tclass;
+       ib_net16_t                              pkey;
+       uint8_t                                 rate;
+       uint8_t                                 pkt_life;
+       ib_net32_t                              sl_flow_hop;
+       uint8_t                                 scope_state;
+/*     uint8_t                                 proxy_join:1; */
+/* TODO : Under DDK got C4214 which note that using bitfield can cause problems 
+    in porting to other compilers  */
+    uint8_t                 proxy_join;
+       uint8_t                                 reserved[2];
+       uint8_t                                 pad[4];
+
+}      PACK_SUFFIX ib_member_rec_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*      mgid
+*              Multicast GID address for this multicast group.
+*
+*      port_gid
+*              Valid GID of the endpoint joining this multicast group.
+*
+*      requestor_gid
+*              GID of the endpoint making this request on hehave of port_gid.
+*
+*      qkey
+*              Q_Key to be sued by this multicast group.
+*
+*      mlid
+*              Multicast LID for this multicast group.
+*
+*      mtu
+*              MTU and MTU selector fields to use on this path
+*
+*      tclass
+*              Another global routing parameter.
+*
+*      pkey
+*              Partition key (P_Key) to use for this member.
+*
+*      rate
+*              Rate and rate selector fields to use on this path.
+*
+*      pkt_life
+*              Packet lifetime
+*
+*      sl_flow_hop
+*              Global routing parameters: service level, hop count, and flow label.
+*
+*      scope_state
+*              MGID scope and JoinState of multicast request.
+*
+*      proxy_join
+*              Enables others in the Partition to proxy add/remove from the group
+*
+* SEE ALSO
+*********/
+
+/****f* IBA Base: Types/ib_member_get_sl_flow_hop
+* NAME
+*      ib_member_get_sl_flow_hop
+*
+* DESCRIPTION
+*      Get encoded sl flow label and hop limit
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_member_get_sl_flow_hop(
+       IN              const   ib_net32_t                                      sl_flow_hop,
+               OUT                     uint8_t* const                          p_sl,
+               OUT                     uint32_t* const                         p_flow_lbl,
+               OUT                     uint8_t* const                          p_hop )
+{
+       ib_net32_t tmp_sl_flow_hop;
+
+       if (p_sl)
+               *p_sl = (uint8_t)(sl_flow_hop & 0x0f);
+
+       tmp_sl_flow_hop = sl_flow_hop >> 4;
+
+       if (p_flow_lbl)
+               *p_flow_lbl = (uint32_t)(tmp_sl_flow_hop & 0xfffff);
+
+       tmp_sl_flow_hop = tmp_sl_flow_hop >> 20;
+
+       if (p_hop)
+               *p_hop = (uint8_t)(tmp_sl_flow_hop & 0xff);
+}
+/*
+* PARAMETERS
+*      sl_flow_hop
+*              [in] the sl flow label and hop limit of MC Group
+*
+* RETURN VALUES
+*      p_sl
+*              [out] pointer to the service level
+*
+*      p_flow_lbl
+*              [out] pointer to the flow label info
+*
+*      p_hop
+*              [out] pointer to the hop count limit.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_member_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_member_set_sl_flow_hop
+* NAME
+*      ib_member_set_sl_flow_hop
+*
+* DESCRIPTION
+*      Set encoded version, sl flow and hop
+*
+* SYNOPSIS
+*/
+AL_INLINE ib_net32_t     AL_API
+ib_member_set_sl_flow_hop(
+       IN              const   uint8_t                                         sl,
+       IN              const   uint32_t                                        flow_label,
+       IN              const   uint8_t                                         hop_limit )
+{
+       ib_net32_t              sl_flow_hop;
+
+       sl_flow_hop = hop_limit;
+       sl_flow_hop = sl_flow_hop << 20;
+       sl_flow_hop = sl_flow_hop | flow_label;
+       sl_flow_hop = sl_flow_hop << 2;
+       sl_flow_hop = sl_flow_hop | sl;
+       return (sl_flow_hop);
+}
+/*
+* PARAMETERS
+*      sl
+*              [in] the service level.
+*
+*      flow_lbl
+*              [in] the flow label info
+*
+*      hop_limit
+*              [in] the hop limit.
+*
+* RETURN VALUES
+*      sl_flow_hop
+*              [out] the sl flow label and hop limit
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_member_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_member_get_scope_state
+* NAME
+*      ib_member_get_scope_state
+*
+* DESCRIPTION
+*      Get encoded MGID scope and JoinState
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_member_get_scope_state(
+       IN              const   uint8_t                                         scope_state,
+               OUT                     uint8_t* const                          p_scope,
+               OUT                     uint8_t* const                          p_state )
+{
+       uint8_t         tmp_scope_state;
+
+       if (p_state)
+               *p_state = (uint8_t)(scope_state & 0x0f);
+
+       tmp_scope_state = scope_state >> 4;
+
+       if (p_scope)
+               *p_scope = (uint8_t)(tmp_scope_state & 0x0f);
+
+}
+/*
+* PARAMETERS
+*      scope_state
+*              [in] the scope and state
+*
+* RETURN VALUES
+*      p_scope
+*              [out] pointer to the MGID scope
+*
+*      p_state
+*              [out] pointer to the join state
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_member_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_member_set_scope_state
+* NAME
+*      ib_member_set_scope_state
+*
+* DESCRIPTION
+*      Set encoded version, MGID scope and JoinState
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_member_set_scope_state(
+       IN              const   uint8_t                                         scope,
+       IN              const   uint8_t                                         state )
+{
+       uint8_t         scope_state;
+
+       scope_state = scope;
+       scope_state = scope_state << 4;
+       scope_state = scope_state | state;
+       return (scope_state);
+}
+/*
+* PARAMETERS
+*      scope
+*              [in] the MGID scope
+*
+*      state
+*              [in] the JoinState
+*
+* RETURN VALUES
+*      scope_state
+*              [out] the encoded one
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_member_rec_t
+*********/
+
+/****f* IBA Base: Types/ib_member_set_join_state
+* NAME
+*      ib_member_set_join_state
+*
+* DESCRIPTION
+*      Set JoinState
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_member_set_join_state(
+       IN      OUT                     ib_member_rec_t                         *p_mc_rec,
+       IN              const   uint8_t                                         state )
+{
+   /* keep the scope as it is */
+       p_mc_rec->scope_state = (p_mc_rec->scope_state & 0xF0) | (0x0f & state);
+}
+/*
+* PARAMETERS
+*      p_mc_rec
+*              [in] pointer to the member record
+*
+*      state
+*              [in] the JoinState
+*
+* RETURN VALUES
+*      NONE
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_member_rec_t
+*********/
+
+/*
+ * Join State Codes:
+ */
+#define IB_MC_REC_STATE_FULL_MEMBER 0x01
+#define IB_MC_REC_STATE_NON_MEMBER 0x02
+#define IB_MC_REC_STATE_SEND_ONLY_MEMBER 0x04
+
+/*
+ *     Generic MAD notice types
+ */
+#define IB_NOTICE_TYPE_FATAL                           0x00
+#define IB_NOTICE_TYPE_URGENT                          0x01
+#define IB_NOTICE_TYPE_SECURITY                                0x02
+#define IB_NOTICE_TYPE_SUBN_MGMT                       0x03
+#define IB_NOTICE_TYPE_INFO                                    0x04
+#define IB_NOTICE_TYPE_EMPTY                           0x7F
+
+
+#include <complib/cl_packon.h>
+typedef struct _ib_mad_notice_attr    // Total Size calc  Accumulated
+{
+  uint8_t                              generic_type;    // 1                1
+  
+  union _notice_g_or_v
+  {
+        struct _notice_generic            // 5                6
+        {
+               uint8_t         prod_type_msb;
+               ib_net16_t      prod_type_lsb;
+               ib_net16_t      trap_num;
+        }      PACK_SUFFIX generic;
+        
+        struct _notice_vend
+        {
+               uint8_t         vend_id_msb;
+               ib_net16_t      vend_id_lsb;
+               ib_net16_t      dev_id;
+        }      PACK_SUFFIX vend;
+  } g_or_v;
+  
+  ib_net16_t                   issuer_lid;    // 2                 8
+  ib_net16_t                   toggle_count;  // 2                 10
+  
+  union _data_details               // 54                64
+       {
+         struct _raw_data
+         {
+                uint8_t        details[54];
+         } PACK_SUFFIX raw_data;
+
+         struct _ntc_64_67
+         {
+                uint8_t    res[6];
+                ib_gid_t   gid;        // the Node or Multicast Group that came in/out
+         } PACK_SUFFIX ntc_64_67;
+
+         struct _ntc_128 {
+                ib_net16_t sw_lid; // the sw lid of which link state changed
+         } PACK_SUFFIX ntc_128;
+         
+         struct _ntc_129_131 {
+                ib_net16_t    pad;
+                ib_net16_t    lid;             // lid and port number of the violation
+                uint8_t     port_num;
+         } PACK_SUFFIX ntc_129_131;
+         
+         struct _ntc_144 {
+                ib_net16_t    pad1;
+                ib_net16_t    lid;             // lid where capability mask changed
+                ib_net16_t    pad2;
+                ib_net32_t    new_cap_mask; // new capability mask
+         } PACK_SUFFIX ntc_144;
+
+         struct _ntc_145 {
+                ib_net16_t    pad1;
+                ib_net16_t    lid;             // lid where sys guid changed
+                ib_net16_t    pad2;
+                ib_net64_t    new_sys_guid; // new system image guid
+         } PACK_SUFFIX ntc_145;
+
+         struct _ntc_256 {                       // total: 54
+                ib_net16_t    pad1;                   // 2
+                ib_net16_t    lid;                    // 2
+                ib_net16_t    pad2;                   // 2
+                uint8_t       method;                 // 1
+                uint8_t       pad3;                   // 1
+                ib_net16_t    attr_id;                // 2
+                ib_net32_t    attr_mod;               // 4
+                ib_net64_t    mkey;                   // 8
+                uint8_t       dr_slid;                // 1
+                uint8_t       dr_trunc_hop;           // 1
+                uint8_t       dr_rtn_path[30];        // 30
+         } PACK_SUFFIX ntc_256;
+
+         struct _ntc_257_258 // violation of p/q_key // 49
+         {
+                ib_net16_t    pad1;                   // 2
+                ib_net16_t    lid1;                   // 2
+                ib_net16_t    lid2;                   // 2
+                ib_net32_t    key;                    // 2
+                uint8_t       sl;                     // 1
+                ib_net32_t    qp1;                    // 4
+                ib_net32_t    qp2;                    // 4
+                ib_gid_t      gid1;                   // 16
+                ib_gid_t      gid2;                   // 16
+         } PACK_SUFFIX ntc_257_258;
+
+         struct _ntc_259 // p/q_key violation with sw info 53
+         {
+                ib_net16_t    data_valid;   // 2
+                ib_net16_t    lid1;         // 2
+                ib_net16_t    lid2;         // 2
+                ib_net32_t    key;          // 4
+                uint8_t       sl;           // 1
+                ib_net32_t    qp1;          // 4
+                uint8_t       qp2_msb;      // 1
+                ib_net16_t    qp2_lsb;      // 2
+                ib_gid_t      gid1;         // 16
+                ib_gid_t      gid2;         // 16
+                ib_net16_t    sw_lid;       // 2
+                uint8_t       port_no;      // 1
+         } PACK_SUFFIX ntc_259;
+
+       } data_details;
+
+  ib_gid_t                     issuer_gid;    // 16          80
+
+}      PACK_SUFFIX ib_mad_notice_attr_t;
+#include <complib/cl_packoff.h>
+
+/****f* IBA Base: Types/ib_notice_is_generic
+* NAME
+*      ib_notice_is_generic
+*
+* DESCRIPTION
+*      Check if the notice is generic
+*
+* SYNOPSIS
+*/
+OSM_INLINE boolean_t     AL_API
+ib_notice_is_generic(
+  IN              const        ib_mad_notice_attr_t *p_ntc)
+{
+  return (p_ntc->generic_type & 0x80);
+}
+/*
+* PARAMETERS
+*      p_ntc
+*              [in] Pointer to  the notice MAD attribute
+*
+* RETURN VALUES
+*      TRUE if mad is generic
+*
+* SEE ALSO
+*      ib_mad_notice_attr_t
+*********/
+
+/****f* IBA Base: Types/ib_notice_get_type
+* NAME
+*      ib_notice_get_type
+*
+* DESCRIPTION
+*      Get the notice type
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_notice_get_type(
+  IN              const        ib_mad_notice_attr_t *p_ntc)
+{
+  return p_ntc->generic_type & 0x7f;
+}
+/*
+* PARAMETERS
+*      p_ntc
+*              [in] Pointer to  the notice MAD attribute
+*
+* RETURN VALUES
+*      TRUE if mad is generic
+*
+* SEE ALSO
+*      ib_mad_notice_attr_t
+*********/
+
+/****f* IBA Base: Types/ib_notice_get_prod_type
+* NAME
+*      ib_notice_get_prod_type
+*
+* DESCRIPTION
+*      Get the notice Producer Type of Generic Notice
+*
+* SYNOPSIS
+*/
+AL_INLINE ib_net32_t     AL_API
+ib_notice_get_prod_type(
+  IN              const        ib_mad_notice_attr_t *p_ntc)
+{
+  uint32_t pt;
+  pt = cl_ntoh16(p_ntc->g_or_v.generic.prod_type_lsb) |
+    (p_ntc->g_or_v.generic.prod_type_msb << 16);
+  return cl_hton32(pt);
+}
+/*
+* PARAMETERS
+*      p_ntc
+*              [in] Pointer to the notice MAD attribute
+*
+* RETURN VALUES
+*      The producer type
+*
+* SEE ALSO
+*      ib_mad_notice_attr_t
+*********/
+
+/****f* IBA Base: Types/ib_notice_set_prod_type
+* NAME
+*      ib_notice_set_prod_type
+*
+* DESCRIPTION
+*      Set the notice Producer Type of Generic Notice
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_notice_set_prod_type(
+  IN ib_mad_notice_attr_t *p_ntc,
+  IN ib_net32_t prod_type_val)
+{
+  uint32_t ptv = cl_ntoh32(prod_type_val);
+  p_ntc->g_or_v.generic.prod_type_lsb = cl_hton16( (uint16_t)(ptv & 0x0000ffff));
+  p_ntc->g_or_v.generic.prod_type_msb = (uint8_t)( (ptv & 0x00ff0000) >> 16);
+}
+/*
+* PARAMETERS
+*      p_ntc
+*              [in] Pointer to the notice MAD attribute
+*
+*  prod_type
+*     [in] The producer Type code
+*
+* RETURN VALUES
+*      None
+*
+* SEE ALSO
+*      ib_mad_notice_attr_t
+*********/
+
+/****f* IBA Base: Types/ib_notice_get_vend_id
+* NAME
+*      ib_notice_get_vend_id
+*
+* DESCRIPTION
+*      Get the Vendor Id of Vendor type Notice
+*
+* SYNOPSIS
+*/
+AL_INLINE ib_net32_t     AL_API
+ib_notice_get_vend_id(
+  IN              const        ib_mad_notice_attr_t *p_ntc)
+{
+  uint32_t vi;
+  vi = cl_ntoh16(p_ntc->g_or_v.vend.vend_id_lsb) |
+    (p_ntc->g_or_v.vend.vend_id_msb << 16);
+  return cl_hton32(vi);
+}
+/*
+* PARAMETERS
+*      p_ntc
+*              [in] Pointer to  the notice MAD attribute
+*
+* RETURN VALUES
+*      The Vendor Id of Vendor type Notice
+*
+* SEE ALSO
+*      ib_mad_notice_attr_t
+*********/
+
+/****f* IBA Base: Types/ib_notice_set_vend_id
+* NAME
+*      ib_notice_set_vend_id
+*
+* DESCRIPTION
+*      Set the notice Producer Type of Generic Notice
+*
+* SYNOPSIS
+*/
+AL_INLINE void     AL_API
+ib_notice_set_vend_id(
+  IN ib_mad_notice_attr_t *p_ntc,
+  IN ib_net32_t vend_id)
+{
+  uint32_t vi = cl_ntoh32(vend_id);
+  p_ntc->g_or_v.vend.vend_id_lsb = cl_hton16((uint16_t)(vi & 0x0000ffff));
+  p_ntc->g_or_v.vend.vend_id_msb = (uint8_t)((vi & 0x00ff0000) >> 16);
+}
+/*
+* PARAMETERS
+*      p_ntc
+*              [in] Pointer to the notice MAD attribute
+*
+*  vend_id
+*     [in] The producer Type code
+*
+* RETURN VALUES
+*      None
+*
+* SEE ALSO
+*      ib_mad_notice_attr_t
+*********/
+
+#include <complib/cl_packon.h>
+typedef struct _ib_inform_info
+{
+  ib_gid_t                                gid;
+  ib_net16_t                           lid_range_begin;
+  ib_net16_t                           lid_range_end;
+  ib_net16_t                           reserved1;
+  uint8_t                                      is_generic;
+  uint8_t                                      subscribe;
+  ib_net16_t                           trap_type;
+  union _inform_g_or_v
+  {
+        struct _inform_generic
+        {
+               ib_net16_t              trap_num;
+               ib_net32_t              qpn_resp_time_val;
+      uint8_t        reserved2;
+               uint8_t                 node_type_msb;
+               ib_net16_t              node_type_lsb;
+        } PACK_SUFFIX generic;
+        
+        struct _inform_vend
+        {
+               ib_net16_t              dev_id;
+               ib_net32_t              qpn_resp_time_val;
+      uint8_t        reserved2;
+               uint8_t                 vendor_id_msb;
+               ib_net16_t              vendor_id_lsb;
+        } PACK_SUFFIX vend;
+        
+  }    PACK_SUFFIX g_or_v;
+  
+}      PACK_SUFFIX ib_inform_info_t;
+#include <complib/cl_packoff.h>
+
+/****f* IBA Base: Types/ib_inform_info_get_qpn_resp_time
+* NAME
+*      ib_inform_info_get_qpn_resp_time
+*
+* DESCRIPTION
+*      Get QPN of the inform info
+*
+* SYNOPSIS
+*/
+OSM_INLINE void     AL_API
+ib_inform_info_get_qpn_resp_time(
+  IN              const        ib_net32_t                      qpn_resp_time_val,
+  OUT                  ib_net32_t* const                       p_qpn,
+  OUT                  uint8_t* const                          p_resp_time_val )
+{
+  uint32_t tmp = cl_ntoh32(qpn_resp_time_val);
+
+  if (p_qpn)
+    *p_qpn = cl_hton32((tmp & 0xffffff00) >> 8);
+       
+       if (p_resp_time_val)
+               *p_resp_time_val = (uint8_t)(tmp & 0x0000001f);
+}
+/*
+* PARAMETERS
+*      qpn_resp_time_val
+*              [in] the  qpn and resp time val from the mad
+*
+* RETURN VALUES
+*      p_qpn
+*              [out] pointer to the qpn
+*
+*      p_state
+*              [out] pointer to the resp time val
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_inform_info_t
+*********/
+
+/****f* IBA Base: Types/ib_inform_info_set_qpn
+* NAME
+*      ib_inform_info_set_qpn
+*
+* DESCRIPTION
+*      Set the QPN of the inform info
+*
+* SYNOPSIS
+*/
+OSM_INLINE void     AL_API
+ib_inform_info_set_qpn(
+  IN   ib_inform_info_t        *p_ii,
+  IN   ib_net32_t const        qpn)
+{
+  uint32_t tmp = cl_ntoh32(p_ii->g_or_v.generic.qpn_resp_time_val);
+  p_ii->g_or_v.generic.qpn_resp_time_val = 
+    cl_hton32(
+      (tmp & 0x000000ff) |
+      ((cl_ntoh32(qpn) << 8) & 0xffffff00)
+      );
+}
+/*
+* PARAMETERS
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_inform_info_t
+*********/
+
+/****f* IBA Base: Types/ib_inform_info_get_node_type
+* NAME
+*      ib_inform_info_get_node_type
+*
+* DESCRIPTION
+*      Get Node Type of the Inform Info
+*
+* SYNOPSIS
+*/
+OSM_INLINE ib_net32_t     AL_API
+ib_inform_info_get_node_type(
+  IN              const        ib_inform_info_t  *p_inf)
+{
+  uint32_t nt;
+  nt = cl_ntoh16(p_inf->g_or_v.generic.node_type_lsb) |
+    (p_inf->g_or_v.generic.node_type_msb << 16);
+  return cl_hton32(nt);
+}
+/*
+* PARAMETERS
+*      p_inf
+*              [in] pointer to an inform info
+*
+* RETURN VALUES
+*     The node type
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_inform_info_t
+*********/
+
+/****f* IBA Base: Types/ib_inform_info_get_vend_id
+* NAME
+*      ib_inform_info_get_vend_id
+*
+* DESCRIPTION
+*      Get Node Type of the Inform Info
+*
+* SYNOPSIS
+*/
+OSM_INLINE ib_net32_t     AL_API
+ib_inform_info_get_vend_id(
+  IN   const   ib_inform_info_t  *p_inf)
+{
+  uint32_t vi;
+  vi = cl_ntoh16(p_inf->g_or_v.vend.vendor_id_lsb) |
+    (p_inf->g_or_v.vend.vendor_id_msb << 16);
+  return cl_hton32(vi);
+}
+/*
+* PARAMETERS
+*      p_inf
+*              [in] pointer to an inform info
+*
+* RETURN VALUES
+*     The node type
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_inform_info_t
+*********/
+
+/****s* IBA Base: Types/ib_inform_info_record_t
+* NAME
+*      ib_inform_info_record_t
+*
+* DESCRIPTION
+*      IBA defined InformInfo Record. (15.2.5.12)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_inform_info_record
+{
+       ib_gid_t                                subscriber_gid;
+       ib_net16_t                      subscriber_enum;
+       uint8_t                                 reserved[6];
+       ib_inform_info_t        inform_info;
+
+}      PACK_SUFFIX ib_inform_info_record_t;
+#include <complib/cl_packoff.h>
+
+/****d* IBA Base: Types/DM_SVC_NAME
+* NAME
+*      DM_SVC_NAME
+*
+* DESCRIPTION
+*      IBA defined Device Management service name (16.3)
+*
+* SYNOPSIS
+*/
+#define        DM_SVC_NAME                             "DeviceManager.IBTA"
+/*
+* SEE ALSO
+*********/
+
+/****s* IBA Base: Types/ib_dm_mad_t
+* NAME
+*      ib_dm_mad_t
+*
+* DESCRIPTION
+*      IBA defined Device Management MAD (16.3.1)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_dm_mad
+{
+       ib_mad_t                header;
+       uint8_t                 resv[40];
+
+#define        IB_DM_DATA_SIZE                 192
+       uint8_t                 data[IB_DM_DATA_SIZE];
+
+}      PACK_SUFFIX ib_dm_mad_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*      header
+*              Common MAD header.
+*
+*      resv
+*              Reserved.
+*
+*      data
+*              Device Management payload.  The structure and content of this field
+*              depend upon the method, attr_id, and attr_mod fields in the header.
+*
+* SEE ALSO
+* ib_mad_t
+*********/
+
+/****s* IBA Base: Types/ib_iou_info_t
+* NAME
+*      ib_iou_info_t
+*
+* DESCRIPTION
+*      IBA defined IO Unit information structure (16.3.3.3)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_iou_info
+{
+       ib_net16_t              change_id;
+       uint8_t                 max_controllers;
+       uint8_t                 diag_rom;
+
+#define        IB_DM_CTRL_LIST_SIZE    128
+
+       uint8_t                 controller_list[IB_DM_CTRL_LIST_SIZE];
+#define        IOC_NOT_INSTALLED               0x0
+#define        IOC_INSTALLED                   0x1
+//             Reserved values                         0x02-0xE
+#define        SLOT_DOES_NOT_EXIST             0xF
+
+}      PACK_SUFFIX ib_iou_info_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*      change_id
+*              Value incremented, with rollover, by any change to the controller_list.
+*
+*      max_controllers
+*              Number of slots in controller_list.
+*
+*      diag_rom
+*              A byte containing two fields: DiagDeviceID and OptionROM.
+*              These fields may be read using the ib_iou_info_diag_dev_id
+*              and ib_iou_info_option_rom functions.
+*
+*      controller_list
+*              A series of 4-bit nibbles, with each nibble representing a slot
+*              in the IO Unit.  Individual nibbles may be read using the
+*              ioc_at_slot function.
+*
+* SEE ALSO
+* ib_dm_mad_t, ib_iou_info_diag_dev_id, ib_iou_info_option_rom, ioc_at_slot
+*********/
+
+/****f* IBA Base: Types/ib_iou_info_diag_dev_id
+* NAME
+*      ib_iou_info_diag_dev_id
+*
+* DESCRIPTION
+*      Returns the DiagDeviceID.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_iou_info_diag_dev_id(
+       IN              const   ib_iou_info_t* const            p_iou_info )
+{
+       return( (uint8_t)(p_iou_info->diag_rom >> 6 & 1) );
+}
+/*
+* PARAMETERS
+*      p_iou_info
+*              [in] Pointer to the IO Unit information structure.
+*
+* RETURN VALUES
+*      DiagDeviceID field of the IO Unit information.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_iou_info_t
+*********/
+
+/****f* IBA Base: Types/ib_iou_info_option_rom
+* NAME
+*      ib_iou_info_option_rom
+*
+* DESCRIPTION
+*      Returns the OptionROM.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ib_iou_info_option_rom(
+       IN              const   ib_iou_info_t*  const   p_iou_info )
+{
+       return( (uint8_t)(p_iou_info->diag_rom >> 7) );
+}
+/*
+* PARAMETERS
+*      p_iou_info
+*              [in] Pointer to the IO Unit information structure.
+*
+* RETURN VALUES
+*      OptionROM field of the IO Unit information.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_iou_info_t
+*********/
+
+/****f* IBA Base: Types/ioc_at_slot
+* NAME
+*      ioc_at_slot
+*
+* DESCRIPTION
+*      Returns the IOC value at the specified slot.
+*
+* SYNOPSIS
+*/
+AL_INLINE uint8_t     AL_API
+ioc_at_slot(
+       IN              const   ib_iou_info_t*  const   p_iou_info,
+       IN                              uint8_t                                 slot )
+{
+       if( slot >= IB_DM_CTRL_LIST_SIZE ) return SLOT_DOES_NOT_EXIST;
+       else return (int8_t)
+               ( (slot%2) ?
+                       ((p_iou_info->controller_list[slot/2] & 0xf0) >> 4 ):
+                       (p_iou_info->controller_list[slot/2] & 0x0f) );
+}
+/*
+* PARAMETERS
+*      p_iou_info
+*              [in] Pointer to the IO Unit information structure.
+*
+*      slot
+*              [in] Pointer to the IO Unit information structure.
+*
+* RETURN VALUES
+*      OptionROM field of the IO Unit information.
+*
+* NOTES
+*
+* SEE ALSO
+*      ib_iou_info_t
+*********/
+
+/****s* IBA Base: Types/ib_ioc_profile_t
+* NAME
+*      ib_ioc_profile_t
+*
+* DESCRIPTION
+*      IBA defined IO Controller profile structure (16.3.3.4)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_ioc_profile
+{
+       ib_net64_t                              ioc_guid;
+
+       ib_net32_t                              vend_id;
+
+       ib_net32_t                              dev_id;
+       ib_net16_t                              dev_ver;
+       ib_net16_t                              resv2;
+
+       ib_net32_t                              subsys_vend_id;
+       ib_net32_t                              subsys_id;
+
+       ib_net16_t                              io_class;
+       ib_net16_t                              io_subclass;
+       ib_net16_t                              protocol;
+       ib_net16_t                              protocol_ver;
+
+       ib_net32_t                              resv3;
+       ib_net16_t                              send_msg_depth;
+       uint8_t                                 resv4;
+       uint8_t                                 rdma_read_depth;
+       ib_net32_t                              send_msg_size;
+       ib_net32_t                              rdma_size;
+
+       uint8_t                                 ctrl_ops_cap;
+#define        CTRL_OPS_CAP_ST         0x01
+#define        CTRL_OPS_CAP_SF         0x02
+#define        CTRL_OPS_CAP_RT         0x04
+#define        CTRL_OPS_CAP_RF         0x08
+#define        CTRL_OPS_CAP_WT         0x10
+#define        CTRL_OPS_CAP_WF         0x20
+#define        CTRL_OPS_CAP_AT         0x40
+#define        CTRL_OPS_CAP_AF         0x80
+
+       uint8_t                                 resv5;
+
+       uint8_t                                 num_svc_entries;
+#define        MAX_NUM_SVC_ENTRIES     0xff
+
+       uint8_t                                 resv6[9];
+
+#define        CTRL_ID_STRING_LEN      64
+       char                                    id_string[CTRL_ID_STRING_LEN];
+
+}      PACK_SUFFIX ib_ioc_profile_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*      ioc_guid
+*              An EUI-64 GUID used to uniquely identify the IO controller.
+*
+*      vend_id
+*              IO controller vendor ID, IEEE format.
+*
+*      dev_id
+*              A number assigned by the vendor to identify the type of controller.
+*
+*      dev_ver
+*              A number assigned by the vendor to identify the divice version.
+*
+*      subsys_vend_id
+*              ID of the vendor of the enclosure, if any, in which the IO controller
+*              resides in IEEE format; otherwise zero.
+*
+*      subsys_id
+*              A number identifying the subsystem where the controller resides.
+*
+*      io_class
+*              0x0000 - 0xfffe = reserved for IO classes encompased by InfiniBand
+*              Architecture.  0xffff = Vendor specific.
+*
+*      io_subclass
+*              0x0000 - 0xfffe = reserved for IO subclasses encompased by InfiniBand
+*              Architecture.  0xffff = Vendor specific.  This shall be set to 0xfff
+*              if the io_class component is 0xffff.
+*
+*      protocol
+*              0x0000 - 0xfffe = reserved for IO subclasses encompased by InfiniBand
+*              Architecture.  0xffff = Vendor specific.  This shall be set to 0xfff
+*              if the io_class component is 0xffff.
+*
+*      protocol_ver
+*              Protocol specific.
+*
+*      send_msg_depth
+*              Maximum depth of the send message queue.
+*
+*      rdma_read_depth
+*              Maximum depth of the per-channel RDMA read queue.
+*
+*      send_msg_size
+*              Maximum size of send messages.
+*
+*      ctrl_ops_cap
+*              Supported operation types of this IO controller.  A bit set to one
+*              for affirmation of supported capability.
+*
+*      num_svc_entries
+*              Number of entries in the service entries table.
+*
+*      id_string
+*              UTF-8 encoded string for identifying the controller to an operator.
+*
+* SEE ALSO
+* ib_dm_mad_t
+*********/
+
+
+AL_INLINE uint32_t     AL_API
+ib_ioc_profile_get_vend_id(
+       IN              const   ib_ioc_profile_t* const         p_ioc_profile )
+{
+       return( cl_ntoh32(p_ioc_profile->vend_id) >> 8 );
+}
+
+
+AL_INLINE void     AL_API
+ib_ioc_profile_set_vend_id(
+       IN                              ib_ioc_profile_t* const         p_ioc_profile,
+       IN              const   uint32_t                                        vend_id )
+{
+       p_ioc_profile->vend_id = (cl_hton32(vend_id) << 8);
+}
+
+
+/****s* IBA Base: Types/ib_svc_entry_t
+* NAME
+*      ib_svc_entry_t
+*
+* DESCRIPTION
+*      IBA defined IO Controller service entry structure (16.3.3.5)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_svc_entry
+{
+#define        MAX_SVC_ENTRY_NAME_LEN          40
+       char                                    name[MAX_SVC_ENTRY_NAME_LEN];
+
+       ib_net64_t                              id;
+
+}      PACK_SUFFIX ib_svc_entry_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*      name
+*              UTF-8 encoded, null-terminated name of the service.
+*
+*      id
+*              An identifier of the associated Service.
+*
+* SEE ALSO
+* ib_svc_entries_t
+*********/
+
+
+/****s* IBA Base: Types/ib_svc_entries_t
+* NAME
+*      ib_svc_entries_t
+*
+* DESCRIPTION
+*      IBA defined IO Controller service entry array (16.3.3.5)
+*
+* SYNOPSIS
+*/
+#include <complib/cl_packon.h>
+typedef struct _ib_svc_entries
+{
+#define        SVC_ENTRY_COUNT                         4
+       ib_svc_entry_t                  service_entry[SVC_ENTRY_COUNT];
+
+}      PACK_SUFFIX ib_svc_entries_t;
+#include <complib/cl_packoff.h>
+/*
+* FIELDS
+*      service_entry
+*              An array of IO controller service entries.
+*
+* SEE ALSO
+* ib_dm_mad_t, ib_svc_entry_t
+*********/
+
+
+AL_INLINE void     AL_API
+ib_dm_get_slot_lo_hi(
+       IN              const   ib_net32_t                      slot_lo_hi,
+               OUT                     uint8_t         *const  p_slot,
+               OUT                     uint8_t         *const  p_lo,
+               OUT                     uint8_t         *const  p_hi )
+{
+       ib_net32_t              tmp_slot_lo_hi = CL_NTOH32( slot_lo_hi );
+
+       if( p_slot )
+               *p_slot = (uint8_t)( ( tmp_slot_lo_hi >> 16 ) & 0x0f );
+
+       if( p_hi )
+               *p_hi   = (uint8_t)( ( tmp_slot_lo_hi >> 8 ) & 0xff );
+
+       if( p_lo )
+               *p_lo   = (uint8_t)( ( tmp_slot_lo_hi >> 0 ) & 0xff );
+}
+
+
+/*
+ *     IBA defined information describing an I/O controller
+ */
+#include <complib/cl_packon.h>
+typedef struct _ib_ioc_info
+{
+       ib_net64_t                              module_guid;
+       ib_net64_t                              iou_guid;
+       ib_ioc_profile_t                ioc_profile;
+       ib_net64_t                              access_key;
+       uint16_t                                initiators_conf;
+       uint8_t                                 resv[38];
+
+}      PACK_SUFFIX ib_ioc_info_t;
+#include <complib/cl_packoff.h>
+
+/*
+ * Defines known Communication management class versions
+ */
+#define IB_MCLASS_CM_VER_2                                     2
+#define IB_MCLASS_CM_VER_1                                     1
+
+/*
+ *     Defines the size of user available data in communication management MADs
+ */
+#define IB_REQ_PDATA_SIZE_VER2                         92
+#define IB_MRA_PDATA_SIZE_VER2                         222
+#define IB_REJ_PDATA_SIZE_VER2                         148
+#define IB_REP_PDATA_SIZE_VER2                         196
+#define IB_RTU_PDATA_SIZE_VER2                         224
+#define IB_LAP_PDATA_SIZE_VER2                         168
+#define IB_APR_PDATA_SIZE_VER2                         148
+#define IB_DREQ_PDATA_SIZE_VER2                                220
+#define IB_DREP_PDATA_SIZE_VER2                                224
+#define IB_SIDR_REQ_PDATA_SIZE_VER2                    216
+#define IB_SIDR_REP_PDATA_SIZE_VER2                    136
+
+#define IB_REQ_PDATA_SIZE_VER1                         92
+#define IB_MRA_PDATA_SIZE_VER1                         222
+#define IB_REJ_PDATA_SIZE_VER1                         148
+#define IB_REP_PDATA_SIZE_VER1                         204
+#define IB_RTU_PDATA_SIZE_VER1                         224
+#define IB_LAP_PDATA_SIZE_VER1                         168
+#define IB_APR_PDATA_SIZE_VER1                         151
+#define IB_DREQ_PDATA_SIZE_VER1                                220
+#define IB_DREP_PDATA_SIZE_VER1                                224
+#define IB_SIDR_REQ_PDATA_SIZE_VER1                    216
+#define IB_SIDR_REP_PDATA_SIZE_VER1                    140
+
+#define IB_ARI_SIZE                                                    72              // redefine
+#define IB_APR_INFO_SIZE                                       72
+
+
+/****d* Access Layer/ib_rej_status_t
+* NAME
+*      ib_rej_status_t
+*
+* DESCRIPTION
+*      Rejection reasons.
+*
+* SYNOPSIS
+*/
+typedef        ib_net16_t                                                      ib_rej_status_t;
+/*
+* SEE ALSO
+*      ib_cm_rej, ib_cm_rej_rec_t
+*
+* SOURCE
+ */
+#define IB_REJ_INSUF_QP                                                CL_HTON16(1)
+#define IB_REJ_INSUF_EEC                                       CL_HTON16(2)
+#define IB_REJ_INSUF_RESOURCES                         CL_HTON16(3)
+#define IB_REJ_TIMEOUT                                         CL_HTON16(4)
+#define IB_REJ_UNSUPPORTED                                     CL_HTON16(5)
+#define IB_REJ_INVALID_COMM_ID                         CL_HTON16(6)
+#define IB_REJ_INVALID_COMM_INSTANCE           CL_HTON16(7)
+#define IB_REJ_INVALID_SID                                     CL_HTON16(8)
+#define IB_REJ_INVALID_XPORT                           CL_HTON16(9)
+#define IB_REJ_STALE_CONN                                      CL_HTON16(10)
+#define IB_REJ_RDC_NOT_EXIST                           CL_HTON16(11)
+#define IB_REJ_INVALID_GID                                     CL_HTON16(12)
+#define IB_REJ_INVALID_LID                                     CL_HTON16(13)
+#define IB_REJ_INVALID_SL                                      CL_HTON16(14)
+#define IB_REJ_INVALID_TRAFFIC_CLASS           CL_HTON16(15)
+#define IB_REJ_INVALID_HOP_LIMIT                       CL_HTON16(16)
+#define IB_REJ_INVALID_PKT_RATE                                CL_HTON16(17)
+#define IB_REJ_INVALID_ALT_GID                         CL_HTON16(18)
+#define IB_REJ_INVALID_ALT_LID                         CL_HTON16(19)
+#define IB_REJ_INVALID_ALT_SL                          CL_HTON16(20)
+#define IB_REJ_INVALID_ALT_TRAFFIC_CLASS       CL_HTON16(21)
+#define IB_REJ_INVALID_ALT_HOP_LIMIT           CL_HTON16(22)
+#define IB_REJ_INVALID_ALT_PKT_RATE                    CL_HTON16(23)
+#define IB_REJ_PORT_REDIRECT                           CL_HTON16(24)
+#define IB_REJ_INVALID_MTU                                     CL_HTON16(26)
+#define IB_REJ_INSUFFICIENT_RESP_RES           CL_HTON16(27)
+#define IB_REJ_USER_DEFINED                                    CL_HTON16(28)
+#define IB_REJ_INVALID_RNR_RETRY                       CL_HTON16(29)
+#define IB_REJ_DUPLICATE_LOCAL_COMM_ID         CL_HTON16(30)
+#define IB_REJ_INVALID_CLASS_VER                       CL_HTON16(31)
+#define IB_REJ_INVALID_FLOW_LBL                                CL_HTON16(32)
+#define IB_REJ_INVALID_ALT_FLOW_LBL                    CL_HTON16(33)
+
+#define IB_REJ_SERVICE_HANDOFF                         CL_HTON16(65535)
+/******/
+
+
+/****d* Access Layer/ib_apr_status_t
+* NAME
+*      ib_apr_status_t
+*
+* DESCRIPTION
+*      Automatic path migration status information.
+*
+* SYNOPSIS
+*/
+typedef uint8_t                                                                ib_apr_status_t;
+/*
+* SEE ALSO
+*      ib_cm_apr, ib_cm_apr_rec_t
+*
+* SOURCE
+ */
+#define IB_AP_SUCCESS                                          0
+#define IB_AP_INVALID_COMM_ID                          1
+#define IB_AP_UNSUPPORTED                                      2
+#define IB_AP_REJECT                                           3
+#define IB_AP_REDIRECT                                         4
+#define IB_AP_IS_CURRENT                                       5
+#define IB_AP_INVALID_QPN_EECN                         6
+#define IB_AP_INVALID_LID                                      7
+#define IB_AP_INVALID_GID                                      8
+#define IB_AP_INVALID_FLOW_LBL                         9
+#define IB_AP_INVALID_TCLASS                           10
+#define IB_AP_INVALID_HOP_LIMIT                                11
+#define IB_AP_INVALID_PKT_RATE                         12
+#define IB_AP_INVALID_SL                                       13
+/******/
+
+/****d* Access Layer/ib_cm_cap_mask_t
+* NAME
+*      ib_cm_cap_mask_t
+*
+* DESCRIPTION
+*      Capability mask values in ClassPortInfo.
+*
+* SYNOPSIS
+*/
+#define IB_CM_RELIABLE_CONN_CAPABLE                    CL_HTON16(9)
+#define IB_CM_RELIABLE_DGRM_CAPABLE                    CL_HTON16(10)
+#define IB_CM_RDGRM_CAPABLE                                    CL_HTON16(11)
+#define IB_CM_UNRELIABLE_CONN_CAPABLE          CL_HTON16(12)
+#define IB_CM_SIDR_CAPABLE                                     CL_HTON16(13)
+/*
+* SEE ALSO
+*      ib_cm_rep, ib_class_port_info_t
+*
+* SOURCE
+*
+*******/
+
+
+/*
+ *     Service ID resolution status
+ */
+typedef uint16_t                                                       ib_sidr_status_t;
+#define IB_SIDR_SUCCESS                                                0
+#define IB_SIDR_UNSUPPORTED                                    1
+#define IB_SIDR_REJECT                                         2
+#define IB_SIDR_NO_QP                                          3
+#define IB_SIDR_REDIRECT                                       4
+#define IB_SIDR_UNSUPPORTED_VER                                5
+
+
+/*
+ *     The following definitions are shared between the Access Layer and VPD
+ */
+
+
+typedef struct _ib_ca* __ptr64                 ib_ca_handle_t;
+typedef struct _ib_pd* __ptr64                 ib_pd_handle_t;
+typedef struct _ib_rdd* __ptr64                        ib_rdd_handle_t;
+typedef struct _ib_mr* __ptr64                 ib_mr_handle_t;
+typedef struct _ib_mw* __ptr64                 ib_mw_handle_t;
+typedef struct _ib_qp* __ptr64                 ib_qp_handle_t;
+typedef struct _ib_eec* __ptr64         ib_eec_handle_t;
+typedef struct _ib_cq* __ptr64                 ib_cq_handle_t;
+typedef struct _ib_av* __ptr64                 ib_av_handle_t;
+typedef struct _ib_mcast* __ptr64              ib_mcast_handle_t;
+
+/* Currently for windows branch we use the extended version of ib special verbs struct 
+       in order to be compliant with Infinicon ib_types , later we'll change it to support 
+       OpenSM ib_types.h */
+#ifndef WIN32
+
+/****d* Access Layer/ib_api_status_t
+* NAME
+*      ib_api_status_t
+*
+* DESCRIPTION
+*      Function return codes indicating the success or failure of an API call.
+*      Note that success is indicated by the return value IB_SUCCESS, which
+*      is always zero.
+*
+* NOTES
+*      IB_VERBS_PROCESSING_DONE is used by UVP library to terminate a verbs call
+*      in the pre-ioctl step itself.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_api_status_t
+{
+       IB_SUCCESS,
+       IB_INSUFFICIENT_RESOURCES,
+       IB_INSUFFICIENT_MEMORY,
+       IB_INVALID_PARAMETER,
+       IB_INVALID_SETTING,
+       IB_NOT_FOUND,
+       IB_TIMEOUT,
+       IB_CANCELED,
+       IB_INTERRUPTED,
+       IB_INVALID_PERMISSION,
+       IB_UNSUPPORTED,
+       IB_OVERFLOW,
+       IB_MAX_MCAST_QPS_REACHED,
+       IB_INVALID_QP_STATE,
+       IB_INVALID_EEC_STATE,
+       IB_INVALID_APM_STATE,
+       IB_INVALID_PORT_STATE,
+       IB_INVALID_STATE,
+       IB_RESOURCE_BUSY,
+       IB_INVALID_PKEY,
+       IB_INVALID_LKEY,
+       IB_INVALID_RKEY,
+       IB_INVALID_MAX_WRS,
+       IB_INVALID_MAX_SGE,
+       IB_INVALID_CQ_SIZE,
+       IB_INVALID_SERVICE_TYPE,
+       IB_INVALID_GID,
+       IB_INVALID_LID,
+       IB_INVALID_GUID,
+       IB_INVALID_CA_HANDLE,
+       IB_INVALID_AV_HANDLE,
+       IB_INVALID_CQ_HANDLE,
+       IB_INVALID_EEC_HANDLE,
+       IB_INVALID_QP_HANDLE,
+       IB_INVALID_PD_HANDLE,
+       IB_INVALID_MR_HANDLE,
+       IB_INVALID_MW_HANDLE,
+       IB_INVALID_RDD_HANDLE,
+       IB_INVALID_MCAST_HANDLE,
+       IB_INVALID_CALLBACK,
+       IB_INVALID_AL_HANDLE,                                   /* InfiniBand Access Layer */
+       IB_INVALID_HANDLE,                                              /* InfiniBand Access Layer */
+       IB_ERROR,                                                               /* InfiniBand Access Layer */
+       IB_REMOTE_ERROR,                                                /* Infiniband Access Layer */
+       IB_VERBS_PROCESSING_DONE,                               /* See Notes above                 */
+       IB_INVALID_WR_TYPE,
+       IB_QP_IN_TIMEWAIT,
+       IB_EE_IN_TIMEWAIT,
+       IB_INVALID_PORT,
+       IB_NOT_DONE,
+       IB_UNKNOWN_ERROR                                                /* ALWAYS LAST ENUM VALUE! */
+
+}      ib_api_status_t;
+/*****/
+
+AL_EXPORT const char* ib_error_str[];
+
+/****f* IBA Base: Types/ib_get_err_str
+* NAME
+*      ib_get_err_str
+*
+* DESCRIPTION
+*      Returns a string for the specified status value.
+*
+* SYNOPSIS
+*/
+AL_INLINE const char*    AL_API
+ib_get_err_str(
+       IN                              ib_api_status_t                         status )
+{
+       if( status > IB_UNKNOWN_ERROR )
+               status = IB_UNKNOWN_ERROR;
+       return( ib_error_str[status] );
+}
+/*
+* PARAMETERS
+*      status
+*              [in] status value
+*
+* RETURN VALUES
+*      Pointer to the status description string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+/****d* Verbs/ib_async_event_t
+* NAME
+*      ib_async_event_t -- Async event types
+*
+* DESCRIPTION
+*      This type indicates the reason the async callback was called.
+*      The context in the ib_event_rec_t indicates the resource context
+*      that associated with the callback.  For example, for IB_AE_CQ_ERROR
+*      the context provided during the ib_create_cq is returned in the event.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_async_event_t
+{
+       IB_AE_SQ_ERROR = 1,
+       IB_AE_SQ_DRAINED,
+       IB_AE_RQ_ERROR,
+       IB_AE_CQ_ERROR,
+       IB_AE_QP_FATAL,
+       IB_AE_QP_COMM,
+       IB_AE_QP_APM,
+       IB_AE_EEC_FATAL,
+       IB_AE_EEC_COMM,
+       IB_AE_EEC_APM,
+       IB_AE_LOCAL_FATAL,
+       IB_AE_PKEY_TRAP,
+       IB_AE_QKEY_TRAP,
+       IB_AE_MKEY_TRAP,
+       IB_AE_PORT_TRAP,
+       IB_AE_SYSIMG_GUID_TRAP,
+       IB_AE_BUF_OVERRUN,
+       IB_AE_LINK_INTEGRITY,
+       IB_AE_FLOW_CTRL_ERROR,
+       IB_AE_BKEY_TRAP,
+       IB_AE_QP_APM_ERROR,
+       IB_AE_EEC_APM_ERROR,
+       IB_AE_WQ_REQ_ERROR,
+       IB_AE_WQ_ACCESS_ERROR,
+       IB_AE_PORT_ACTIVE,
+       IB_AE_PORT_DOWN,
+       IB_AE_UNKNOWN           /* ALWAYS LAST ENUM VALUE */
+
+}      ib_async_event_t;
+/*
+* VALUES
+*      IB_AE_SQ_ERROR
+*              An error occurred when accessing the send queue of the QP or EEC.
+*              This event is optional.
+*
+*      IB_AE_SQ_DRAINED
+*              The send queue of the specified QP has completed the outstanding
+*              messages in progress when the state change was requested and, if
+*              applicable, has received all acknowledgements for those messages.
+*
+*      IB_AE_RQ_ERROR
+*              An error occurred when accessing the receive queue of the QP or EEC.
+*              This event is optional.
+*
+*      IB_AE_CQ_ERROR
+*              An error occurred when writing an entry to the CQ.
+*
+*      IB_AE_QP_FATAL
+*              A catastrophic error occurred while accessing or processing the
+*              work queue that prevents reporting of completions.
+*
+*      IB_AE_QP_COMM
+*              The first packet has arrived for the receive work queue where the
+*              QP is still in the RTR state.
+*
+*      IB_AE_QP_APM
+*              If alternate path migration is supported, this event indicates that
+*              the QP connection has migrated to the alternate path.
+*
+*      IB_AE_EEC_FATAL
+*              If reliable datagram service is supported, this event indicates that
+*              a catastrophic error occurred while accessing or processing the EEC
+*              that prevents reporting of completions.
+*
+*      IB_AE_EEC_COMM
+*              If reliable datagram service is supported, this event indicates that
+*              the first packet has arrived for the receive work queue where the
+*              EEC is still in the RTR state.
+*
+*      IB_AE_EEC_APM
+*              If reliable datagram service and alternate path migration is supported,
+*              this event indicates that the EEC connection has migrated to the
+*              alternate path.
+*
+*      IB_AE_LOCAL_FATAL
+*              A catastrophic HCA error occurred which cannot be attributed to any
+*              resource; behavior is indeterminate.
+*
+*      IB_AE_PKEY_TRAP
+*              A PKEY violation was detected.  This event is optional.
+*
+*      IB_AE_QKEY_TRAP
+*              A QKEY violation was detected.  This event is optional.
+*
+*      IB_AE_MKEY_TRAP
+*              An MKEY violation was detected.  This event is optional.
+*
+*      IB_AE_PORT_TRAP
+*              A port capability change was detected.  This event is optional.
+*
+*      IB_AE_SYSIMG_GUID_TRAP
+*              If the system image GUID is supported, this event indicates that the
+*              system image GUID of this HCA has been changed.  This event is
+*              optional.
+*
+*      IB_AE_BUF_OVERRUN
+*              The number of consecutive flow control update periods with at least
+*              one overrun error in each period has exceeded the threshold specified
+*              in the port info attributes.  This event is optional.
+*
+*      IB_AE_LINK_INTEGRITY
+*              The detection of excessively frequent local physical errors has
+*              exceeded the threshold specified in the port info attributes.  This
+*              event is optional.
+*
+*      IB_AE_FLOW_CTRL_ERROR
+*              An HCA watchdog timer monitoring the arrival of flow control updates
+*              has expired without receiving an update.  This event is optional.
+*
+*      IB_AE_BKEY_TRAP
+*              An BKEY violation was detected.  This event is optional.
+*
+*      IB_AE_QP_APM_ERROR
+*              If alternate path migration is supported, this event indicates that
+*              an incoming path migration request to this QP was not accepted.
+*
+*      IB_AE_EEC_APM_ERROR
+*              If reliable datagram service and alternate path migration is supported,
+*              this event indicates that an incoming path migration request to this
+*              EEC was not accepted.
+*
+*      IB_AE_WQ_REQ_ERROR
+*              An OpCode violation was detected at the responder.
+*
+*      IB_AE_WQ_ACCESS_ERROR
+*              An access violation was detected at the responder.
+*
+*      IB_AE_PORT_ACTIVE
+*              If the port active event is supported, this event is generated
+*              when the link becomes active: IB_LINK_ACTIVE.
+*
+*      IB_AE_PORT_DOWN
+*              The link is declared unavailable: IB_LINK_INIT, IB_LINK_ARMED,
+*              IB_LINK_DOWN.
+*
+*      IB_AE_UNKNOWN
+*              An unknown error occurred which cannot be attributed to any
+*              resource; behavior is indeterminate.
+*
+*****/
+
+AL_EXPORT const char* ib_async_event_str[];
+
+/****f* IBA Base: Types/ib_get_async_event_str
+* NAME
+*      ib_get_async_event_str
+*
+* DESCRIPTION
+*      Returns a string for the specified asynchronous event.
+*
+* SYNOPSIS
+*/
+AL_INLINE const char*    AL_API
+ib_get_async_event_str(
+       IN                              ib_async_event_t                        event )
+{
+       if( event > IB_AE_UNKNOWN )
+               event = IB_AE_UNKNOWN;
+       return( ib_async_event_str[event] );
+}
+/*
+* PARAMETERS
+*      event
+*              [in] event value
+*
+* RETURN VALUES
+*      Pointer to the asynchronous event description string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+/****s* Verbs/ib_event_rec_t
+* NAME
+*      ib_event_rec_t -- Async event notification record
+*
+* DESCRIPTION
+*      When an async event callback is made, this structure is passed to indicate
+*      the type of event, the source of event that caused it, and the context
+*      associated with this event.
+*
+*      context -- Context of the resource that caused the event.
+*              -- ca_context if this is a port/adapter event.
+*              -- qp_context if the source is a QP event
+*              -- cq_context if the source is a CQ event.
+*              -- ee_context if the source is an EE event.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_event_rec
+{
+       void                                    *context;
+       ib_async_event_t                type;
+
+       /* HCA vendor specific event information. */
+       uint64_t                                vendor_specific;
+
+       /* The following structures are valid only for trap types. */
+       union _trap
+       {
+               struct
+               {
+                       uint16_t                        lid;
+                       ib_net64_t                      port_guid;
+                       uint8_t                         port_num;
+
+                       /*
+                        * The following structure is valid only for
+                        * P_KEY, Q_KEY, and M_KEY violation traps.
+                        */
+                       struct
+                       {
+                               uint8_t                 sl;
+                               uint16_t                src_lid;
+                               uint16_t                dest_lid;
+                               union _key
+                               {
+                                       uint16_t        pkey;
+                                       uint32_t        qkey;
+                                       uint64_t        mkey;
+                               } key;
+                               uint32_t                src_qp;
+                               uint32_t                dest_qp;
+                               ib_gid_t                src_gid;
+                               ib_gid_t                dest_gid;
+
+                       }       violation;
+
+               } info;
+
+               ib_net64_t      sysimg_guid;
+
+       }       trap;
+
+}      ib_event_rec_t;
+/*******/
+
+
+/****d* Access Layer/ib_atomic_t
+* NAME
+*      ib_atomic_t
+*
+* DESCRIPTION
+*      Indicates atomicity levels supported by an adapter.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_atomic_t
+{
+       IB_ATOMIC_NONE,
+       IB_ATOMIC_LOCAL,
+       IB_ATOMIC_GLOBAL
+
+}      ib_atomic_t;
+/*
+* VALUES
+*      IB_ATOMIC_NONE
+*              Atomic operations not supported.
+*
+*      IB_ATOMIC_LOCAL
+*              Atomic operations guaranteed between QPs of a single CA.
+*
+*      IB_ATOMIC_GLOBAL
+*              Atomic operations are guaranteed between CA and any other entity
+*              in the system.
+*****/
+
+
+/****s* Access Layer/ib_port_cap_t
+* NAME
+*      ib_port_cap_t
+*
+* DESCRIPTION
+*      Indicates which management agents are currently available on the specified
+*      port.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_port_cap
+{
+       boolean_t               cm;
+       boolean_t               snmp;
+       boolean_t               dev_mgmt;
+       boolean_t               vend;
+       boolean_t               sm;
+       boolean_t               sm_disable;
+       boolean_t               qkey_ctr;
+       boolean_t               pkey_ctr;
+       boolean_t               notice;
+       boolean_t               trap;
+       boolean_t               apm;
+       boolean_t               slmap;
+       boolean_t               pkey_nvram;
+       boolean_t               mkey_nvram;
+       boolean_t               sysguid;
+       boolean_t               dr_notice;
+       boolean_t               boot_mgmt;
+       boolean_t               capm_notice;
+       boolean_t               reinit;
+       boolean_t               ledinfo;
+       boolean_t               port_active;
+
+}      ib_port_cap_t;
+/*****/
+
+
+/****d* Access Layer/ib_init_type_t
+* NAME
+*      ib_init_type_t
+*
+* DESCRIPTION
+*      If supported by the HCA, the type of initialization requested by
+*      this port before SM moves it to the active or armed state.  If the
+*      SM implements reinitialization, it shall set these bits to indicate
+*      the type of initialization performed prior to activating the port.
+*      Otherwise, these bits shall be set to 0.
+*
+* SYNOPSIS
+*/
+typedef uint8_t                                        ib_init_type_t;
+#define IB_INIT_TYPE_NO_LOAD                           0x01
+#define IB_INIT_TYPE_PRESERVE_CONTENT          0x02
+#define IB_INIT_TYPE_PRESERVE_PRESENCE         0x04
+#define IB_INIT_TYPE_DO_NOT_RESUSCITATE                0x08
+/*****/
+
+
+/****s* Access Layer/ib_port_attr_mod_t
+* NAME
+*      ib_port_attr_mod_t
+*
+* DESCRIPTION
+*      Port attributes that may be modified.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_port_attr_mod
+{
+       ib_port_cap_t                   cap;
+       uint16_t                                pkey_ctr;
+       uint16_t                                qkey_ctr;
+
+       ib_init_type_t                  init_type;
+       ib_net64_t                              system_image_guid;
+
+}      ib_port_attr_mod_t;
+/*
+* SEE ALSO
+*      ib_port_cap_t
+*****/
+
+
+/****s* Access Layer/ib_port_attr_t
+* NAME
+*      ib_port_attr_t
+*
+* DESCRIPTION
+*      Information about a port on a given channel adapter.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_port_attr
+{
+       ib_net64_t                              port_guid;
+       uint8_t                                 port_num;
+       uint8_t                                 mtu;
+       uint64_t                                max_msg_size;
+       ib_net16_t                              lid;
+       uint8_t                                 lmc;
+
+       /*
+        * LinkWidthSupported as defined in PortInfo.  Required to calculate
+        * inter-packet delay (a.k.a. static rate).
+        */
+       uint8_t                                 link_width_supported;
+
+       uint16_t                                max_vls;
+
+       ib_net16_t                              sm_lid;
+       uint8_t                                 sm_sl;
+       uint8_t                                 link_state;
+
+       ib_init_type_t                  init_type_reply;        /* Optional */
+
+       /*
+        * subnet_timeout:
+        * The maximum expected subnet propagation delay to reach any port on
+        * the subnet.  This value also determines the rate at which traps can
+        * be generated from this node.
+        *
+        * timeout = 4.096 microseconds * 2^subnet_timeout
+        */
+       uint8_t                                 subnet_timeout;
+
+       ib_port_cap_t                   cap;
+       uint16_t                                pkey_ctr;
+       uint16_t                                qkey_ctr;
+
+       uint16_t                                num_gids;
+       uint16_t                                num_pkeys;
+       /*
+        * Pointers at the end of the structure to allow doing a simple
+        * memory comparison of contents up to the first pointer.
+        */
+       ib_gid_t                                *p_gid_table;
+       ib_net16_t                              *p_pkey_table;
+
+}      ib_port_attr_t;
+/*
+* SEE ALSO
+*      uint8_t, ib_port_cap_t, ib_link_states_t
+*****/
+
+
+/****s* Access Layer/ib_ca_attr_t
+* NAME
+*      ib_ca_attr_t
+*
+* DESCRIPTION
+*      Information about a channel adapter.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_ca_attr
+{
+       ib_net64_t                              ca_guid;
+
+       uint32_t                                vend_id;
+       uint16_t                                dev_id;
+       uint16_t                                revision;
+
+       /*
+        * Total size of the ca attributes in bytes
+        */
+       uint32_t                                size;
+       uint32_t                                max_qps;
+       uint32_t                                max_wrs;
+
+       uint32_t                                max_sges;
+       uint32_t                                max_rd_sges;
+
+       uint32_t                                max_cqs;
+       uint32_t                                max_cqes;
+
+       uint32_t                                max_pds;
+
+       uint32_t                                init_regions;
+       uint64_t                                init_region_size;
+
+       uint32_t                                init_windows;
+       uint32_t                                max_addr_handles;
+
+       uint32_t                                max_partitions;
+
+       ib_atomic_t                             atomicity;
+
+       uint8_t                                 max_qp_resp_res;
+       uint8_t                                 max_eec_resp_res;
+       uint8_t                                 max_resp_res;
+
+       uint8_t                                 max_qp_init_depth;
+       uint8_t                                 max_eec_init_depth;
+
+       uint32_t                                max_eecs;
+       uint32_t                                max_rdds;
+
+       uint32_t                                max_ipv6_qps;
+       uint32_t                                max_ether_qps;
+
+       uint32_t                                max_mcast_grps;
+       uint32_t                                max_mcast_qps;
+       uint32_t                                max_qps_per_mcast_grp;
+
+       /*
+        * local_ack_delay:
+        * Specifies the maximum time interval between the local CA receiving
+        * a message and the transmission of the associated ACK or NAK.
+        *
+        * timeout = 4.096 microseconds * 2^local_ack_delay
+        */
+       uint8_t                                 local_ack_delay;
+
+       boolean_t                               bad_pkey_ctr_support;
+       boolean_t                               bad_qkey_ctr_support;
+       boolean_t                               raw_mcast_support;
+       boolean_t                               apm_support;
+       boolean_t                               av_port_check;
+       boolean_t                               change_primary_port;
+       boolean_t                               modify_wr_depth;
+       boolean_t                               current_qp_state_support;
+       boolean_t                               shutdown_port_capability;
+       boolean_t                               init_type_support;
+       boolean_t                               port_active_event_support;
+       boolean_t                               system_image_guid_support;
+       boolean_t                               hw_agents;
+
+       ib_net64_t                              system_image_guid;
+
+       uint32_t                                num_page_sizes;
+       uint8_t                                 num_ports;
+
+       uint32_t                                *p_page_size;
+       ib_port_attr_t                  *p_port_attr;
+
+}      ib_ca_attr_t;
+/*
+* FIELDS
+*      ca_guid
+*              GUID for this adapter.
+*
+*      vend_id
+*              IEEE vendor ID for this adapter
+*
+*      dev_id
+*              Device ID of this adapter. (typically from PCI device ID)
+*
+*      revision
+*              Revision ID of this adapter
+*
+*      size
+*              Total size in bytes for the HCA attributes.  This size includes total
+*              size required for all the variable members of the structure.  If a
+*              vendor requires to pass vendor specific fields beyond this structure,
+*              the HCA vendor can choose to report a larger size.  If a vendor is
+*              reporting extended vendor specific features, they should also provide
+*              appropriate access functions to aid with the required interpretation.
+*
+*      max_qps
+*              Maximum number of QP's supported by this HCA.
+*
+*      max_wrs
+*              Maximum number of work requests supported by this HCA.
+*
+*      max_sges
+*              Maximum number of scatter gather elements supported per work request.
+*
+*      max_rd_sges
+*              Maximum number of scatter gather elements supported for READ work
+*              requests for a Reliable Datagram QP.  This value must be zero if RD
+*              service is not supported.
+*
+*      max_cqs
+*              Maximum number of Completion Queues supported.
+*
+*      max_cqes
+*              Maximum number of CQ elements supported per CQ.
+*
+*      max_pds
+*              Maximum number of protection domains supported.
+*
+*      init_regions
+*              Initial number of memory regions supported.  These are only informative
+*              values.  HCA vendors can extended and grow these limits on demand.
+*
+*      init_region_size
+*              Initial limit on the size of the registered memory region.
+*
+*      init_windows
+*              Initial number of window entries supported.
+*
+*      max_addr_handles
+*              Maximum number of address handles supported.
+*
+*      max_partitions
+*              Maximum number of partitions supported.
+*
+*      atomicity
+*              Indicates level of atomic operations supported by this HCA.
+*
+*      max_qp_resp_res
+*      max_eec_resp_res
+*              Maximum limit on number of responder resources for incoming RDMA
+*              operations, on QPs and EEC's respectively.
+*
+*      max_resp_res
+*              Maximum number of responder resources per HCA, with this HCA used as
+*              the target.
+*
+*      max_qp_init_depth
+*      max_eec_init_depth
+*              Maximimum initiator depth per QP or EEC for initiating RDMA reads and
+*              atomic operations.
+*
+*      max_eecs
+*              Maximimum number of EEC's supported by the HCA.
+*
+*      max_rdds
+*              Maximum number of Reliable datagram domains supported.
+*
+*      max_ipv6_qps
+*      max_ether_qps
+*              Maximum number of IPV6 and raw ether QP's supported by this HCA.
+*
+*      max_mcast_grps
+*              Maximum number of multicast groups supported.
+*
+*      max_mcast_qps
+*              Maximum number of QP's that can support multicast operations.
+*
+*      max_qps_per_mcast_grp
+*              Maximum number of multicast QP's per multicast group.
+*
+*      local_ack_delay
+*              Specifies the maximum time interval between the local CA receiving
+*              a message and the transmission of the associated ACK or NAK.
+*              timeout = 4.096 microseconds * 2^local_ack_delay
+*
+*      bad_pkey_ctr_support
+*      bad_qkey_ctr_support
+*              Indicates support for the bad pkey and qkey counters.
+*
+*      raw_mcast_support
+*              Indicates support for raw packet multicast.
+*
+*      apm_support
+*              Indicates support for Automatic Path Migration.
+*
+*      av_port_check
+*              Indicates ability to check port number in address handles.
+*
+*      change_primary_port
+*              Indicates ability to change primary port for a QP or EEC during a
+*              SQD->RTS transition.
+*
+*      modify_wr_depth
+*              Indicates ability to modify QP depth during a modify QP operation.
+*              Check the verb specification for permitted states.
+*
+*      current_qp_state_support
+*              Indicates ability of the HCA to support the current QP state modifier
+*              during a modify QP operation.
+*
+*      shutdown_port_capability
+*              Shutdown port capability support indicator.
+*
+*      init_type_support
+*              Indicates init_type_reply and ability to set init_type is supported.
+*
+*      port_active_event_support
+*              Port active event support indicator.
+*
+*      system_image_guid_support
+*              System image GUID support indicator.
+*
+*      hw_agents
+*              Indicates SMA is implemented in HW.
+*
+*      system_image_guid
+*              Optional system image GUID.  This field is valid only if the
+*              system_image_guid_support flag is set.
+*
+*      num_page_sizes
+*              Indicates support for different page sizes supported by the HCA.
+*              The variable size array can be obtained from p_page_size.
+*
+*      num_ports
+*              Number of physical ports supported on this HCA.
+*
+*      p_page_size
+*              Array holding different page size supported.
+*
+*      p_port_attr
+*              Array holding port attributes.
+*
+* NOTES
+*      This structure contains the attributes of a channel adapter.  Users must
+*      call ib_copy_ca_attr to copy the contents of this structure to a new
+*      memory region.
+*
+* SEE ALSO
+*      ib_port_attr_t, ib_atomic_t, ib_copy_ca_attr
+*****/
+
+/****f* Access layer/ib_copy_ca_attr
+* NAME
+*      ib_copy_ca_attr
+*
+* DESCRIPTION
+*      Copies CA attributes.
+*
+* SYNOPSIS
+*/
+ib_ca_attr_t*
+ib_copy_ca_attr(
+       IN                              ib_ca_attr_t* const             p_dest,
+       IN              const   ib_ca_attr_t* const             p_src );
+/*
+* PARAMETERS
+*      p_dest
+*              Pointer to the buffer that is the destination of the copy.
+*
+*      p_src
+*              Pointer to the CA attributes to copy.
+*
+* RETURN VALUE
+*      Pointer to the copied CA attributes.
+*
+* NOTES
+*      The buffer pointed to by the p_dest parameter must be at least the size
+*      specified in the size field of the buffer pointed to by p_src.
+*
+* SEE ALSO
+*      ib_ca_attr_t, ib_dup_ca_attr, ib_free_ca_attr
+*****/
+
+
+/****s* Access Layer/ib_av_attr_t
+* NAME
+*      ib_av_attr_t
+*
+* DESCRIPTION
+*      IBA address vector.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_av_attr
+{
+       uint8_t                                 port_num;
+
+       uint8_t                                 sl;
+       ib_net16_t                              dlid;
+
+       boolean_t                               grh_valid;
+       ib_grh_t                                grh;
+       uint8_t                                 static_rate;
+       uint8_t                                 path_bits;
+
+       struct _av_conn
+       {
+               uint8_t                         path_mtu;
+               uint8_t                         local_ack_timeout;
+               uint8_t                         seq_err_retry_cnt;
+               uint8_t                         rnr_retry_cnt;
+
+       }       conn;
+
+}      ib_av_attr_t;
+/*
+* SEE ALSO
+*      ib_gid_t
+*****/
+
+
+/****d* Access Layer/ib_qp_type_t
+* NAME
+*      ib_qp_type_t
+*
+* DESCRIPTION
+*      Indicates the type of queue pair being created.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_qp_type
+{
+       IB_QPT_RELIABLE_CONN    = 0,            /* Matches CM REQ transport type */
+       IB_QPT_UNRELIABLE_CONN  = 1,            /* Matches CM REQ transport type */
+       IB_QPT_RELIABLE_DGRM    = 2,            /* Matches CM REQ transport type */
+       IB_QPT_UNRELIABLE_DGRM,
+       IB_QPT_QP0,
+       IB_QPT_QP1,
+       IB_QPT_RAW_IPV6,
+       IB_QPT_RAW_ETHER,
+       IB_QPT_MAD,                                                             /* InfiniBand Access Layer */
+       IB_QPT_QP0_ALIAS,                                               /* InfiniBand Access Layer */
+       IB_QPT_QP1_ALIAS                                                /* InfiniBand Access Layer */
+
+}      ib_qp_type_t;
+/*
+* VALUES
+*      IB_QPT_RELIABLE_CONN
+*              Reliable, connected queue pair.
+*
+*      IB_QPT_UNRELIABLE_CONN
+*              Unreliable, connected queue pair.
+*
+*      IB_QPT_RELIABLE_DGRM
+*              Reliable, datagram queue pair.
+*
+*      IB_QPT_UNRELIABLE_DGRM
+*              Unreliable, datagram queue pair.
+*
+*      IB_QPT_QP0
+*              Queue pair 0.
+*
+*      IB_QPT_QP1
+*              Queue pair 1.
+*
+*      IB_QPT_RAW_DGRM
+*              Raw datagram queue pair.
+*
+*      IB_QPT_RAW_IPV6
+*              Raw IP version 6 queue pair.
+*
+*      IB_QPT_RAW_ETHER
+*              Raw Ethernet queue pair.
+*
+*      IB_QPT_MAD
+*              Unreliable, datagram queue pair that will send and receive management
+*              datagrams with assistance from the access layer.
+*
+*      IB_QPT_QP0_ALIAS
+*              Alias to queue pair 0.  Aliased QPs can only be created on an aliased
+*              protection domain.
+*
+*      IB_QPT_QP1_ALIAS
+*              Alias to queue pair 1.  Aliased QPs can only be created on an aliased
+*              protection domain.
+*****/
+
+
+/****d* Access Layer/ib_access_t
+* NAME
+*      ib_access_t
+*
+* DESCRIPTION
+*      Indicates the type of access is permitted on resources such as QPs,
+*      memory regions and memory windows.
+*
+* SYNOPSIS
+*/
+typedef uint32_t                               ib_access_t;
+#define IB_AC_RDMA_READ                        0x00000001
+#define IB_AC_RDMA_WRITE               0x00000002
+#define IB_AC_ATOMIC                   0x00000004
+#define IB_AC_LOCAL_WRITE              0x00000008
+#define IB_AC_MW_BIND                  0x00000010
+/*
+* NOTES
+*      Users may combine access rights using a bit-wise or operation to specify
+*      additional access.  For example: IB_AC_RDMA_READ | IB_AC_RDMA_WRITE grants
+*      RDMA read and write access.
+*****/
+
+
+/****d* Access Layer/ib_qp_state_t
+* NAME
+*      ib_qp_state_t
+*
+* DESCRIPTION
+*      Indicates or sets the state of a queue pair.  The current state of a queue
+*      pair is returned through the ib_qp_query call and set via the
+*      ib_qp_modify call.
+*
+* SYNOPSIS
+*/
+typedef uint32_t                               ib_qp_state_t;
+#define IB_QPS_RESET                   0x00000001
+#define IB_QPS_INIT                            0x00000002
+#define IB_QPS_RTR                             0x00000004
+#define IB_QPS_RTS                             0x00000008
+#define IB_QPS_SQD                             0x00000010
+#define IB_QPS_SQD_DRAINING            0x00000030
+#define IB_QPS_SQD_DRAINED             0x00000050
+#define IB_QPS_SQERR                   0x00000080
+#define IB_QPS_ERROR                   0x00000100
+#define IB_QPS_TIME_WAIT               0xDEAD0000      /* InfiniBand Access Layer */
+/*****/
+
+
+/****d* Access Layer/ib_apm_state_t
+* NAME
+*      ib_apm_state_t
+*
+* DESCRIPTION
+*      The current automatic path migration state of a queue pair
+*
+* SYNOPSIS
+*/
+typedef enum _ib_apm_state
+{
+       IB_APM_MIGRATED = 1,
+       IB_APM_REARM,
+       IB_APM_ARMED
+
+}      ib_apm_state_t;
+/*****/
+
+
+/****s* Access Layer/ib_qp_create_t
+* NAME
+*      ib_qp_create_t
+*
+* DESCRIPTION
+*      Attributes used to initialize a queue pair at creation time.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_qp_create
+{
+       ib_qp_type_t                    qp_type;
+
+       ib_rdd_handle_t                 h_rdd;
+
+       uint32_t                                sq_depth;
+       uint32_t                                rq_depth;
+       uint32_t                                sq_sge;
+       uint32_t                                rq_sge;
+
+       ib_cq_handle_t                  h_sq_cq;
+       ib_cq_handle_t                  h_rq_cq;
+
+       boolean_t                               sq_signaled;
+
+}      ib_qp_create_t;
+/*
+* FIELDS
+*      type
+*              Specifies the type of queue pair to create.
+*
+*      h_rdd
+*              A handle to a reliable datagram domain to associate with the queue
+*              pair.  This field is ignored if the queue pair is not a reliable
+*              datagram type queue pair.
+*
+*      sq_depth
+*              Indicates the requested maximum number of work requests that may be
+*              outstanding on the queue pair's send queue.  This value must be less
+*              than or equal to the maximum reported by the channel adapter associated
+*              with the queue pair.
+*
+*      rq_depth
+*              Indicates the requested maximum number of work requests that may be
+*              outstanding on the queue pair's receive queue.  This value must be less
+*              than or equal to the maximum reported by the channel adapter associated
+*              with the queue pair.
+*
+*      sq_sge
+*              Indicates the maximum number scatter-gather elements that may be
+*              given in a send work request.  This value must be less
+*              than or equal to the maximum reported by the channel adapter associated
+*              with the queue pair.
+*
+*      rq_sge
+*              Indicates the maximum number scatter-gather elements that may be
+*              given in a receive work request.  This value must be less
+*              than or equal to the maximum reported by the channel adapter associated
+*              with the queue pair.
+*
+*      h_sq_cq
+*              A handle to the completion queue that will be used to report send work
+*              request completions.  This handle must be NULL if the type is
+*              IB_QPT_MAD, IB_QPT_QP0_ALIAS, or IB_QPT_QP1_ALIAS.
+*
+*      h_rq_cq
+*              A handle to the completion queue that will be used to report receive
+*              work request completions.  This handle must be NULL if the type is
+*              IB_QPT_MAD, IB_QPT_QP0_ALIAS, or IB_QPT_QP1_ALIAS.
+*
+*      sq_signaled
+*              A flag that is used to indicate whether the queue pair will signal
+*              an event upon completion of a send work request.  If set to
+*              TRUE, send work requests will always generate a completion
+*              event.  If set to FALSE, a completion event will only be
+*              generated if the send_opt field of the send work request has the
+*              IB_SEND_OPT_SIGNALED flag set.
+*
+* SEE ALSO
+*      ib_qp_type_t, ib_qp_attr_t
+*****/
+
+
+/****s* Access Layer/ib_qp_attr_t
+* NAME
+*      ib_qp_attr_t
+*
+* DESCRIPTION
+*      Queue pair attributes returned through ib_query_qp.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_qp_attr
+{
+       ib_pd_handle_t                  h_pd;
+       ib_qp_type_t                    qp_type;
+       ib_access_t                             access_ctrl;
+       uint16_t                                pkey_index;
+
+       uint32_t                                sq_depth;
+       uint32_t                                rq_depth;
+       uint32_t                                sq_sge;
+       uint32_t                                rq_sge;
+       uint8_t                                 init_depth;
+       uint8_t                                 resp_res;
+
+       ib_cq_handle_t                  h_sq_cq;
+       ib_cq_handle_t                  h_rq_cq;
+       ib_rdd_handle_t                 h_rdd;
+
+       boolean_t                               sq_signaled;
+
+       ib_qp_state_t                   state;
+       ib_net32_t                              num;
+       ib_net32_t                              dest_num;
+       ib_net32_t                              qkey;
+
+       ib_net32_t                              sq_psn;
+       ib_net32_t                              rq_psn;
+
+       uint8_t                                 primary_port;
+       uint8_t                                 alternate_port;
+       ib_av_attr_t                    primary_av;
+       ib_av_attr_t                    alternate_av;
+       ib_apm_state_t                  apm_state;
+
+}      ib_qp_attr_t;
+/*
+* FIELDS
+*      h_pd
+*              This is a handle to a protection domain associated with the queue
+*              pair, or NULL if the queue pair is type IB_QPT_RELIABLE_DGRM.
+*
+* NOTES
+*      Other fields are defined by the Infiniband specification.
+*
+* SEE ALSO
+*      ib_qp_type_t, ib_access_t, ib_qp_state_t, ib_av_attr_t, ib_apm_state_t
+*****/
+
+
+/****d* Access Layer/ib_qp_opts_t
+* NAME
+*      ib_qp_opts_t
+*
+* DESCRIPTION
+*      Optional fields supplied in the modify QP operation.
+*
+* SYNOPSIS
+*/
+typedef uint32_t                               ib_qp_opts_t;
+#define IB_MOD_QP_ALTERNATE_AV         0x00000001
+#define IB_MOD_QP_PKEY                         0x00000002
+#define IB_MOD_QP_APM_STATE                    0x00000004
+#define IB_MOD_QP_PRIMARY_AV           0x00000008
+#define IB_MOD_QP_RNR_NAK_TIMEOUT      0x00000010
+#define IB_MOD_QP_RESP_RES                     0x00000020
+#define IB_MOD_QP_INIT_DEPTH           0x00000040
+#define IB_MOD_QP_PRIMARY_PORT         0x00000080
+#define IB_MOD_QP_ACCESS_CTRL          0x00000100
+#define IB_MOD_QP_QKEY                         0x00000200
+#define IB_MOD_QP_SQ_DEPTH                     0x00000400
+#define IB_MOD_QP_RQ_DEPTH                     0x00000800
+#define IB_MOD_QP_CURRENT_STATE                0x00001000
+#define IB_MOD_QP_RETRY_CNT                    0x00002000
+#define IB_MOD_QP_LOCAL_ACK_TIMEOUT    0x00004000
+#define IB_MOD_QP_RNR_RETRY_CNT                0x00008000
+
+/*
+* SEE ALSO
+*      ib_qp_mod_t
+*****/
+
+
+/****s* Access Layer/ib_qp_mod_t
+* NAME
+*      ib_qp_mod_t
+*
+* DESCRIPTION
+*      Information needed to change the state of a queue pair through the
+*      ib_modify_qp call.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_qp_mod
+{
+       ib_qp_state_t                           req_state;
+
+       union _qp_state
+       {
+               struct _qp_reset
+               {
+                       /*
+                        * Time, in milliseconds, that the QP needs to spend in the
+                        * time wait state before being reused.
+                        */
+                       uint32_t                        timewait;
+
+               }       reset;
+
+               struct _qp_init
+               {
+                       ib_qp_opts_t            opts;
+                       uint8_t                         primary_port;
+                       ib_net32_t                      qkey;
+                       uint16_t                        pkey_index;
+                       ib_access_t                     access_ctrl;
+
+               }       init;
+
+               struct _qp_rtr
+               {
+                       ib_net32_t                      rq_psn;
+                       ib_net32_t                      dest_qp;
+                       ib_av_attr_t            primary_av;
+                       uint8_t                         resp_res;
+
+                       ib_qp_opts_t            opts;
+                       ib_av_attr_t            alternate_av;
+                       ib_net32_t                      qkey;
+                       uint16_t                        pkey_index;
+                       ib_access_t                     access_ctrl;
+                       uint32_t                        sq_depth;
+                       uint32_t                        rq_depth;
+                       uint8_t                         rnr_nak_timeout;
+
+               }       rtr;
+
+               struct _qp_rts
+               {
+                       ib_net32_t                      sq_psn;
+                       uint8_t                         retry_cnt;
+                       uint8_t                         rnr_retry_cnt;
+                       uint8_t                         rnr_nak_timeout;
+                       uint8_t                         local_ack_timeout;
+                       uint8_t                         init_depth;
+
+                       ib_qp_opts_t            opts;
+                       ib_qp_state_t           current_state;
+                       ib_net32_t                      qkey;
+                       ib_access_t                     access_ctrl;
+                       uint8_t                         resp_res;
+
+                       ib_av_attr_t            primary_av;
+                       ib_av_attr_t            alternate_av;
+
+                       uint32_t                        sq_depth;
+                       uint32_t                        rq_depth;
+
+                       ib_apm_state_t          apm_state;
+                       uint8_t                         primary_port;
+                       uint16_t                        pkey_index;
+
+               }       rts;
+
+               struct _qp_sqd
+               {
+                       boolean_t                       sqd_event;
+
+               }       sqd;
+
+       }       state;
+
+}      ib_qp_mod_t;
+/*
+* SEE ALSO
+*      ib_qp_state_t, ib_access_t, ib_av_attr_t, ib_apm_state_t
+*****/
+
+
+/****s* Access Layer/ib_eec_attr_t
+* NAME
+*      ib_eec_attr_t
+*
+* DESCRIPTION
+*      Information about an end-to-end context.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_eec_attr
+{
+       ib_qp_state_t                   state;
+       ib_rdd_handle_t                 h_rdd;
+       ib_net32_t                              local_eecn;
+
+       ib_net32_t                              sq_psn;
+       ib_net32_t                              rq_psn;
+       uint8_t                                 primary_port;
+       uint16_t                                pkey_index;
+       uint32_t                                resp_res;
+       ib_net32_t                              remote_eecn;
+       uint32_t                                init_depth;
+       uint32_t                                dest_num;       // ??? What is this?
+       ib_av_attr_t                    primary_av;
+       ib_av_attr_t                    alternate_av;
+       ib_apm_state_t                  apm_state;
+
+}      ib_eec_attr_t;
+/*
+* SEE ALSO
+*      ib_qp_state_t, ib_av_attr_t, ib_apm_state_t
+*****/
+
+
+/****d* Access Layer/ib_eec_opts_t
+* NAME
+*      ib_eec_opts_t
+*
+* DESCRIPTION
+*      Optional fields supplied in the modify EEC operation.
+*
+* SYNOPSIS
+*/
+typedef uint32_t                               ib_eec_opts_t;
+#define IB_MOD_EEC_ALTERNATE_AV        0x00000001
+#define IB_MOD_EEC_PKEY                        0x00000002
+#define IB_MOD_EEC_APM_STATE   0x00000004
+#define IB_MOD_EEC_PRIMARY_AV  0x00000008
+#define IB_MOD_EEC_RNR                 0x00000010
+#define IB_MOD_EEC_RESP_RES            0x00000020
+#define IB_MOD_EEC_OUTSTANDING 0x00000040
+#define IB_MOD_EEC_PRIMARY_PORT        0x00000080
+/*
+* NOTES
+*
+*
+*****/
+
+/****s* Access Layer/ib_eec_mod_t
+* NAME
+*      ib_eec_mod_t
+*
+* DESCRIPTION
+*      Information needed to change the state of an end-to-end context through
+*      the ib_modify_eec function.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_eec_mod
+{
+       ib_qp_state_t                           req_state;
+
+       union _eec_state
+       {
+               struct _eec_init
+               {
+                       uint8_t                         primary_port;
+                       uint16_t                        pkey_index;
+
+               }       init;
+
+               struct _eec_rtr
+               {
+                       ib_net32_t                      rq_psn;
+                       ib_net32_t                      remote_eecn;
+                       ib_av_attr_t            primary_av;
+                       uint8_t                         resp_res;
+
+                       ib_eec_opts_t           opts;
+                       ib_av_attr_t            alternate_av;
+                       uint16_t                        pkey_index;
+
+               }       rtr;
+
+               struct _eec_rts
+               {
+                       ib_net32_t                      sq_psn;
+                       uint8_t                         retry_cnt;
+                       uint8_t                         rnr_retry_cnt;
+                       uint8_t                         local_ack_timeout;
+                       uint8_t                         init_depth;
+
+                       ib_eec_opts_t           opts;
+                       ib_av_attr_t            alternate_av;
+                       ib_apm_state_t          apm_state;
+
+                       ib_av_attr_t            primary_av;
+                       uint16_t                        pkey_index;
+                       uint8_t                         primary_port;
+
+               }       rts;
+
+               struct _eec_sqd
+               {
+                       boolean_t                       sqd_event;
+
+               }       sqd;
+
+       }       state;
+
+}      ib_eec_mod_t;
+/*
+* SEE ALSO
+*      ib_qp_state_t, ib_av_attr_t, ib_apm_state_t
+*****/
+
+
+/****d* Access Layer/ib_wr_type_t
+* NAME
+*      ib_wr_type_t
+*
+* DESCRIPTION
+*      Identifies the type of work request posted to a queue pair.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_wr_type_t
+{
+       WR_SEND = 1,
+       WR_RDMA_WRITE,
+       WR_RDMA_READ,
+       WR_COMPARE_SWAP,
+       WR_FETCH_ADD
+
+}      ib_wr_type_t;
+/*****/
+
+
+/****s* Access Layer/ib_local_ds_t
+* NAME
+*      ib_local_ds_t
+*
+* DESCRIPTION
+*      Local data segment information referenced by send and receive work
+*      requests.  This is used to specify local data buffers used as part of a
+*      work request.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_local_ds
+{
+       void                                    *vaddr;
+       uint32_t                                length;
+       uint32_t                                lkey;
+
+}      ib_local_ds_t;
+/*****/
+
+
+/****d* Access Layer/ib_send_opt_t
+* NAME
+*      ib_send_opt_t
+*
+* DESCRIPTION
+*      Optional flags used when posting send work requests.  These flags
+*      indicate specific processing for the send operation.
+*
+* SYNOPSIS
+*/
+typedef uint32_t                                       ib_send_opt_t;
+#define IB_SEND_OPT_IMMEDIATE          0x00000001
+#define IB_SEND_OPT_FENCE                      0x00000002
+#define IB_SEND_OPT_SIGNALED           0x00000004
+#define IB_SEND_OPT_SOLICITED          0x00000008
+#define IB_SEND_OPT_INLINE                     0x00000010
+#define IB_SEND_OPT_LOCAL                      0x00000020
+#define IB_SEND_OPT_VEND_MASK          0xFFFF0000
+
+
+/*
+* VALUES
+*      The following flags determine the behavior of a work request when
+*      posted to the send side.
+*
+*      IB_SEND_OPT_IMMEDIATE
+*              Send immediate data with the given request.
+*
+*      IB_SEND_OPT_FENCE
+*              The operation is fenced.  Complete all pending send operations before
+*              processing this request.
+*
+*      IB_SEND_OPT_SIGNALED
+*              If the queue pair is configured for signaled completion, then
+*              generate a completion queue entry when this request completes.
+*
+*      IB_SEND_OPT_SOLICITED
+*              Set the solicited bit on the last packet of this request.
+*
+*      IB_SEND_OPT_INLINE
+*              Indicates that the requested send data should be copied into a VPD
+*              owned data buffer.  This flag permits the user to issue send operations
+*              without first needing to register the buffer(s) associated with the
+*              send operation.  Verb providers that support this operation may place
+*              vendor specific restrictions on the size of send operation that may
+*              be performed as inline.
+*
+*
+*  IB_SEND_OPT_LOCAL
+*     Indicates that a sent MAD request should be given to the local VPD for
+*     processing.  MADs sent using this option are not placed on the wire.
+*     This send option is only valid for MAD send operations.
+*
+*
+*      IB_SEND_OPT_VEND_MASK
+*              This mask indicates bits reserved in the send options that may be used
+*              by the verbs provider to indicate vendor specific options.  Bits set
+*              in this area of the send options are ignored by the Access Layer, but
+*              may have specific meaning to the underlying VPD.
+*
+*****/
+
+
+/****s* Access Layer/ib_send_wr_t
+* NAME
+*      ib_send_wr_t
+*
+* DESCRIPTION
+*      Information used to submit a work request to the send queue of a queue
+*      pair.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_send_wr
+{
+       struct _ib_send_wr              *p_next;
+       uint64_t                                wr_id;
+       ib_wr_type_t                    wr_type;
+       ib_send_opt_t                   send_opt;
+       uint32_t                                num_ds;
+       ib_local_ds_t                   *ds_array;
+       ib_net32_t                              immediate_data;
+
+       union _send_dgrm
+       {
+               struct _send_ud
+               {
+                       ib_net32_t              remote_qp;
+                       ib_net32_t              remote_qkey;
+                       ib_av_handle_t  h_av;
+
+               }       ud;
+
+               struct _send_rd
+               {
+                       ib_net32_t              remote_qp;
+                       ib_net32_t              remote_qkey;
+                       ib_net32_t              eecn;
+
+               }       rd;
+
+               struct _send_raw_ether
+               {
+                       ib_net16_t              dest_lid;
+                       uint8_t                 path_bits;
+                       uint8_t                 sl;
+                       uint8_t                 max_static_rate;
+                       ib_net16_t              ether_type;
+
+               }       raw_ether;
+
+               struct _send_raw_ipv6
+               {
+                       ib_net16_t              dest_lid;
+                       uint8_t                 path_bits;
+                       uint8_t                 sl;
+                       uint8_t                 max_static_rate;
+
+               }       raw_ipv6;
+
+       }       dgrm;
+
+       struct _send_remote_ops
+       {
+               uint64_t                        vaddr;
+               uint32_t                        rkey;
+
+               ib_net64_t                      atomic1;
+               ib_net64_t                      atomic2;
+
+       }       remote_ops;
+
+}      ib_send_wr_t;
+/*
+* FIELDS
+*      p_next
+*              A pointer used to chain work requests together.  This permits multiple
+*              work requests to be posted to a queue pair through a single function
+*              call.  This value is set to NULL to mark the end of the chain.
+*
+*      wr_id
+*              A 64-bit work request identifier that is returned to the consumer
+*              as part of the work completion.
+*
+*      wr_type
+*              The type of work request being submitted to the send queue.
+*
+*      send_opt
+*              Optional send control parameters.
+*
+*      num_ds
+*              Number of local data segments specified by this work request.
+*
+*      ds_array
+*              A reference to an array of local data segments used by the send
+*              operation.
+*
+*      immediate_data
+*              32-bit field sent as part of a message send or RDMA write operation.
+*              This field is only valid if the send_opt flag IB_SEND_OPT_IMMEDIATE
+*              has been set.
+*
+*      dgrm.ud.remote_qp
+*              Identifies the destination queue pair of an unreliable datagram send
+*              operation.
+*
+*      dgrm.ud.remote_qkey
+*              The qkey for the destination queue pair.
+*
+*      dgrm.ud.h_av
+*              An address vector that specifies the path information used to route
+*              the outbound datagram to the destination queue pair.
+*
+*      dgrm.rd.remote_qp
+*              Identifies the destination queue pair of a reliable datagram send
+*              operation.
+*
+*      dgrm.rd.remote_qkey
+*              The qkey for the destination queue pair.
+*
+*      dgrm.rd.eecn
+*              The local end-to-end context number to use with the reliable datagram
+*              send operation.
+*
+*      dgrm.raw_ether.dest_lid
+*              The destination LID that will receive this raw ether send.
+*
+*      dgrm.raw_ether.path_bits
+*              path bits...
+*
+*      dgrm.raw_ether.sl
+*              service level...
+*
+*      dgrm.raw_ether.max_static_rate
+*              static rate...
+*
+*      dgrm.raw_ether.ether_type
+*              ether type...
+*
+*      dgrm.raw_ipv6.dest_lid
+*              The destination LID that will receive this raw ether send.
+*
+*      dgrm.raw_ipv6.path_bits
+*              path bits...
+*
+*      dgrm.raw_ipv6.sl
+*              service level...
+*
+*      dgrm.raw_ipv6.max_static_rate
+*              static rate...
+*
+*      remote_ops.vaddr
+*              The registered virtual memory address of the remote memory to access
+*              with an RDMA or atomic operation.
+*
+*      remote_ops.rkey
+*              The rkey associated with the specified remote vaddr. This data must
+*              be presented exactly as obtained from the remote node. No swapping
+*              of data must be performed.
+*
+*      atomic1
+*              The first operand for an atomic operation.
+*
+*      atomic2
+*              The second operand for an atomic operation.
+*
+* NOTES
+*      The format of data sent over the fabric is user-defined and is considered
+*      opaque to the access layer.  The sole exception to this are MADs posted
+*      to a MAD QP service.  MADs are expected to match the format defined by
+*      the Infiniband specification and must be in network-byte order when posted
+*      to the MAD QP service.
+*
+* SEE ALSO
+*      ib_wr_type_t, ib_local_ds_t, ib_send_opt_t
+*****/
+
+
+/****s* Access Layer/ib_recv_wr_t
+* NAME
+*      ib_recv_wr_t
+*
+* DESCRIPTION
+*      Information used to submit a work request to the receive queue of a queue
+*      pair.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_recv_wr
+{
+       struct _ib_recv_wr              *p_next;
+       uint64_t                                wr_id;
+       uint32_t                                num_ds;
+       ib_local_ds_t                   *ds_array;
+
+}      ib_recv_wr_t;
+/*
+* FIELDS
+*      p_next
+*              A pointer used to chain work requests together.  This permits multiple
+*              work requests to be posted to a queue pair through a single function
+*              call.  This value is set to NULL to mark the end of the chain.
+*
+*      wr_id
+*              A 64-bit work request identifier that is returned to the consumer
+*              as part of the work completion.
+*
+*      num_ds
+*              Number of local data segments specified by this work request.
+*
+*      ds_array
+*              A reference to an array of local data segments used by the send
+*              operation.
+*
+* SEE ALSO
+*      ib_local_ds_t
+*****/
+
+
+/****s* Access Layer/ib_bind_wr_t
+* NAME
+*      ib_bind_wr_t
+*
+* DESCRIPTION
+*      Information used to submit a memory window bind work request to the send
+*      queue of a queue pair.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_bind_wr
+{
+       uint64_t                                wr_id;
+       ib_send_opt_t                   send_opt;
+
+       ib_mr_handle_t                  h_mr;
+       ib_access_t                             access_ctrl;
+       uint32_t                                current_rkey;
+
+       ib_local_ds_t                   local_ds;
+
+}      ib_bind_wr_t;
+/*
+* FIELDS
+*      wr_id
+*              A 64-bit work request identifier that is returned to the consumer
+*              as part of the work completion.
+*
+*      send_opt
+*              Optional send control parameters.
+*
+*      h_mr
+*              Handle to the memory region to which this window is being bound.
+*
+*      access_ctrl
+*              Access rights for this memory window.
+*
+*      current_rkey
+*              The current rkey assigned to this window for remote access.
+*
+*      local_ds
+*              A reference to a local data segment used by the bind operation.
+*
+* SEE ALSO
+*      ib_send_opt_t, ib_access_t, ib_local_ds_t
+*****/
+
+
+/****d* Access Layer/ib_wc_status_t
+* NAME
+*      ib_wc_status_t
+*
+* DESCRIPTION
+*      Indicates the status of a completed work request.  These VALUES are
+*      returned to the user when retrieving completions.  Note that success is
+*      identified as IB_WCS_SUCCESS, which is always zero.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_wc_status_t
+{
+       IB_WCS_SUCCESS,
+       IB_WCS_LOCAL_LEN_ERR,
+       IB_WCS_LOCAL_OP_ERR,
+       IB_WCS_LOCAL_EEC_OP_ERR,
+       IB_WCS_LOCAL_PROTECTION_ERR,
+       IB_WCS_WR_FLUSHED_ERR,
+       IB_WCS_MEM_WINDOW_BIND_ERR,
+       IB_WCS_REM_ACCESS_ERR,
+       IB_WCS_REM_OP_ERR,
+       IB_WCS_RNR_RETRY_ERR,
+       IB_WCS_TIMEOUT_RETRY_ERR,
+       IB_WCS_REM_INVALID_REQ_ERR,
+       IB_WCS_REM_INVALID_RD_REQ_ERR,
+       IB_WCS_INVALID_EECN,
+       IB_WCS_INVALID_EEC_STATE,
+       IB_WCS_UNMATCHED_RESPONSE,                      /* InfiniBand Access Layer */
+       IB_WCS_CANCELED,                                        /* InfiniBand Access Layer */
+       IB_WCS_UNKNOWN                                          /* Must be last. */
+
+}      ib_wc_status_t;
+/*
+* VALUES
+*      IB_WCS_SUCCESS
+*              Work request completed successfully.
+*
+*      IB_WCS_MAD
+*              The completed work request was associated with a managmenet datagram
+*              that requires post processing.  The MAD will be returned to the user
+*              through a callback once all post processing has completed.
+*
+*      IB_WCS_LOCAL_LEN_ERR
+*              Generated for a work request posted to the send queue when the
+*              total of the data segment lengths exceeds the message length of the
+*              channel.  Generated for a work request posted to the receive queue when
+*              the total of the data segment lengths is too small for a
+*              valid incoming message.
+*
+*      IB_WCS_LOCAL_OP_ERR
+*              An internal QP consistency error was generated while processing this
+*              work request.  This may indicate that the QP was in an incorrect state
+*              for the requested operation.
+*
+*      IB_WCS_LOCAL_EEC_OP_ERR
+*              An internal EEC consistency error was generated while processing
+*              this work request.  This may indicate that the EEC was in an incorrect
+*              state for the requested operation.
+*
+*      IB_WCS_LOCAL_PROTECTION_ERR
+*              The data segments of the locally posted work request did not refer to
+*              a valid memory region.  The memory may not have been properly
+*              registered for the requested operation.
+*
+*      IB_WCS_WR_FLUSHED_ERR
+*              The work request was flushed from the QP before being completed.
+*
+*      IB_WCS_MEM_WINDOW_BIND_ERR
+*              A memory window bind operation failed due to insufficient access
+*              rights.
+*
+*      IB_WCS_REM_ACCESS_ERR,
+*              A protection error was detected at the remote node for a RDMA or atomic
+*              operation.
+*
+*      IB_WCS_REM_OP_ERR,
+*              The operation could not be successfully completed at the remote node.
+*              This may indicate that the remote QP was in an invalid state or
+*              contained an invalid work request.
+*
+*      IB_WCS_RNR_RETRY_ERR,
+*              The RNR retry count was exceeded while trying to send this message.
+*
+*      IB_WCS_TIMEOUT_RETRY_ERR
+*              The local transport timeout counter expired while trying to send this
+*              message.
+*
+*      IB_WCS_REM_INVALID_REQ_ERR,
+*              The remote node detected an invalid message on the channel.  This error
+*              is usually a result of one of the following:
+*                      - The operation was not supported on receive queue.
+*                      - There was insufficient buffers to receive a new RDMA request.
+*                      - There was insufficient buffers to receive a new atomic operation.
+*                      - An RDMA request was larger than 2^31 bytes.
+*
+*      IB_WCS_REM_INVALID_RD_REQ_ERR,
+*              Responder detected an invalid RD message.  This may be the result of an
+*              invalid qkey or an RDD mismatch.
+*
+*      IB_WCS_INVALID_EECN
+*              An invalid EE context number was detected.
+*
+*      IB_WCS_INVALID_EEC_STATE
+*              The EEC was in an invalid state for the specified request.
+*
+*      IB_WCS_UNMATCHED_RESPONSE
+*              A response MAD was received for which there was no matching send.  The
+*              send operation may have been canceled by the user or may have timed
+*              out.
+*
+*      IB_WCS_CANCELED
+*              The completed work request was canceled by the user.
+*****/
+
+
+AL_EXPORT const char* ib_wc_status_str[];
+
+
+/****f* IBA Base: Types/ib_get_wc_status_str
+* NAME
+*      ib_get_wc_status_str
+*
+* DESCRIPTION
+*      Returns a string for the specified work completion status.
+*
+* SYNOPSIS
+*/
+AL_INLINE const char*    AL_API
+ib_get_wc_status_str(
+       IN                              ib_wc_status_t                          wc_status )
+{
+       if( wc_status > IB_WCS_UNKNOWN )
+               wc_status = IB_WCS_UNKNOWN;
+       return( ib_wc_status_str[wc_status] );
+}
+/*
+* PARAMETERS
+*      wc_status
+*              [in] work completion status value
+*
+* RETURN VALUES
+*      Pointer to the work completion status description string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+/****d* Access Layer/ib_wc_type_t
+* NAME
+*      ib_wc_type_t
+*
+* DESCRIPTION
+*      Indicates the type of work completion.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_wc_type_t
+{
+       IB_WC_SEND,
+       IB_WC_RDMA_WRITE,
+       IB_WC_RECV,
+       IB_WC_RDMA_READ,
+       IB_WC_MW_BIND,
+       IB_WC_FETCH_ADD,
+       IB_WC_COMPARE_SWAP,
+       IB_WC_RECV_RDMA_WRITE
+
+}      ib_wc_type_t;
+/*****/
+
+
+/****d* Access Layer/ib_recv_opt_t
+* NAME
+*      ib_recv_opt_t
+*
+* DESCRIPTION
+*      Indicates optional fields valid in a receive work completion.
+*
+* SYNOPSIS
+*/
+typedef uint32_t                                       ib_recv_opt_t;
+#define        IB_RECV_OPT_IMMEDIATE           0x00000001
+#define IB_RECV_OPT_FORWARD                    0x00000002
+#define IB_RECV_OPT_GRH_VALID          0x00000004
+#define IB_RECV_OPT_VEND_MASK          0xFFFF0000
+/*
+* VALUES
+*      IB_RECV_OPT_IMMEDIATE
+*              Indicates that immediate data is valid for this work completion.
+*
+*      IB_RECV_OPT_FORWARD
+*              Indicates that the received trap should be forwarded to the SM.
+*
+*      IB_RECV_OPT_GRH_VALID
+*              Indicates presence of the global route header. When set, the first
+*              40 bytes received are the GRH.
+*
+*      IB_RECV_OPT_VEND_MASK
+*              This mask indicates bits reserved in the receive options that may be
+*              used by the verbs provider to indicate vendor specific options.  Bits
+*              set in this area of the receive options are ignored by the Access Layer,
+*              but may have specific meaning to the underlying VPD.
+*****/
+
+
+/****s* Access Layer/ib_wc_t
+* NAME
+*      ib_wc_t
+*
+* DESCRIPTION
+*      Work completion information.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_wc
+{
+       struct _ib_wc                   *p_next;
+       uint64_t                                wr_id;
+       ib_wc_type_t                    wc_type;
+
+       uint32_t                                length;
+       ib_wc_status_t                  status;
+       uint64_t                                vendor_specific;
+
+       union _wc_recv
+       {
+               struct _wc_conn
+               {
+                       ib_recv_opt_t   recv_opt;
+                       ib_net32_t              immediate_data;
+
+               }       conn;
+
+               struct _wc_ud
+               {
+                       ib_recv_opt_t   recv_opt;
+                       ib_net32_t              immediate_data;
+                       ib_net32_t              remote_qp;
+                       uint16_t                pkey_index;
+                       ib_net16_t              remote_lid;
+                       uint8_t                 remote_sl;
+                       uint8_t                 path_bits;
+
+               }       ud;
+
+               struct _wc_rd
+               {
+                       ib_net32_t              remote_eecn;
+                       ib_net32_t              remote_qp;
+                       ib_net16_t              remote_lid;
+                       uint8_t                 remote_sl;
+                       uint32_t                free_cnt;
+
+               }       rd;
+
+               struct _wc_raw_ipv6
+               {
+                       ib_net16_t              remote_lid;
+                       uint8_t                 remote_sl;
+                       uint8_t                 path_bits;
+
+               }       raw_ipv6;
+
+               struct _wc_raw_ether
+               {
+                       ib_net16_t              remote_lid;
+                       uint8_t                 remote_sl;
+                       uint8_t                 path_bits;
+                       ib_net16_t              ether_type;
+
+               }       raw_ether;
+
+       }       recv;
+
+}      ib_wc_t;
+/*
+* FIELDS
+*      p_next
+*              A pointer used to chain work completions.  This permits multiple
+*              work completions to be retrieved from a completion queue through a
+*              single function call.  This value is set to NULL to mark the end of
+*              the chain.
+*
+*      wr_id
+*              The 64-bit work request identifier that was specified when posting the
+*              work request.
+*
+*      wc_type
+*              Indicates the type of work completion.
+*
+*
+*      length
+*              The total length of the data sent or received with the work request.
+*
+*      status
+*              The result of the work request.
+*
+*      vendor_specific
+*              HCA vendor specific information returned as part of the completion.
+*
+*      recv.conn.recv_opt
+*              Indicates optional fields valid as part of a work request that
+*              completed on a connected (reliable or unreliable) queue pair.
+*
+*      recv.conn.immediate_data
+*              32-bit field received as part of an inbound message on a connected
+*              queue pair.  This field is only valid if the recv_opt flag
+*              IB_RECV_OPT_IMMEDIATE has been set.
+*
+*      recv.ud.recv_opt
+*              Indicates optional fields valid as part of a work request that
+*              completed on an unreliable datagram queue pair.
+*
+*      recv.ud.immediate_data
+*              32-bit field received as part of an inbound message on a unreliable
+*              datagram queue pair.  This field is only valid if the recv_opt flag
+*              IB_RECV_OPT_IMMEDIATE has been set.
+*
+*      recv.ud.remote_qp
+*              Identifies the source queue pair of a received datagram.
+*
+*      recv.ud.pkey_index
+*              The pkey index for the source queue pair. This is valid only for
+*              GSI type QP's.
+*
+*      recv.ud.remote_lid
+*              The source LID of the received datagram.
+*
+*      recv.ud.remote_sl
+*              The service level used by the source of the received datagram.
+*
+*      recv.ud.path_bits
+*              path bits...
+*
+*      recv.rd.remote_eecn
+*              The remote end-to-end context number that sent the received message.
+*
+*      recv.rd.remote_qp
+*              Identifies the source queue pair of a received message.
+*
+*      recv.rd.remote_lid
+*              The source LID of the received message.
+*
+*      recv.rd.remote_sl
+*              The service level used by the source of the received message.
+*
+*      recv.rd.free_cnt
+*              The number of available entries in the completion queue.  Reliable
+*              datagrams may complete out of order, so this field may be used to
+*              determine the number of additional completions that may occur.
+*
+*      recv.raw_ipv6.remote_lid
+*              The source LID of the received message.
+*
+*      recv.raw_ipv6.remote_sl
+*              The service level used by the source of the received message.
+*
+*      recv.raw_ipv6.path_bits
+*              path bits...
+*
+*      recv.raw_ether.remote_lid
+*              The source LID of the received message.
+*
+*      recv.raw_ether.remote_sl
+*              The service level used by the source of the received message.
+*
+*      recv.raw_ether.path_bits
+*              path bits...
+*
+*      recv.raw_ether.ether_type
+*              ether type...
+* NOTES
+*      When the work request completes with error, the only values that the
+*      consumer can depend on are the wr_id field, and the status of the
+*      operation.
+*
+*      If the consumer is using the same CQ for completions from more than
+*      one type of QP (i.e Reliable Connected, Datagram etc), then the consumer
+*      must have additional information to decide what fields of the union are
+*      valid.
+* SEE ALSO
+*      ib_wc_type_t, ib_qp_type_t, ib_wc_status_t, ib_recv_opt_t
+*****/
+
+
+/****s* Access Layer/ib_mr_create_t
+* NAME
+*      ib_mr_create_t
+*
+* DESCRIPTION
+*      Information required to create a registered memory region.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_mr_create
+{
+       void                                    *vaddr;
+       uint64_t                                length;
+       ib_access_t                             access_ctrl;
+
+}      ib_mr_create_t;
+/*
+* FIELDS
+*      vaddr
+*              Starting virtual address of the region being registered.
+*
+*      length
+*              Length of the buffer to register.
+*
+*      access_ctrl
+*              Access rights of the registered region.
+*
+* SEE ALSO
+*      ib_access_t
+*****/
+
+
+/****s* Access Layer/ib_phys_create_t
+* NAME
+*      ib_phys_create_t
+*
+* DESCRIPTION
+*      Information required to create a physical memory region.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_phys_create
+{
+       uint64_t                                length;
+       uint32_t                                num_bufs;
+       uint64_t                                *buf_array;
+       uint32_t                                buf_offset;
+       uint32_t                                page_size;
+       ib_access_t                             access_ctrl;
+
+}      ib_phys_create_t;
+/*
+*      length
+*              The length of the memory region in bytes.
+*
+*      num_bufs
+*              Number of buffers listed in the specified buffer array.
+*
+*      buf_array
+*              An array of physical buffers to be registered as a single memory
+*              region.
+*
+*      buf_offset
+*              The offset into the first physical page of the specified memory
+*              region to start the virtual address.
+*
+*      page_size
+*              The physical page size of the memory being registered.
+*
+*      access_ctrl
+*              Access rights of the registered region.
+*
+* SEE ALSO
+*      ib_access_t
+*****/
+
+
+/****s* Access Layer/ib_mr_attr_t
+* NAME
+*      ib_mr_attr_t
+*
+* DESCRIPTION
+*      Attributes of a registered memory region.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_mr_attr
+{
+       ib_pd_handle_t                  h_pd;
+       void                                    *local_lb;
+       void                                    *local_ub;
+       void                                    *remote_lb;
+       void                                    *remote_ub;
+       ib_access_t                             access_ctrl;
+       uint32_t                                lkey;
+       uint32_t                                rkey;
+
+}      ib_mr_attr_t;
+/*
+* DESCRIPTION
+*      h_pd
+*              Handle to the protection domain for this memory region.
+*
+*      local_lb
+*              The virtual address of the lower bound of protection for local
+*              memory access.
+*
+*      local_ub
+*              The virtual address of the upper bound of protection for local
+*              memory access.
+*
+*      remote_lb
+*              The virtual address of the lower bound of protection for remote
+*              memory access.
+*
+*      remote_ub
+*              The virtual address of the upper bound of protection for remote
+*              memory access.
+*
+*      access_ctrl
+*              Access rights for the specified memory region.
+*
+*      lkey
+*              The lkey associated with this memory region.
+*
+*      rkey
+*              The rkey associated with this memory region.
+*
+* NOTES
+*      The remote_lb, remote_ub, and rkey are only valid if remote memory access
+*      is enabled for this memory region.
+*
+* SEE ALSO
+*      ib_access_t
+*****/
+
+
+/****d* Access Layer/ib_ca_mod_t
+* NAME
+*      ib_ca_mod_t -- Modify port attributes and error counters
+*
+* DESCRIPTION
+*      Specifies modifications to the port attributes of a channel adapter.
+*
+* SYNOPSIS
+*/
+typedef uint32_t                                                       ib_ca_mod_t;
+#define IB_CA_MOD_IS_CM_SUPPORTED                      0x00000001
+#define IB_CA_MOD_IS_SNMP_SUPPORTED                    0x00000002
+#define        IB_CA_MOD_IS_DEV_MGMT_SUPPORTED         0x00000004
+#define        IB_CA_MOD_IS_VEND_SUPPORTED                     0x00000008
+#define        IB_CA_MOD_IS_SM                                         0x00000010
+#define IB_CA_MOD_IS_SM_DISABLED                       0x00000020
+#define IB_CA_MOD_QKEY_CTR                                     0x00000040
+#define IB_CA_MOD_PKEY_CTR                                     0x00000080
+#define IB_CA_MOD_IS_NOTICE_SUPPORTED          0x00000100
+#define IB_CA_MOD_IS_TRAP_SUPPORTED                    0x00000200
+#define IB_CA_MOD_IS_APM_SUPPORTED                     0x00000400
+#define IB_CA_MOD_IS_SLMAP_SUPPORTED           0x00000800
+#define IB_CA_MOD_IS_PKEY_NVRAM_SUPPORTED      0x00001000
+#define IB_CA_MOD_IS_MKEY_NVRAM_SUPPORTED      0x00002000
+#define IB_CA_MOD_IS_SYSGUID_SUPPORTED         0x00004000
+#define IB_CA_MOD_IS_DR_NOTICE_SUPPORTED       0x00008000
+#define IB_CA_MOD_IS_BOOT_MGMT_SUPPORTED       0x00010000
+#define IB_CA_MOD_IS_CAPM_NOTICE_SUPPORTED     0x00020000
+#define IB_CA_MOD_IS_REINIT_SUPORTED           0x00040000
+#define IB_CA_MOD_IS_LEDINFO_SUPPORTED         0x00080000
+#define IB_CA_MOD_SHUTDOWN_PORT                                0x00100000
+#define IB_CA_MOD_INIT_TYPE_VALUE                      0x00200000
+#define IB_CA_MOD_SYSTEM_IMAGE_GUID                    0x00400000
+/*
+* VALUES
+*      IB_CA_MOD_IS_CM_SUPPORTED
+*              Indicates if there is a communication manager accessible through
+*              the port.
+*
+*      IB_CA_MOD_IS_SNMP_SUPPORTED
+*              Indicates if there is an SNMP agent accessible through the port.
+*
+*      IB_CA_MOD_IS_DEV_MGMT_SUPPORTED
+*              Indicates if there is a device management agent accessible through
+*              the port.
+*
+*      IB_CA_MOD_IS_VEND_SUPPORTED
+*              Indicates if there is a vendor supported agent accessible through
+*              the port.
+*
+*      IB_CA_MOD_IS_SM
+*              Indicates if there is a subnet manager accessible through
+*              the port.
+*
+*      IB_CA_MOD_IS_SM_DISABLED
+*              Indicates if the port has been disabled for configuration by the subnet
+*              manager.
+*
+*      IB_CA_MOD_QKEY_CTR
+*              Used to reset the qkey violation counter associated with the port.
+*
+*      IB_CA_MOD_PKEY_CTR
+*              Used to reset the pkey violation counter associated with the port.
+*
+*      IB_CA_MOD_IS_NOTICE_SUPPORTED
+*              Indicates that this CA supports ability to generate Notices for
+*              Port State changes. (only applicable to switches)
+*
+*      IB_CA_MOD_IS_TRAP_SUPPORTED
+*              Indicates that this management port supports ability to generate
+*              trap messages. (only applicable to switches)
+*
+*      IB_CA_MOD_IS_APM_SUPPORTED
+*              Indicates that this port is capable of performing Automatic Migration.
+*
+*      IB_CA_MOD_IS_SLMAP_SUPPORTED
+*              Indicates this port supports SLMAP capability.
+*
+*      IB_CA_MOD_IS_PKEY_NVRAM_SUPPORTED
+*              Indicates that PKEY is supported in NVRAM
+*
+*      IB_CA_MOD_IS_MKEY_NVRAM_SUPPORTED
+*              Indicates that MKEY is supported in NVRAM
+*
+*      IB_CA_MOD_IS_SYSGUID_SUPPORTED
+*              Indicates System Image GUID support.
+*
+*      IB_CA_MOD_IS_DR_NOTICE_SUPPORTED
+*              Indicate support for generating Direct Routed Notices
+*
+*      IB_CA_MOD_IS_BOOT_MGMT_SUPPORTED
+*              Indicates support for Boot Management
+*
+*      IB_CA_MOD_IS_CAPM_NOTICE_SUPPORTED
+*              Indicates capability to generate notices for changes to CAPMASK
+*
+*      IB_CA_MOD_IS_REINIT_SUPORTED
+*              Indicates type of node init supported. Refer to Chapter 14 for
+*              Initialization actions.
+*
+*      IB_CA_MOD_IS_LEDINFO_SUPPORTED
+*              Indicates support for LED info.
+*
+*      IB_CA_MOD_SHUTDOWN_PORT
+*              Used to modify the port active indicator.
+*
+*      IB_CA_MOD_INIT_TYPE_VALUE
+*              Used to modify the init_type value for the port.
+*
+*      IB_CA_MOD_SYSTEM_IMAGE_GUID
+*              Used to modify the system image GUID for the port.
+*****/
+
+
+/****d* Access Layer/ib_mr_mod_t
+* NAME
+*      ib_mr_mod_t
+*
+* DESCRIPTION
+*      Mask used to specify which attributes of a registered memory region are
+*      being modified.
+*
+* SYNOPSIS
+*/
+typedef uint32_t                                               ib_mr_mod_t;
+#define IB_MR_MOD_ADDR                                 0x00000001
+#define IB_MR_MOD_PD                                   0x00000002
+#define IB_MR_MOD_ACCESS                               0x00000004
+/*
+* PARAMETERS
+*      IB_MEM_MOD_ADDR
+*              The address of the memory region is being modified.
+*
+*      IB_MEM_MOD_PD
+*              The protection domain associated with the memory region is being
+*              modified.
+*
+*      IB_MEM_MOD_ACCESS
+*              The access rights the memory region are being modified.
+*****/
+
+/****d* IBA Base: Constants/IB_SMINFO_STATE_INIT
+* NAME
+*      IB_SMINFO_STATE_INIT
+*
+* DESCRIPTION
+*      Encoded state value used in the SMInfo attribute.
+*
+* SOURCE
+*/
+#define IB_SMINFO_STATE_INIT                                   4
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_HANDOVER
+* NAME
+*      IB_SMINFO_ATTR_MOD_HANDOVER
+*
+* DESCRIPTION
+*      Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_HANDOVER            (CL_NTOH32(0x000001))
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_ACKNOWLEDGE
+* NAME
+*      IB_SMINFO_ATTR_MOD_ACKNOWLEDGE
+*
+* DESCRIPTION
+*      Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_ACKNOWLEDGE         (CL_NTOH32(0x000002))
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_DISABLE
+* NAME
+*      IB_SMINFO_ATTR_MOD_DISABLE
+*
+* DESCRIPTION
+*      Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_DISABLE                     (CL_NTOH32(0x000003))
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_STANDBY
+* NAME
+*      IB_SMINFO_ATTR_MOD_STANDBY
+*
+* DESCRIPTION
+*      Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_STANDBY                     (CL_NTOH32(0x000004))
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_DISCOVER
+* NAME
+*      IB_SMINFO_ATTR_MOD_DISCOVER
+*
+* DESCRIPTION
+*      Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_DISCOVER                    (CL_NTOH32(0x000005))
+/**********/
+
+/****s* Access Layer/ib_ci_op_t
+* NAME
+*      ib_ci_op_t
+*
+* DESCRIPTION
+*      A structure used for vendor specific CA interface communication.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_ci_op
+{
+       IN                              uint32_t                                        command;
+       IN      OUT                     void*                                           p_buf OPTIONAL;
+       IN                              uint32_t                                        buf_size;
+       IN      OUT                     uint32_t                                        num_bytes_ret;
+       IN      OUT                     int32_t                                         status;
+
+}      ib_ci_op_t;
+/*
+* FIELDS
+*      command
+*              A command code that is understood by the verbs provider.
+*
+*      p_buf
+*              A reference to a buffer containing vendor specific data.  The verbs
+*              provider must not access pointers in the p_buf between user-mode and
+*              kernel-mode.  Any pointers embedded in the p_buf are invalidated by
+*              the user-mode/kernel-mode transition.
+*
+*      buf_size
+*              The size of the buffer in bytes.
+*
+*      num_bytes_ret
+*              The size in bytes of the vendor specific data returned in the buffer.
+*              This field is set by the verbs provider.  The verbs provider should
+*              verify that the buffer size is sufficient to hold the data being
+*              returned.
+*
+*      status
+*              The completion status from the verbs provider.  This field should be
+*              initialize to indicate an error to allow detection and cleanup in
+*              case a communication error occurs between user-mode and kernel-mode.
+*
+* NOTES
+*      This structure is provided to allow the exchange of vendor specific
+*      data between the originator and the verbs provider.  Users of this
+*      structure are expected to know the format of data in the p_buf based
+*      on the structure command field or the usage context.
+*****/
+
+END_C_DECLS
+
+#endif
+#if defined( __WIN__ )
+    #include <iba/ib_types_extended.h>
+#endif
+
+#endif // __IB_TYPES_H__
diff --git a/trunk/ulp/opensm/user/include/iba/ib_types_extended.h b/trunk/ulp/opensm/user/include/iba/ib_types_extended.h
new file mode 100644 (file)
index 0000000..3340c91
--- /dev/null
@@ -0,0 +1,2485 @@
+/*
+ * 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$
+ */
+
+
+#if !defined(__IB_TYPES_EXTENDED_H__)
+#define __IB_TYPES_EXTENDED_H__
+
+
+#if defined( WIN32 )
+       #if defined( EXPORT_AL_SYMBOLS )
+               #define AL_EXPORT       __declspec(dllexport)
+       #else
+               #define AL_EXPORT       __declspec(dllimport)
+       #endif
+
+       #ifdef CL_KERNEL
+               #define AL_API
+               #define AL_INLINE       static inline
+       #else
+               #define AL_API          __stdcall
+                #define AL_INLINE      AL_EXPORT inline
+       #endif  /* CL_KERNEL */
+#else
+       #define AL_EXPORT       extern
+       #define AL_INLINE       static inline
+       #define AL_API
+       #define __ptr64
+#endif
+/*
+ *     Defines the size of user available data in communication management MADs
+ */
+#define IB_REQ_PDATA_SIZE                                      92
+#define IB_MRA_PDATA_SIZE                                      222
+#define IB_REJ_PDATA_SIZE                                      148
+#define IB_REP_PDATA_SIZE                                      196
+#define IB_RTU_PDATA_SIZE                                      224
+#define IB_LAP_PDATA_SIZE                                      168
+#define IB_APR_PDATA_SIZE                                      148
+#define IB_DREQ_PDATA_SIZE                                     220
+#define IB_DREP_PDATA_SIZE                                     224
+#define IB_SIDR_REQ_PDATA_SIZE                         216
+#define IB_SIDR_REP_PDATA_SIZE                         136
+
+/* following v1 ver1.2 p901 */
+#define IB_PATH_RECORD_RATE_5_GBS               5
+#define IB_PATH_RECORD_RATE_20_GBS              6
+#define IB_PATH_RECORD_RATE_40_GBS              7
+#define IB_PATH_RECORD_RATE_60_GBS              8
+#define IB_PATH_RECORD_RATE_80_GBS              9
+#define IB_PATH_RECORD_RATE_120_GBS             10
+
+
+
+/*
+ *     The following definitions are shared between the Access Layer and VPD
+ */
+
+
+
+/****d* Access Layer/ib_api_status_t
+* NAME
+*      ib_api_status_t
+*
+* DESCRIPTION
+*      Function return codes indicating the success or failure of an API call.
+*      Note that success is indicated by the return value IB_SUCCESS, which
+*      is always zero.
+*
+* NOTES
+*      IB_VERBS_PROCESSING_DONE is used by UVP library to terminate a verbs call
+*      in the pre-ioctl step itself.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_api_status_t
+{
+       IB_SUCCESS,
+       IB_INSUFFICIENT_RESOURCES,
+       IB_INSUFFICIENT_MEMORY,
+       IB_INVALID_PARAMETER,
+       IB_INVALID_SETTING,
+       IB_NOT_FOUND,
+       IB_TIMEOUT,
+       IB_CANCELED,
+       IB_INTERRUPTED,
+       IB_INVALID_PERMISSION,
+       IB_UNSUPPORTED,
+       IB_OVERFLOW,
+       IB_MAX_MCAST_QPS_REACHED,
+       IB_INVALID_QP_STATE,
+       IB_INVALID_APM_STATE,
+       IB_INVALID_PORT_STATE,
+       IB_INVALID_STATE,
+       IB_RESOURCE_BUSY,
+       IB_INVALID_PKEY,
+       IB_INVALID_LKEY,
+       IB_INVALID_RKEY,
+       IB_INVALID_MAX_WRS,
+       IB_INVALID_MAX_SGE,
+       IB_INVALID_CQ_SIZE,
+       IB_INVALID_SERVICE_TYPE,
+       IB_INVALID_GID,
+       IB_INVALID_LID,
+       IB_INVALID_GUID,
+       IB_INVALID_CA_HANDLE,
+       IB_INVALID_AV_HANDLE,
+       IB_INVALID_CQ_HANDLE,
+       IB_INVALID_QP_HANDLE,
+       IB_INVALID_PD_HANDLE,
+       IB_INVALID_MR_HANDLE,
+       IB_INVALID_MW_HANDLE,
+       IB_INVALID_MCAST_HANDLE,
+       IB_INVALID_CALLBACK,
+       IB_INVALID_AL_HANDLE,                                   /* InfiniBand Access Layer */
+       IB_INVALID_HANDLE,                                              /* InfiniBand Access Layer */
+       IB_ERROR,                                                               /* InfiniBand Access Layer */
+       IB_REMOTE_ERROR,                                                /* Infiniband Access Layer */
+       IB_VERBS_PROCESSING_DONE,                               /* See Notes above                 */
+       IB_INVALID_WR_TYPE,
+       IB_QP_IN_TIMEWAIT,
+       IB_INVALID_PORT,
+       IB_NOT_DONE,
+       IB_INVALID_INDEX,
+       IB_NO_MATCH,
+       IB_PENDING,
+       IB_UNKNOWN_ERROR                                                /* ALWAYS LAST ENUM VALUE! */
+
+}      ib_api_status_t;
+/*****/
+
+
+
+/****f* IBA Base: Types/ib_get_err_str
+* NAME
+*      ib_get_err_str
+*
+* DESCRIPTION
+*      Returns a string for the specified status value.
+*
+* SYNOPSIS
+*/
+AL_EXPORT const char* AL_API
+ib_get_err_str(
+       IN                              ib_api_status_t                         status );
+/*
+* PARAMETERS
+*      status
+*              [in] status value
+*
+* RETURN VALUES
+*      Pointer to the status description string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****d* Verbs/ib_async_event_t
+* NAME
+*      ib_async_event_t -- Async event types
+*
+* DESCRIPTION
+*      This type indicates the reason the async callback was called.
+*      The context in the ib_event_rec_t indicates the resource context
+*      that associated with the callback.  For example, for IB_AE_CQ_ERROR
+*      the context provided during the ib_create_cq is returned in the event.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_async_event_t
+{
+       IB_AE_SQ_ERROR = 1,
+       IB_AE_SQ_DRAINED,
+       IB_AE_RQ_ERROR,
+       IB_AE_CQ_ERROR,
+       IB_AE_QP_FATAL,
+       IB_AE_QP_COMM,
+       IB_AE_QP_APM,
+       IB_AE_LOCAL_FATAL,
+       IB_AE_PKEY_TRAP,
+       IB_AE_QKEY_TRAP,
+       IB_AE_MKEY_TRAP,
+       IB_AE_PORT_TRAP,
+       IB_AE_SYSIMG_GUID_TRAP,
+       IB_AE_BUF_OVERRUN,
+       IB_AE_LINK_INTEGRITY,
+       IB_AE_FLOW_CTRL_ERROR,
+       IB_AE_BKEY_TRAP,
+       IB_AE_QP_APM_ERROR,
+       IB_AE_WQ_REQ_ERROR,
+       IB_AE_WQ_ACCESS_ERROR,
+       IB_AE_PORT_ACTIVE,
+       IB_AE_PORT_DOWN,
+       IB_AE_UNKNOWN           /* ALWAYS LAST ENUM VALUE */
+
+}      ib_async_event_t;
+/*
+* VALUES
+*      IB_AE_SQ_ERROR
+*              An error occurred when accessing the send queue of the QP.
+*              This event is optional.
+*
+*      IB_AE_SQ_DRAINED
+*              The send queue of the specified QP has completed the outstanding
+*              messages in progress when the state change was requested and, if
+*              applicable, has received all acknowledgements for those messages.
+*
+*      IB_AE_RQ_ERROR
+*              An error occurred when accessing the receive queue of the QP.
+*              This event is optional.
+*
+*      IB_AE_CQ_ERROR
+*              An error occurred when writing an entry to the CQ.
+*
+*      IB_AE_QP_FATAL
+*              A catastrophic error occurred while accessing or processing the
+*              work queue that prevents reporting of completions.
+*
+*      IB_AE_QP_COMM
+*              The first packet has arrived for the receive work queue where the
+*              QP is still in the RTR state.
+*
+*      IB_AE_QP_APM
+*              If alternate path migration is supported, this event indicates that
+*              the QP connection has migrated to the alternate path.
+*
+*      IB_AE_LOCAL_FATAL
+*              A catastrophic HCA error occurred which cannot be attributed to any
+*              resource; behavior is indeterminate.
+*
+*      IB_AE_PKEY_TRAP
+*              A PKEY violation was detected.  This event is optional.
+*
+*      IB_AE_QKEY_TRAP
+*              A QKEY violation was detected.  This event is optional.
+*
+*      IB_AE_MKEY_TRAP
+*              An MKEY violation was detected.  This event is optional.
+*
+*      IB_AE_PORT_TRAP
+*              A port capability change was detected.  This event is optional.
+*
+*      IB_AE_SYSIMG_GUID_TRAP
+*              If the system image GUID is supported, this event indicates that the
+*              system image GUID of this HCA has been changed.  This event is
+*              optional.
+*
+*      IB_AE_BUF_OVERRUN
+*              The number of consecutive flow control update periods with at least
+*              one overrun error in each period has exceeded the threshold specified
+*              in the port info attributes.  This event is optional.
+*
+*      IB_AE_LINK_INTEGRITY
+*              The detection of excessively frequent local physical errors has
+*              exceeded the threshold specified in the port info attributes.  This
+*              event is optional.
+*
+*      IB_AE_FLOW_CTRL_ERROR
+*              An HCA watchdog timer monitoring the arrival of flow control updates
+*              has expired without receiving an update.  This event is optional.
+*
+*      IB_AE_BKEY_TRAP
+*              An BKEY violation was detected.  This event is optional.
+*
+*      IB_AE_QP_APM_ERROR
+*              If alternate path migration is supported, this event indicates that
+*              an incoming path migration request to this QP was not accepted.
+*
+*      IB_AE_WQ_REQ_ERROR
+*              An OpCode violation was detected at the responder.
+*
+*      IB_AE_WQ_ACCESS_ERROR
+*              An access violation was detected at the responder.
+*
+*      IB_AE_PORT_ACTIVE
+*              If the port active event is supported, this event is generated
+*              when the link becomes active: IB_LINK_ACTIVE.
+*
+*      IB_AE_PORT_DOWN
+*              The link is declared unavailable: IB_LINK_INIT, IB_LINK_ARMED,
+*              IB_LINK_DOWN.
+*
+*      IB_AE_UNKNOWN
+*              An unknown error occurred which cannot be attributed to any
+*              resource; behavior is indeterminate.
+*
+*****/
+
+
+
+/****f* IBA Base: Types/ib_get_async_event_str
+* NAME
+*      ib_get_async_event_str
+*
+* DESCRIPTION
+*      Returns a string for the specified asynchronous event.
+*
+* SYNOPSIS
+*/
+AL_EXPORT const char* AL_API
+ib_get_async_event_str(
+       IN                              ib_async_event_t                        event );
+/*
+* PARAMETERS
+*      event
+*              [in] event value
+*
+* RETURN VALUES
+*      Pointer to the asynchronous event description string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+/****s* Verbs/ib_event_rec_t
+* NAME
+*      ib_event_rec_t -- Async event notification record
+*
+* DESCRIPTION
+*      When an async event callback is made, this structure is passed to indicate
+*      the type of event, the source of event that caused it, and the context
+*      associated with this event.
+*
+*      context -- Context of the resource that caused the event.
+*              -- ca_context if this is a port/adapter event.
+*              -- qp_context if the source is a QP event
+*              -- cq_context if the source is a CQ event.
+*              -- ee_context if the source is an EE event.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_event_rec
+{
+       void* __ptr64                   context;
+       ib_async_event_t                type;
+
+       /* HCA vendor specific event information. */
+       uint64_t                                vendor_specific;
+
+       /* The following structures are valid only for trap types. */
+       union _trap
+       {
+               struct
+               {
+                       uint16_t                        lid;
+                       ib_net64_t                      port_guid;
+                       uint8_t                         port_num;
+
+                       /*
+                        * The following structure is valid only for
+                        * P_KEY, Q_KEY, and M_KEY violation traps.
+                        */
+                       struct
+                       {
+                               uint8_t                 sl;
+                               uint16_t                src_lid;
+                               uint16_t                dest_lid;
+                               union _key
+                               {
+                                       uint16_t        pkey;
+                                       uint32_t        qkey;
+                                       uint64_t        mkey;
+                               } key;
+                               uint32_t                src_qp;
+                               uint32_t                dest_qp;
+                               ib_gid_t                src_gid;
+                               ib_gid_t                dest_gid;
+
+                       }       violation;
+
+               } info;
+
+               ib_net64_t      sysimg_guid;
+
+       }       trap;
+
+}      ib_event_rec_t;
+/*******/
+
+
+/****d* Access Layer/ib_atomic_t
+* NAME
+*      ib_atomic_t
+*
+* DESCRIPTION
+*      Indicates atomicity levels supported by an adapter.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_atomic_t
+{
+       IB_ATOMIC_NONE,
+       IB_ATOMIC_LOCAL,
+       IB_ATOMIC_GLOBAL
+
+}      ib_atomic_t;
+/*
+* VALUES
+*      IB_ATOMIC_NONE
+*              Atomic operations not supported.
+*
+*      IB_ATOMIC_LOCAL
+*              Atomic operations guaranteed between QPs of a single CA.
+*
+*      IB_ATOMIC_GLOBAL
+*              Atomic operations are guaranteed between CA and any other entity
+*              in the system.
+*****/
+
+
+/****s* Access Layer/ib_port_cap_t
+* NAME
+*      ib_port_cap_t
+*
+* DESCRIPTION
+*      Indicates which management agents are currently available on the specified
+*      port.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_port_cap
+{
+       boolean_t               cm;
+       boolean_t               snmp;
+       boolean_t               dev_mgmt;
+       boolean_t               vend;
+       boolean_t               sm;
+       boolean_t               sm_disable;
+       boolean_t               qkey_ctr;
+       boolean_t               pkey_ctr;
+       boolean_t               notice;
+       boolean_t               trap;
+       boolean_t               apm;
+       boolean_t               slmap;
+       boolean_t               pkey_nvram;
+       boolean_t               mkey_nvram;
+       boolean_t               sysguid;
+       boolean_t               dr_notice;
+       boolean_t               boot_mgmt;
+       boolean_t               capm_notice;
+       boolean_t               reinit;
+       boolean_t               ledinfo;
+       boolean_t               port_active;
+       boolean_t               ipd;
+       boolean_t               pkey_switch_ext_port;
+       boolean_t               bm;
+       boolean_t               link_rtl;
+       boolean_t               client_reregister;      
+
+}      ib_port_cap_t;
+/*****/
+
+
+/****d* Access Layer/ib_init_type_t
+* NAME
+*      ib_init_type_t
+*
+* DESCRIPTION
+*      If supported by the HCA, the type of initialization requested by
+*      this port before SM moves it to the active or armed state.  If the
+*      SM implements reinitialization, it shall set these bits to indicate
+*      the type of initialization performed prior to activating the port.
+*      Otherwise, these bits shall be set to 0.
+*
+* SYNOPSIS
+*/
+typedef uint8_t                                        ib_init_type_t;
+#define IB_INIT_TYPE_NO_LOAD                           0x01
+#define IB_INIT_TYPE_PRESERVE_CONTENT          0x02
+#define IB_INIT_TYPE_PRESERVE_PRESENCE         0x04
+#define IB_INIT_TYPE_DO_NOT_RESUSCITATE                0x08
+/*****/
+
+
+/****s* Access Layer/ib_port_attr_mod_t
+* NAME
+*      ib_port_attr_mod_t
+*
+* DESCRIPTION
+*      Port attributes that may be modified.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_port_attr_mod
+{
+       ib_port_cap_t                   cap;
+       uint16_t                                pkey_ctr;
+       uint16_t                                qkey_ctr;
+
+       ib_init_type_t                  init_type;
+       ib_net64_t                              system_image_guid;
+
+}      ib_port_attr_mod_t;
+/*
+* SEE ALSO
+*      ib_port_cap_t
+*****/
+
+
+/****s* Access Layer/ib_port_attr_t
+* NAME
+*      ib_port_attr_t
+*
+* DESCRIPTION
+*      Information about a port on a given channel adapter.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_port_attr
+{
+       ib_net64_t                              port_guid;
+       uint8_t                                 port_num;
+       uint8_t                                 mtu;
+       uint64_t                                max_msg_size;
+       ib_net16_t                              lid;
+       uint8_t                                 lmc;
+
+       /*
+        * LinkWidthSupported as defined in PortInfo.  Required to calculate
+        * inter-packet delay (a.k.a. static rate).
+        */
+       uint8_t                                 link_width_supported;
+
+       uint16_t                                max_vls;
+
+       ib_net16_t                              sm_lid;
+       uint8_t                                 sm_sl;
+       uint8_t                                 link_state;
+
+       ib_init_type_t                  init_type_reply;        /* Optional */
+
+       /*
+        * subnet_timeout:
+        * The maximum expected subnet propagation delay to reach any port on
+        * the subnet.  This value also determines the rate at which traps can
+        * be generated from this node.
+        *
+        * timeout = 4.096 microseconds * 2^subnet_timeout
+        */
+       uint8_t                                 subnet_timeout;
+
+       ib_port_cap_t                   cap;
+       uint16_t                                pkey_ctr;
+       uint16_t                                qkey_ctr;
+
+       uint16_t                                num_gids;
+       uint16_t                                num_pkeys;
+       /*
+        * Pointers at the end of the structure to allow doing a simple
+        * memory comparison of contents up to the first pointer.
+        */
+       ib_gid_t* __ptr64               p_gid_table;
+       ib_net16_t* __ptr64             p_pkey_table;
+
+}      ib_port_attr_t;
+/*
+* SEE ALSO
+*      uint8_t, ib_port_cap_t, ib_link_states_t
+*****/
+
+
+/****s* Access Layer/ib_ca_attr_t
+* NAME
+*      ib_ca_attr_t
+*
+* DESCRIPTION
+*      Information about a channel adapter.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_ca_attr
+{
+       ib_net64_t                              ca_guid;
+
+       uint32_t                                vend_id;
+       uint16_t                                dev_id;
+       uint16_t                                revision;
+
+       /*
+        * Total size of the ca attributes in bytes
+        */
+       uint32_t                                size;
+       uint32_t                                max_qps;
+       uint32_t                                max_wrs;
+
+       uint32_t                                max_sges;
+       uint32_t                                max_rd_sges;
+
+       uint32_t                                max_cqs;
+       uint32_t                                max_cqes;
+
+       uint32_t                                max_pds;
+
+       uint32_t                                init_regions;
+       uint64_t                                init_region_size;
+
+       uint32_t                                init_windows;
+       uint32_t                                max_addr_handles;
+
+       uint32_t                                max_partitions;
+
+       ib_atomic_t                             atomicity;
+
+       uint8_t                                 max_qp_resp_res;
+       uint8_t                                 max_resp_res;
+
+       uint8_t                                 max_qp_init_depth;
+
+       uint32_t                                max_ipv6_qps;
+       uint32_t                                max_ether_qps;
+
+       uint32_t                                max_mcast_grps;
+       uint32_t                                max_mcast_qps;
+       uint32_t                                max_qps_per_mcast_grp;
+
+       /*
+        * local_ack_delay:
+        * Specifies the maximum time interval between the local CA receiving
+        * a message and the transmission of the associated ACK or NAK.
+        *
+        * timeout = 4.096 microseconds * 2^local_ack_delay
+        */
+       uint8_t                                 local_ack_delay;
+
+       boolean_t                               bad_pkey_ctr_support;
+       boolean_t                               bad_qkey_ctr_support;
+       boolean_t                               raw_mcast_support;
+       boolean_t                               apm_support;
+       boolean_t                               av_port_check;
+       boolean_t                               change_primary_port;
+       boolean_t                               modify_wr_depth;
+       boolean_t                               current_qp_state_support;
+       boolean_t                               shutdown_port_capability;
+       boolean_t                               init_type_support;
+       boolean_t                               port_active_event_support;
+       boolean_t                               system_image_guid_support;
+       boolean_t                               hw_agents;
+
+       ib_net64_t                              system_image_guid;
+
+       uint32_t                                num_page_sizes;
+       uint8_t                                 num_ports;
+
+       uint32_t* __ptr64               p_page_size;
+       ib_port_attr_t* __ptr64 p_port_attr;
+
+}      ib_ca_attr_t;
+/*
+* FIELDS
+*      ca_guid
+*              GUID for this adapter.
+*
+*      vend_id
+*              IEEE vendor ID for this adapter
+*
+*      dev_id
+*              Device ID of this adapter. (typically from PCI device ID)
+*
+*      revision
+*              Revision ID of this adapter
+*
+*      size
+*              Total size in bytes for the HCA attributes.  This size includes total
+*              size required for all the variable members of the structure.  If a
+*              vendor requires to pass vendor specific fields beyond this structure,
+*              the HCA vendor can choose to report a larger size.  If a vendor is
+*              reporting extended vendor specific features, they should also provide
+*              appropriate access functions to aid with the required interpretation.
+*
+*      max_qps
+*              Maximum number of QP's supported by this HCA.
+*
+*      max_wrs
+*              Maximum number of work requests supported by this HCA.
+*
+*      max_sges
+*              Maximum number of scatter gather elements supported per work request.
+*
+*      max_rd_sges
+*              Maximum number of scatter gather elements supported for READ work
+*              requests for a Reliable Datagram QP.  This value must be zero if RD
+*              service is not supported.
+*
+*      max_cqs
+*              Maximum number of Completion Queues supported.
+*
+*      max_cqes
+*              Maximum number of CQ elements supported per CQ.
+*
+*      max_pds
+*              Maximum number of protection domains supported.
+*
+*      init_regions
+*              Initial number of memory regions supported.  These are only informative
+*              values.  HCA vendors can extended and grow these limits on demand.
+*
+*      init_region_size
+*              Initial limit on the size of the registered memory region.
+*
+*      init_windows
+*              Initial number of window entries supported.
+*
+*      max_addr_handles
+*              Maximum number of address handles supported.
+*
+*      max_partitions
+*              Maximum number of partitions supported.
+*
+*      atomicity
+*              Indicates level of atomic operations supported by this HCA.
+*
+*      max_qp_resp_res
+*              Maximum limit on number of responder resources for incomming RDMA
+*              operations on QPs.
+*
+*      max_resp_res
+*              Maximum number of responder resources per HCA, with this HCA used as
+*              the target.
+*
+*      max_qp_init_depth
+*              Maximimum initiator depth per QP for initiating RDMA reads and
+*              atomic operations.
+*
+*      max_ipv6_qps
+*      max_ether_qps
+*              Maximum number of IPV6 and raw ether QP's supported by this HCA.
+*
+*      max_mcast_grps
+*              Maximum number of multicast groups supported.
+*
+*      max_mcast_qps
+*              Maximum number of QP's that can support multicast operations.
+*
+*      max_qps_per_mcast_grp
+*              Maximum number of multicast QP's per multicast group.
+*
+*      local_ack_delay
+*              Specifies the maximum time interval between the local CA receiving
+*              a message and the transmission of the associated ACK or NAK.
+*              timeout = 4.096 microseconds * 2^local_ack_delay
+*
+*      bad_pkey_ctr_support
+*      bad_qkey_ctr_support
+*              Indicates support for the bad pkey and qkey counters.
+*
+*      raw_mcast_support
+*              Indicates support for raw packet multicast.
+*
+*      apm_support
+*              Indicates support for Automatic Path Migration.
+*
+*      av_port_check
+*              Indicates ability to check port number in address handles.
+*
+*      change_primary_port
+*              Indicates ability to change primary port for a QP during a
+*              SQD->RTS transition.
+*
+*      modify_wr_depth
+*              Indicates ability to modify QP depth during a modify QP operation.
+*              Check the verb specification for permitted states.
+*
+*      current_qp_state_support
+*              Indicates ability of the HCA to support the current QP state modifier
+*              during a modify QP operation.
+*
+*      shutdown_port_capability
+*              Shutdown port capability support indicator.
+*
+*      init_type_support
+*              Indicates init_type_reply and ability to set init_type is supported.
+*
+*      port_active_event_support
+*              Port active event support indicator.
+*
+*      system_image_guid_support
+*              System image GUID support indicator.
+*
+*      hw_agents
+*              Indicates SMA is implemented in HW.
+*
+*      system_image_guid
+*              Optional system image GUID.  This field is valid only if the
+*              system_image_guid_support flag is set.
+*
+*      num_page_sizes
+*              Indicates support for different page sizes supported by the HCA.
+*              The variable size array can be obtained from p_page_size.
+*
+*      num_ports
+*              Number of physical ports supported on this HCA.
+*
+*      p_page_size
+*              Array holding different page size supported.
+*
+*      p_port_attr
+*              Array holding port attributes.
+*
+* NOTES
+*      This structure contains the attributes of a channel adapter.  Users must
+*      call ib_copy_ca_attr to copy the contents of this structure to a new
+*      memory region.
+*
+* SEE ALSO
+*      ib_port_attr_t, ib_atomic_t, ib_copy_ca_attr
+*****/
+
+/****f* Access layer/ib_copy_ca_attr
+* NAME
+*      ib_copy_ca_attr
+*
+* DESCRIPTION
+*      Copies CA attributes.
+*
+* SYNOPSIS
+*/
+AL_EXPORT ib_ca_attr_t* AL_API
+ib_copy_ca_attr(
+       IN                              ib_ca_attr_t* const             p_dest,
+       IN              const   ib_ca_attr_t* const             p_src );
+/*
+* PARAMETERS
+*      p_dest
+*              Pointer to the buffer that is the destination of the copy.
+*
+*      p_src
+*              Pointer to the CA attributes to copy.
+*
+* RETURN VALUE
+*      Pointer to the copied CA attributes.
+*
+* NOTES
+*      The buffer pointed to by the p_dest parameter must be at least the size
+*      specified in the size field of the buffer pointed to by p_src.
+*
+* SEE ALSO
+*      ib_ca_attr_t, ib_dup_ca_attr, ib_free_ca_attr
+*****/
+
+
+/****d* Access Layer/ib_pd_type_t
+* NAME
+*      ib_pd_type_t
+*
+* DESCRIPTION
+*      Indicates the type of protection domain being allocated.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_pd_type
+{
+       IB_PDT_NORMAL,
+       IB_PDT_ALIAS,
+       IB_PDT_SQP
+
+}      ib_pd_type_t;
+/*
+* VALUES
+*      IB_PDT_NORMAL
+*              Protection domain for all non-aliased QPs.
+*
+*      IB_PDT_ALIAS
+*              Protection domain for IB_QPT_QP0_ALIAS and IB_QPT_QP1_ALIAS QPs.
+*
+*      IB_PDT_SQP
+*              Protection domain for special queue pair usage.
+*****/
+
+
+/****s* Access Layer/ib_av_attr_t
+* NAME
+*      ib_av_attr_t
+*
+* DESCRIPTION
+*      IBA address vector.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_av_attr
+{
+       uint8_t                                 port_num;
+
+       uint8_t                                 sl;
+       ib_net16_t                              dlid;
+
+       boolean_t                               grh_valid;
+       ib_grh_t                                grh;
+       uint8_t                                 static_rate;
+       uint8_t                                 path_bits;
+
+       struct _av_conn
+       {
+               uint8_t                         path_mtu;
+               uint8_t                         local_ack_timeout;
+               uint8_t                         seq_err_retry_cnt;
+               uint8_t                         rnr_retry_cnt;
+
+       }       conn;
+
+}      ib_av_attr_t;
+/*
+* SEE ALSO
+*      ib_gid_t
+*****/
+
+
+/****d* Access Layer/ib_qp_type_t
+* NAME
+*      ib_qp_type_t
+*
+* DESCRIPTION
+*      Indicates the type of queue pair being created.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_qp_type
+{
+       IB_QPT_RELIABLE_CONN    = 0,            /* Matches CM REQ transport type */
+       IB_QPT_UNRELIABLE_CONN  = 1,            /* Matches CM REQ transport type */
+       IB_QPT_UNRELIABLE_DGRM  = 3,            /* Purposefully skip RDD type. */
+       IB_QPT_QP0,
+       IB_QPT_QP1,
+       IB_QPT_RAW_IPV6,
+       IB_QPT_RAW_ETHER,
+       IB_QPT_MAD,                                                             /* InfiniBand Access Layer */
+       IB_QPT_QP0_ALIAS,                                               /* InfiniBand Access Layer */
+       IB_QPT_QP1_ALIAS                                                /* InfiniBand Access Layer */
+
+}      ib_qp_type_t;
+/*
+* VALUES
+*      IB_QPT_RELIABLE_CONN
+*              Reliable, connected queue pair.
+*
+*      IB_QPT_UNRELIABLE_CONN
+*              Unreliable, connected queue pair.
+*
+*      IB_QPT_UNRELIABLE_DGRM
+*              Unreliable, datagram queue pair.
+*
+*      IB_QPT_QP0
+*              Queue pair 0.
+*
+*      IB_QPT_QP1
+*              Queue pair 1.
+*
+*      IB_QPT_RAW_DGRM
+*              Raw datagram queue pair.
+*
+*      IB_QPT_RAW_IPV6
+*              Raw IP version 6 queue pair.
+*
+*      IB_QPT_RAW_ETHER
+*              Raw Ethernet queue pair.
+*
+*      IB_QPT_MAD
+*              Unreliable, datagram queue pair that will send and receive management
+*              datagrams with assistance from the access layer.
+*
+*      IB_QPT_QP0_ALIAS
+*              Alias to queue pair 0.  Aliased QPs can only be created on an aliased
+*              protection domain.
+*
+*      IB_QPT_QP1_ALIAS
+*              Alias to queue pair 1.  Aliased QPs can only be created on an aliased
+*              protection domain.
+*****/
+
+
+/****d* Access Layer/ib_access_t
+* NAME
+*      ib_access_t
+*
+* DESCRIPTION
+*      Indicates the type of access is permitted on resources such as QPs,
+*      memory regions and memory windows.
+*
+* SYNOPSIS
+*/
+typedef uint32_t                               ib_access_t;
+#define IB_AC_RDMA_READ                        0x00000001
+#define IB_AC_RDMA_WRITE               0x00000002
+#define IB_AC_ATOMIC                   0x00000004
+#define IB_AC_LOCAL_WRITE              0x00000008
+#define IB_AC_MW_BIND                  0x00000010
+/*
+* NOTES
+*      Users may combine access rights using a bit-wise or operation to specify
+*      additional access.  For example: IB_AC_RDMA_READ | IB_AC_RDMA_WRITE grants
+*      RDMA read and write access.
+*****/
+
+
+/****d* Access Layer/ib_qp_state_t
+* NAME
+*      ib_qp_state_t
+*
+* DESCRIPTION
+*      Indicates or sets the state of a queue pair.  The current state of a queue
+*      pair is returned through the ib_qp_query call and set via the
+*      ib_qp_modify call.
+*
+* SYNOPSIS
+*/
+typedef uint32_t                               ib_qp_state_t;
+#define IB_QPS_RESET                   0x00000001
+#define IB_QPS_INIT                            0x00000002
+#define IB_QPS_RTR                             0x00000004
+#define IB_QPS_RTS                             0x00000008
+#define IB_QPS_SQD                             0x00000010
+#define IB_QPS_SQD_DRAINING            0x00000030
+#define IB_QPS_SQD_DRAINED             0x00000050
+#define IB_QPS_SQERR                   0x00000080
+#define IB_QPS_ERROR                   0x00000100
+#define IB_QPS_TIME_WAIT               0xDEAD0000      /* InfiniBand Access Layer */
+/*****/
+
+
+/****d* Access Layer/ib_apm_state_t
+* NAME
+*      ib_apm_state_t
+*
+* DESCRIPTION
+*      The current automatic path migration state of a queue pair
+*
+* SYNOPSIS
+*/
+typedef enum _ib_apm_state
+{
+       IB_APM_MIGRATED = 1,
+       IB_APM_REARM,
+       IB_APM_ARMED
+
+}      ib_apm_state_t;
+/*****/
+
+
+/****s* Access Layer/ib_qp_create_t
+* NAME
+*      ib_qp_create_t
+*
+* DESCRIPTION
+*      Attributes used to initialize a queue pair at creation time.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_qp_create
+{
+       ib_qp_type_t                    qp_type;
+
+       uint32_t                                sq_depth;
+       uint32_t                                rq_depth;
+       uint32_t                                sq_sge;
+       uint32_t                                rq_sge;
+
+       ib_cq_handle_t                  h_sq_cq;
+       ib_cq_handle_t                  h_rq_cq;
+
+       boolean_t                               sq_signaled;
+
+}      ib_qp_create_t;
+/*
+* FIELDS
+*      type
+*              Specifies the type of queue pair to create.
+*
+*      sq_depth
+*              Indicates the requested maximum number of work requests that may be
+*              outstanding on the queue pair's send queue.  This value must be less
+*              than or equal to the maximum reported by the channel adapter associated
+*              with the queue pair.
+*
+*      rq_depth
+*              Indicates the requested maximum number of work requests that may be
+*              outstanding on the queue pair's receive queue.  This value must be less
+*              than or equal to the maximum reported by the channel adapter associated
+*              with the queue pair.
+*
+*      sq_sge
+*              Indicates the maximum number scatter-gather elements that may be
+*              given in a send work request.  This value must be less
+*              than or equal to the maximum reported by the channel adapter associated
+*              with the queue pair.
+*
+*      rq_sge
+*              Indicates the maximum number scatter-gather elements that may be
+*              given in a receive work request.  This value must be less
+*              than or equal to the maximum reported by the channel adapter associated
+*              with the queue pair.
+*
+*      h_sq_cq
+*              A handle to the completion queue that will be used to report send work
+*              request completions.  This handle must be NULL if the type is
+*              IB_QPT_MAD, IB_QPT_QP0_ALIAS, or IB_QPT_QP1_ALIAS.
+*
+*      h_rq_cq
+*              A handle to the completion queue that will be used to report receive
+*              work request completions.  This handle must be NULL if the type is
+*              IB_QPT_MAD, IB_QPT_QP0_ALIAS, or IB_QPT_QP1_ALIAS.
+*
+*      sq_signaled
+*              A flag that is used to indicate whether the queue pair will signal
+*              an event upon completion of a send work request.  If set to
+*              TRUE, send work requests will always generate a completion
+*              event.  If set to FALSE, a completion event will only be
+*              generated if the send_opt field of the send work request has the
+*              IB_SEND_OPT_SIGNALED flag set.
+*
+* SEE ALSO
+*      ib_qp_type_t, ib_qp_attr_t
+*****/
+
+
+/****s* Access Layer/ib_qp_attr_t
+* NAME
+*      ib_qp_attr_t
+*
+* DESCRIPTION
+*      Queue pair attributes returned through ib_query_qp.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_qp_attr
+{
+       ib_pd_handle_t                  h_pd;
+       ib_qp_type_t                    qp_type;
+       ib_access_t                             access_ctrl;
+       uint16_t                                pkey_index;
+
+       uint32_t                                sq_max_inline;
+       uint32_t                                sq_depth;
+       uint32_t                                rq_depth;
+       uint32_t                                sq_sge;
+       uint32_t                                rq_sge;
+       uint8_t                                 init_depth;
+       uint8_t                                 resp_res;
+
+       ib_cq_handle_t                  h_sq_cq;
+       ib_cq_handle_t                  h_rq_cq;
+
+       boolean_t                               sq_signaled;
+
+       ib_qp_state_t                   state;
+       ib_net32_t                              num;
+       ib_net32_t                              dest_num;
+       ib_net32_t                              qkey;
+
+       ib_net32_t                              sq_psn;
+       ib_net32_t                              rq_psn;
+
+       uint8_t                                 primary_port;
+       uint8_t                                 alternate_port;
+       ib_av_attr_t                    primary_av;
+       ib_av_attr_t                    alternate_av;
+       ib_apm_state_t                  apm_state;
+
+}      ib_qp_attr_t;
+/*
+* FIELDS
+*      h_pd
+*              This is a handle to a protection domain associated with the QP.
+*
+*      sq_max_inline
+*              Maximum payload that can be inlined directly in a WQE, eliminating
+*              protection checks and additional DMA operations.
+*
+* NOTES
+*      Other fields are defined by the Infiniband specification.
+*
+* SEE ALSO
+*      ib_qp_type_t, ib_access_t, ib_qp_state_t, ib_av_attr_t, ib_apm_state_t
+*****/
+
+
+/****d* Access Layer/ib_qp_opts_t
+* NAME
+*      ib_qp_opts_t
+*
+* DESCRIPTION
+*      Optional fields supplied in the modify QP operation.
+*
+* SYNOPSIS
+*/
+typedef uint32_t                               ib_qp_opts_t;
+#define IB_MOD_QP_ALTERNATE_AV         0x00000001
+#define IB_MOD_QP_PKEY                         0x00000002
+#define IB_MOD_QP_APM_STATE                    0x00000004
+#define IB_MOD_QP_PRIMARY_AV           0x00000008
+#define IB_MOD_QP_RNR_NAK_TIMEOUT      0x00000010
+#define IB_MOD_QP_RESP_RES                     0x00000020
+#define IB_MOD_QP_INIT_DEPTH           0x00000040
+#define IB_MOD_QP_PRIMARY_PORT         0x00000080
+#define IB_MOD_QP_ACCESS_CTRL          0x00000100
+#define IB_MOD_QP_QKEY                         0x00000200
+#define IB_MOD_QP_SQ_DEPTH                     0x00000400
+#define IB_MOD_QP_RQ_DEPTH                     0x00000800
+#define IB_MOD_QP_CURRENT_STATE                0x00001000
+#define IB_MOD_QP_RETRY_CNT                    0x00002000
+#define IB_MOD_QP_LOCAL_ACK_TIMEOUT    0x00004000
+#define IB_MOD_QP_RNR_RETRY_CNT                0x00008000
+
+/*
+* SEE ALSO
+*      ib_qp_mod_t
+*****/
+
+
+/****s* Access Layer/ib_qp_mod_t
+* NAME
+*      ib_qp_mod_t
+*
+* DESCRIPTION
+*      Information needed to change the state of a queue pair through the
+*      ib_modify_qp call.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_qp_mod
+{
+       ib_qp_state_t                           req_state;
+
+       union _qp_state
+       {
+               struct _qp_init
+               {
+                       ib_qp_opts_t            opts;
+                       uint8_t                         primary_port;
+                       ib_net32_t                      qkey;
+                       uint16_t                        pkey_index;
+                       ib_access_t                     access_ctrl;
+
+               }       init;
+
+               struct _qp_rtr
+               {
+                       ib_net32_t                      rq_psn;
+                       ib_net32_t                      dest_qp;
+                       ib_av_attr_t            primary_av;
+                       uint8_t                         resp_res;
+                       uint8_t                         rnr_nak_timeout;
+
+                       ib_qp_opts_t            opts;
+                       ib_av_attr_t            alternate_av;
+                       ib_net32_t                      qkey;
+                       uint16_t                        pkey_index;
+                       ib_access_t                     access_ctrl;
+                       uint32_t                        sq_depth;
+                       uint32_t                        rq_depth;
+
+               }       rtr;
+
+               struct _qp_rts
+               {
+                       ib_net32_t                      sq_psn;
+                       uint8_t                         retry_cnt;
+                       uint8_t                         rnr_retry_cnt;
+                       uint8_t                         local_ack_timeout;
+                       uint8_t                         init_depth;
+
+                       ib_qp_opts_t            opts;
+                       uint8_t                         rnr_nak_timeout;
+                       ib_qp_state_t           current_state;
+                       ib_net32_t                      qkey;
+                       ib_access_t                     access_ctrl;
+                       uint8_t                         resp_res;
+
+                       ib_av_attr_t            primary_av;
+                       ib_av_attr_t            alternate_av;
+
+                       uint32_t                        sq_depth;
+                       uint32_t                        rq_depth;
+
+                       ib_apm_state_t          apm_state;
+                       uint8_t                         primary_port;
+                       uint16_t                        pkey_index;
+
+               }       rts;
+
+               struct _qp_sqd
+               {
+                       boolean_t                       sqd_event;
+
+               }       sqd;
+
+       }       state;
+
+}      ib_qp_mod_t;
+/*
+* SEE ALSO
+*      ib_qp_state_t, ib_access_t, ib_av_attr_t, ib_apm_state_t
+*****/
+
+
+/****d* Access Layer/ib_wr_type_t
+* NAME
+*      ib_wr_type_t
+*
+* DESCRIPTION
+*      Identifies the type of work request posted to a queue pair.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_wr_type_t
+{
+       WR_SEND = 1,
+       WR_RDMA_WRITE,
+       WR_RDMA_READ,
+       WR_COMPARE_SWAP,
+       WR_FETCH_ADD
+
+}      ib_wr_type_t;
+/*****/
+
+
+/****s* Access Layer/ib_local_ds_t
+* NAME
+*      ib_local_ds_t
+*
+* DESCRIPTION
+*      Local data segment information referenced by send and receive work
+*      requests.  This is used to specify local data buffers used as part of a
+*      work request.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_local_ds
+{
+       uint64_t                                vaddr;
+       uint32_t                                length;
+       uint32_t                                lkey;
+
+}      ib_local_ds_t;
+/*****/
+
+
+/****d* Access Layer/ib_send_opt_t
+* NAME
+*      ib_send_opt_t
+*
+* DESCRIPTION
+*      Optional flags used when posting send work requests.  These flags
+*      indicate specific processing for the send operation.
+*
+* SYNOPSIS
+*/
+typedef uint32_t                                       ib_send_opt_t;
+#define IB_SEND_OPT_IMMEDIATE          0x00000001
+#define IB_SEND_OPT_FENCE                      0x00000002
+#define IB_SEND_OPT_SIGNALED           0x00000004
+#define IB_SEND_OPT_SOLICITED          0x00000008
+#define IB_SEND_OPT_INLINE                     0x00000010
+#define IB_SEND_OPT_LOCAL                      0x00000020
+#define IB_SEND_OPT_VEND_MASK          0xFFFF0000
+/*
+* VALUES
+*      The following flags determine the behavior of a work request when
+*      posted to the send side.
+*
+*      IB_SEND_OPT_IMMEDIATE
+*              Send immediate data with the given request.
+*
+*      IB_SEND_OPT_FENCE
+*              The operation is fenced.  Complete all pending send operations before
+*              processing this request.
+*
+*      IB_SEND_OPT_SIGNALED
+*              If the queue pair is configured for signaled completion, then
+*              generate a completion queue entry when this request completes.
+*
+*      IB_SEND_OPT_SOLICITED
+*              Set the solicited bit on the last packet of this request.
+*
+*      IB_SEND_OPT_INLINE
+*              Indicates that the requested send data should be copied into a VPD
+*              owned data buffer.  This flag permits the user to issue send operations
+*              without first needing to register the buffer(s) associated with the
+*              send operation.  Verb providers that support this operation may place
+*              vendor specific restrictions on the size of send operation that may
+*              be performed as inline.
+*
+*      IB_SEND_OPT_LOCAL
+*              Indicates that a sent MAD request should be given to the local VPD for
+*              processing.  MADs sent using this option are not placed on the wire.
+*              This send option is only valid for MAD send operations.
+*
+*      IB_SEND_OPT_VEND_MASK
+*              This mask indicates bits reserved in the send options that may be used
+*              by the verbs provider to indicate vendor specific options.  Bits set
+*              in this area of the send options are ignored by the Access Layer, but
+*              may have specific meaning to the underlying VPD.
+*
+*****/
+
+
+/****s* Access Layer/ib_send_wr_t
+* NAME
+*      ib_send_wr_t
+*
+* DESCRIPTION
+*      Information used to submit a work request to the send queue of a queue
+*      pair.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_send_wr
+{
+       struct _ib_send_wr* __ptr64     p_next;
+       uint64_t                                        wr_id;
+       ib_wr_type_t                            wr_type;
+       ib_send_opt_t                           send_opt;
+       uint32_t                                        num_ds;
+       ib_local_ds_t* __ptr64          ds_array;
+       ib_net32_t                                      immediate_data;
+
+       union _send_dgrm
+       {
+               struct _send_ud
+               {
+                       ib_net32_t              remote_qp;
+                       ib_net32_t              remote_qkey;
+                       ib_av_handle_t  h_av;
+                       uint16_t                pkey_index;
+                       void* __ptr64   rsvd;
+
+               }       ud;
+
+               struct _send_raw_ether
+               {
+                       ib_net16_t              dest_lid;
+                       uint8_t                 path_bits;
+                       uint8_t                 sl;
+                       uint8_t                 max_static_rate;
+                       ib_net16_t              ether_type;
+
+               }       raw_ether;
+
+               struct _send_raw_ipv6
+               {
+                       ib_net16_t              dest_lid;
+                       uint8_t                 path_bits;
+                       uint8_t                 sl;
+                       uint8_t                 max_static_rate;
+
+               }       raw_ipv6;
+
+       }       dgrm;
+
+       struct _send_remote_ops
+       {
+               uint64_t                        vaddr;
+               net32_t                         rkey;
+
+               ib_net64_t                      atomic1;
+               ib_net64_t                      atomic2;
+
+       }       remote_ops;
+
+}      ib_send_wr_t;
+/*
+* FIELDS
+*      p_next
+*              A pointer used to chain work requests together.  This permits multiple
+*              work requests to be posted to a queue pair through a single function
+*              call.  This value is set to NULL to mark the end of the chain.
+*
+*      wr_id
+*              A 64-bit work request identifier that is returned to the consumer
+*              as part of the work completion.
+*
+*      wr_type
+*              The type of work request being submitted to the send queue.
+*
+*      send_opt
+*              Optional send control parameters.
+*
+*      num_ds
+*              Number of local data segments specified by this work request.
+*
+*      ds_array
+*              A reference to an array of local data segments used by the send
+*              operation.
+*
+*      immediate_data
+*              32-bit field sent as part of a message send or RDMA write operation.
+*              This field is only valid if the send_opt flag IB_SEND_OPT_IMMEDIATE
+*              has been set.
+*
+*      dgrm.ud.remote_qp
+*              Identifies the destination queue pair of an unreliable datagram send
+*              operation.
+*
+*      dgrm.ud.remote_qkey
+*              The qkey for the destination queue pair.
+*
+*      dgrm.ud.h_av
+*              An address vector that specifies the path information used to route
+*              the outbound datagram to the destination queue pair.
+*
+*      dgrm.ud.pkey_index
+*              The pkey index for this send work request.  This is valid only
+*              for IB_QPT_QP1 and IB_QPT_QP1_ALIAS QP types.  The work request
+*              is posted to using this pkey index build the GMP's BTH instead
+*              of the QP's pkey.
+*
+*      dgrm.ud.rsvd
+*              Reserved for use by the Access Layer.
+*
+*      dgrm.raw_ether.dest_lid
+*              The destination LID that will receive this raw ether send.
+*
+*      dgrm.raw_ether.path_bits
+*              path bits...
+*
+*      dgrm.raw_ether.sl
+*              service level...
+*
+*      dgrm.raw_ether.max_static_rate
+*              static rate...
+*
+*      dgrm.raw_ether.ether_type
+*              ether type...
+*
+*      dgrm.raw_ipv6.dest_lid
+*              The destination LID that will receive this raw ether send.
+*
+*      dgrm.raw_ipv6.path_bits
+*              path bits...
+*
+*      dgrm.raw_ipv6.sl
+*              service level...
+*
+*      dgrm.raw_ipv6.max_static_rate
+*              static rate...
+*
+*      remote_ops.vaddr
+*              The registered virtual memory address of the remote memory to access
+*              with an RDMA or atomic operation.
+*
+*      remote_ops.rkey
+*              The rkey associated with the specified remote vaddr. This data must
+*              be presented exactly as obtained from the remote node. No swapping
+*              of data must be performed.
+*
+*      atomic1
+*              The first operand for an atomic operation.
+*
+*      atomic2
+*              The second operand for an atomic operation.
+*
+* NOTES
+*      The format of data sent over the fabric is user-defined and is considered
+*      opaque to the access layer.  The sole exception to this are MADs posted
+*      to a MAD QP service.  MADs are expected to match the format defined by
+*      the Infiniband specification and must be in network-byte order when posted
+*      to the MAD QP service.
+*
+* SEE ALSO
+*      ib_wr_type_t, ib_local_ds_t, ib_send_opt_t
+*****/
+
+
+/****s* Access Layer/ib_recv_wr_t
+* NAME
+*      ib_recv_wr_t
+*
+* DESCRIPTION
+*      Information used to submit a work request to the receive queue of a queue
+*      pair.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_recv_wr
+{
+       struct _ib_recv_wr* __ptr64     p_next;
+       uint64_t                                        wr_id;
+       uint32_t                                        num_ds;
+       ib_local_ds_t* __ptr64          ds_array;
+
+}      ib_recv_wr_t;
+/*
+* FIELDS
+*      p_next
+*              A pointer used to chain work requests together.  This permits multiple
+*              work requests to be posted to a queue pair through a single function
+*              call.  This value is set to NULL to mark the end of the chain.
+*
+*      wr_id
+*              A 64-bit work request identifier that is returned to the consumer
+*              as part of the work completion.
+*
+*      num_ds
+*              Number of local data segments specified by this work request.
+*
+*      ds_array
+*              A reference to an array of local data segments used by the send
+*              operation.
+*
+* SEE ALSO
+*      ib_local_ds_t
+*****/
+
+
+/****s* Access Layer/ib_bind_wr_t
+* NAME
+*      ib_bind_wr_t
+*
+* DESCRIPTION
+*      Information used to submit a memory window bind work request to the send
+*      queue of a queue pair.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_bind_wr
+{
+       uint64_t                                wr_id;
+       ib_send_opt_t                   send_opt;
+
+       ib_mr_handle_t                  h_mr;
+       ib_access_t                             access_ctrl;
+       net32_t                                 current_rkey;
+
+       ib_local_ds_t                   local_ds;
+
+}      ib_bind_wr_t;
+/*
+* FIELDS
+*      wr_id
+*              A 64-bit work request identifier that is returned to the consumer
+*              as part of the work completion.
+*
+*      send_opt
+*              Optional send control parameters.
+*
+*      h_mr
+*              Handle to the memory region to which this window is being bound.
+*
+*      access_ctrl
+*              Access rights for this memory window.
+*
+*      current_rkey
+*              The current rkey assigned to this window for remote access.
+*
+*      local_ds
+*              A reference to a local data segment used by the bind operation.
+*
+* SEE ALSO
+*      ib_send_opt_t, ib_access_t, ib_local_ds_t
+*****/
+
+
+/****d* Access Layer/ib_wc_status_t
+* NAME
+*      ib_wc_status_t
+*
+* DESCRIPTION
+*      Indicates the status of a completed work request.  These VALUES are
+*      returned to the user when retrieving completions.  Note that success is
+*      identified as IB_WCS_SUCCESS, which is always zero.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_wc_status_t
+{
+       IB_WCS_SUCCESS,
+       IB_WCS_LOCAL_LEN_ERR,
+       IB_WCS_LOCAL_OP_ERR,
+       IB_WCS_LOCAL_PROTECTION_ERR,
+       IB_WCS_WR_FLUSHED_ERR,
+       IB_WCS_MEM_WINDOW_BIND_ERR,
+       IB_WCS_REM_ACCESS_ERR,
+       IB_WCS_REM_OP_ERR,
+       IB_WCS_RNR_RETRY_ERR,
+       IB_WCS_TIMEOUT_RETRY_ERR,
+       IB_WCS_REM_INVALID_REQ_ERR,
+       IB_WCS_UNMATCHED_RESPONSE,                      /* InfiniBand Access Layer */
+       IB_WCS_CANCELED,                                        /* InfiniBand Access Layer */
+       IB_WCS_UNKNOWN                                          /* Must be last. */
+
+}      ib_wc_status_t;
+/*
+* VALUES
+*      IB_WCS_SUCCESS
+*              Work request completed successfully.
+*
+*      IB_WCS_MAD
+*              The completed work request was associated with a managmenet datagram
+*              that requires post processing.  The MAD will be returned to the user
+*              through a callback once all post processing has completed.
+*
+*      IB_WCS_LOCAL_LEN_ERR
+*              Generated for a work request posted to the send queue when the
+*              total of the data segment lengths exceeds the message length of the
+*              channel.  Generated for a work request posted to the receive queue when
+*              the total of the data segment lengths is too small for a
+*              valid incoming message.
+*
+*      IB_WCS_LOCAL_OP_ERR
+*              An internal QP consistency error was generated while processing this
+*              work request.  This may indicate that the QP was in an incorrect state
+*              for the requested operation.
+*
+*      IB_WCS_LOCAL_PROTECTION_ERR
+*              The data segments of the locally posted work request did not refer to
+*              a valid memory region.  The memory may not have been properly
+*              registered for the requested operation.
+*
+*      IB_WCS_WR_FLUSHED_ERR
+*              The work request was flushed from the QP before being completed.
+*
+*      IB_WCS_MEM_WINDOW_BIND_ERR
+*              A memory window bind operation failed due to insufficient access
+*              rights.
+*
+*      IB_WCS_REM_ACCESS_ERR,
+*              A protection error was detected at the remote node for a RDMA or atomic
+*              operation.
+*
+*      IB_WCS_REM_OP_ERR,
+*              The operation could not be successfully completed at the remote node.
+*              This may indicate that the remote QP was in an invalid state or
+*              contained an invalid work request.
+*
+*      IB_WCS_RNR_RETRY_ERR,
+*              The RNR retry count was exceeded while trying to send this message.
+*
+*      IB_WCS_TIMEOUT_RETRY_ERR
+*              The local transport timeout counter expired while trying to send this
+*              message.
+*
+*      IB_WCS_REM_INVALID_REQ_ERR,
+*              The remote node detected an invalid message on the channel.  This error
+*              is usually a result of one of the following:
+*                      - The operation was not supported on receive queue.
+*                      - There was insufficient buffers to receive a new RDMA request.
+*                      - There was insufficient buffers to receive a new atomic operation.
+*                      - An RDMA request was larger than 2^31 bytes.
+*
+*      IB_WCS_UNMATCHED_RESPONSE
+*              A response MAD was received for which there was no matching send.  The
+*              send operation may have been canceled by the user or may have timed
+*              out.
+*
+*      IB_WCS_CANCELED
+*              The completed work request was canceled by the user.
+*****/
+
+
+
+/****f* IBA Base: Types/ib_get_wc_status_str
+* NAME
+*      ib_get_wc_status_str
+*
+* DESCRIPTION
+*      Returns a string for the specified work completion status.
+*
+* SYNOPSIS
+*/
+AL_EXPORT const char* AL_API
+ib_get_wc_status_str(
+       IN                              ib_wc_status_t                          wc_status );
+/*
+* PARAMETERS
+*      wc_status
+*              [in] work completion status value
+*
+* RETURN VALUES
+*      Pointer to the work completion status description string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+/****d* Access Layer/ib_wc_type_t
+* NAME
+*      ib_wc_type_t
+*
+* DESCRIPTION
+*      Indicates the type of work completion.
+*
+* SYNOPSIS
+*/
+typedef enum _ib_wc_type_t
+{
+       IB_WC_SEND,
+       IB_WC_RDMA_WRITE,
+       IB_WC_RECV,
+       IB_WC_RDMA_READ,
+       IB_WC_MW_BIND,
+       IB_WC_FETCH_ADD,
+       IB_WC_COMPARE_SWAP,
+       IB_WC_RECV_RDMA_WRITE,
+       IB_WC_UNKNOWN
+
+}      ib_wc_type_t;
+/*****/
+
+
+/****f* IBA Base: Types/ib_get_wc_type_str
+* NAME
+*      ib_get_wc_type_str
+*
+* DESCRIPTION
+*      Returns a string for the specified work completion type.
+*
+* SYNOPSIS
+*/
+AL_EXPORT const char* AL_API
+ib_get_wc_type_str(
+       IN                              ib_wc_type_t                            wc_type );
+/*
+* PARAMETERS
+*      wc_type
+*              [in] work completion type value
+*
+* RETURN VALUES
+*      Pointer to the work completion type description string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+
+/****d* Access Layer/ib_recv_opt_t
+* NAME
+*      ib_recv_opt_t
+*
+* DESCRIPTION
+*      Indicates optional fields valid in a receive work completion.
+*
+* SYNOPSIS
+*/
+typedef uint32_t                                       ib_recv_opt_t;
+#define        IB_RECV_OPT_IMMEDIATE           0x00000001
+#define IB_RECV_OPT_FORWARD                    0x00000002
+#define IB_RECV_OPT_GRH_VALID          0x00000004
+#define IB_RECV_OPT_VEND_MASK          0xFFFF0000
+/*
+* VALUES
+*      IB_RECV_OPT_IMMEDIATE
+*              Indicates that immediate data is valid for this work completion.
+*
+*      IB_RECV_OPT_FORWARD
+*              Indicates that the received trap should be forwarded to the SM.
+*
+*      IB_RECV_OPT_GRH_VALID
+*              Indicates presence of the global route header. When set, the first
+*              40 bytes received are the GRH.
+*
+*      IB_RECV_OPT_VEND_MASK
+*              This mask indicates bits reserved in the receive options that may be
+*              used by the verbs provider to indicate vendor specific options.  Bits
+*              set in this area of the receive options are ignored by the Access Layer,
+*              but may have specific meaning to the underlying VPD.
+*****/
+
+
+/****s* Access Layer/ib_wc_t
+* NAME
+*      ib_wc_t
+*
+* DESCRIPTION
+*      Work completion information.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_wc
+{
+       struct _ib_wc* __ptr64  p_next;
+       uint64_t                                wr_id;
+       ib_wc_type_t                    wc_type;
+
+       uint32_t                                length;
+       ib_wc_status_t                  status;
+       uint64_t                                vendor_specific;
+
+       union _wc_recv
+       {
+               struct _wc_conn
+               {
+                       ib_recv_opt_t   recv_opt;
+                       ib_net32_t              immediate_data;
+
+               }       conn;
+
+               struct _wc_ud
+               {
+                       ib_recv_opt_t   recv_opt;
+                       ib_net32_t              immediate_data;
+                       ib_net32_t              remote_qp;
+                       uint16_t                pkey_index;
+                       ib_net16_t              remote_lid;
+                       uint8_t                 remote_sl;
+                       uint8_t                 path_bits;
+
+               }       ud;
+
+               struct _wc_raw_ipv6
+               {
+                       ib_net16_t              remote_lid;
+                       uint8_t                 remote_sl;
+                       uint8_t                 path_bits;
+
+               }       raw_ipv6;
+
+               struct _wc_raw_ether
+               {
+                       ib_net16_t              remote_lid;
+                       uint8_t                 remote_sl;
+                       uint8_t                 path_bits;
+                       ib_net16_t              ether_type;
+
+               }       raw_ether;
+
+       }       recv;
+
+}      ib_wc_t;
+/*
+* FIELDS
+*      p_next
+*              A pointer used to chain work completions.  This permits multiple
+*              work completions to be retrieved from a completion queue through a
+*              single function call.  This value is set to NULL to mark the end of
+*              the chain.
+*
+*      wr_id
+*              The 64-bit work request identifier that was specified when posting the
+*              work request.
+*
+*      wc_type
+*              Indicates the type of work completion.
+*
+*      length
+*              The total length of the data sent or received with the work request.
+*
+*      status
+*              The result of the work request.
+*
+*      vendor_specific
+*              HCA vendor specific information returned as part of the completion.
+*
+*      recv.conn.recv_opt
+*              Indicates optional fields valid as part of a work request that
+*              completed on a connected (reliable or unreliable) queue pair.
+*
+*      recv.conn.immediate_data
+*              32-bit field received as part of an inbound message on a connected
+*              queue pair.  This field is only valid if the recv_opt flag
+*              IB_RECV_OPT_IMMEDIATE has been set.
+*
+*      recv.ud.recv_opt
+*              Indicates optional fields valid as part of a work request that
+*              completed on an unreliable datagram queue pair.
+*
+*      recv.ud.immediate_data
+*              32-bit field received as part of an inbound message on a unreliable
+*              datagram queue pair.  This field is only valid if the recv_opt flag
+*              IB_RECV_OPT_IMMEDIATE has been set.
+*
+*      recv.ud.remote_qp
+*              Identifies the source queue pair of a received datagram.
+*
+*      recv.ud.pkey_index
+*              The pkey index of the source queue pair. This is valid only for
+*              IB_QPT_QP1 and IB_QPT_QP1_ALIAS QP types.
+*
+*      recv.ud.remote_lid
+*              The source LID of the received datagram.
+*
+*      recv.ud.remote_sl
+*              The service level used by the source of the received datagram.
+*
+*      recv.ud.path_bits
+*              path bits...
+*
+*      recv.raw_ipv6.remote_lid
+*              The source LID of the received message.
+*
+*      recv.raw_ipv6.remote_sl
+*              The service level used by the source of the received message.
+*
+*      recv.raw_ipv6.path_bits
+*              path bits...
+*
+*      recv.raw_ether.remote_lid
+*              The source LID of the received message.
+*
+*      recv.raw_ether.remote_sl
+*              The service level used by the source of the received message.
+*
+*      recv.raw_ether.path_bits
+*              path bits...
+*
+*      recv.raw_ether.ether_type
+*              ether type...
+* NOTES
+*      When the work request completes with error, the only values that the
+*      consumer can depend on are the wr_id field, and the status of the
+*      operation.
+*
+*      If the consumer is using the same CQ for completions from more than
+*      one type of QP (i.e Reliable Connected, Datagram etc), then the consumer
+*      must have additional information to decide what fields of the union are
+*      valid.
+* SEE ALSO
+*      ib_wc_type_t, ib_qp_type_t, ib_wc_status_t, ib_recv_opt_t
+*****/
+
+
+/****s* Access Layer/ib_mr_create_t
+* NAME
+*      ib_mr_create_t
+*
+* DESCRIPTION
+*      Information required to create a registered memory region.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_mr_create
+{
+       void* __ptr64                   vaddr;
+       uint64_t                                length;
+       ib_access_t                             access_ctrl;
+
+}      ib_mr_create_t;
+/*
+* FIELDS
+*      vaddr
+*              Starting virtual address of the region being registered.
+*
+*      length
+*              Length of the buffer to register.
+*
+*      access_ctrl
+*              Access rights of the registered region.
+*
+* SEE ALSO
+*      ib_access_t
+*****/
+
+
+/****s* Access Layer/ib_phys_range_t
+* NAME
+*      ib_phys_range_t
+*
+* DESCRIPTION
+*      Information describing a physical memory range.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_phys_range
+{
+       uint64_t                                base_addr;
+       uint64_t                                size;
+
+}      ib_phys_range_t;
+/*
+* FIELDS
+*      base_addr
+*              Physical address of the base of the memory range.
+*
+*      size
+*              size, in bytes, of the memory range.
+*
+* NOTES
+*      The base address must be start and end on an HCA-supported page boundary.
+*
+* SEE ALSO
+*      ib_phys_create_t
+*********/
+
+
+/****s* Access Layer/ib_phys_create_t
+* NAME
+*      ib_phys_create_t
+*
+* DESCRIPTION
+*      Information required to create a physical memory region.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_phys_create
+{
+       uint64_t                                        length;
+       uint32_t                                        num_ranges;
+       ib_phys_range_t* __ptr64        range_array;
+       uint32_t                                        buf_offset;
+       uint32_t                                        hca_page_size;
+       ib_access_t                                     access_ctrl;
+
+}      ib_phys_create_t;
+/*
+* FIELDS
+*      length
+*              The length of the memory region in bytes.
+*
+*      num_ranges
+*              Number of ib_phys_range structures listed in the specified range array.
+*
+*      range_array
+*              An array of ib_phys_range structures to be registered as a single memory
+*              region.
+*
+*      buf_offset
+*              The offset into the first physical memory range of the specified memory
+*              region on which to start the virtual address.
+*
+*      hca_page_size
+*              The HCA page size to use to register the memory.
+*
+*      access_ctrl
+*              Access rights of the registered region.
+*
+* SEE ALSO
+*      ib_access_t
+*****/
+
+
+/****s* Access Layer/ib_mr_attr_t
+* NAME
+*      ib_mr_attr_t
+*
+* DESCRIPTION
+*      Attributes of a registered memory region.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_mr_attr
+{
+       ib_pd_handle_t                  h_pd;
+       uint64_t                                local_lb;
+       uint64_t                                local_ub;
+       uint64_t                                remote_lb;
+       uint64_t                                remote_ub;
+       ib_access_t                             access_ctrl;
+       net32_t                                 lkey;
+       net32_t                                 rkey;
+
+}      ib_mr_attr_t;
+/*
+* DESCRIPTION
+*      h_pd
+*              Handle to the protection domain for this memory region.
+*
+*      local_lb
+*              The virtual address of the lower bound of protection for local
+*              memory access.  This is always a 64-bit quantity to support registering
+*              more than 4GB of memory on 32-bit systems with PAE.
+*
+*      local_ub
+*              The virtual address of the upper bound of protection for local
+*              memory access.  This is always a 64-bit quantity to support registering
+*              more than 4GB of memory on 32-bit systems with PAE.
+*
+*      remote_lb
+*              The virtual address of the lower bound of protection for remote
+*              memory access.  This is always a 64-bit quantity to support registering
+*              more than 4GB of memory on 32-bit systems with PAE.
+*
+*      remote_ub
+*              The virtual address of the upper bound of protection for remote
+*              memory access.  This is always a 64-bit quantity to support registering
+*              more than 4GB of memory on 32-bit systems with PAE.
+*
+*      access_ctrl
+*              Access rights for the specified memory region.
+*
+*      lkey
+*              The lkey associated with this memory region.
+*
+*      rkey
+*              The rkey associated with this memory region.
+*
+* NOTES
+*      The remote_lb, remote_ub, and rkey are only valid if remote memory access
+*      is enabled for this memory region.
+*
+* SEE ALSO
+*      ib_access_t
+*****/
+
+
+/****d* Access Layer/ib_ca_mod_t
+* NAME
+*      ib_ca_mod_t -- Modify port attributes and error counters
+*
+* DESCRIPTION
+*      Specifies modifications to the port attributes of a channel adapter.
+*
+* SYNOPSIS
+*/
+typedef uint32_t                                                       ib_ca_mod_t;
+#define IB_CA_MOD_IS_CM_SUPPORTED                      0x00000001
+#define IB_CA_MOD_IS_SNMP_SUPPORTED                    0x00000002
+#define        IB_CA_MOD_IS_DEV_MGMT_SUPPORTED         0x00000004
+#define        IB_CA_MOD_IS_VEND_SUPPORTED                     0x00000008
+#define        IB_CA_MOD_IS_SM                                         0x00000010
+#define IB_CA_MOD_IS_SM_DISABLED                       0x00000020
+#define IB_CA_MOD_QKEY_CTR                                     0x00000040
+#define IB_CA_MOD_PKEY_CTR                                     0x00000080
+#define IB_CA_MOD_IS_NOTICE_SUPPORTED          0x00000100
+#define IB_CA_MOD_IS_TRAP_SUPPORTED                    0x00000200
+#define IB_CA_MOD_IS_APM_SUPPORTED                     0x00000400
+#define IB_CA_MOD_IS_SLMAP_SUPPORTED           0x00000800
+#define IB_CA_MOD_IS_PKEY_NVRAM_SUPPORTED      0x00001000
+#define IB_CA_MOD_IS_MKEY_NVRAM_SUPPORTED      0x00002000
+#define IB_CA_MOD_IS_SYSGUID_SUPPORTED         0x00004000
+#define IB_CA_MOD_IS_DR_NOTICE_SUPPORTED       0x00008000
+#define IB_CA_MOD_IS_BOOT_MGMT_SUPPORTED       0x00010000
+#define IB_CA_MOD_IS_CAPM_NOTICE_SUPPORTED     0x00020000
+#define IB_CA_MOD_IS_REINIT_SUPORTED           0x00040000
+#define IB_CA_MOD_IS_LEDINFO_SUPPORTED         0x00080000
+#define IB_CA_MOD_SHUTDOWN_PORT                                0x00100000
+#define IB_CA_MOD_INIT_TYPE_VALUE                      0x00200000
+#define IB_CA_MOD_SYSTEM_IMAGE_GUID                    0x00400000
+/*
+* VALUES
+*      IB_CA_MOD_IS_CM_SUPPORTED
+*              Indicates if there is a communication manager accessible through
+*              the port.
+*
+*      IB_CA_MOD_IS_SNMP_SUPPORTED
+*              Indicates if there is an SNMP agent accessible through the port.
+*
+*      IB_CA_MOD_IS_DEV_MGMT_SUPPORTED
+*              Indicates if there is a device management agent accessible through
+*              the port.
+*
+*      IB_CA_MOD_IS_VEND_SUPPORTED
+*              Indicates if there is a vendor supported agent accessible through
+*              the port.
+*
+*      IB_CA_MOD_IS_SM
+*              Indicates if there is a subnet manager accessible through
+*              the port.
+*
+*      IB_CA_MOD_IS_SM_DISABLED
+*              Indicates if the port has been disabled for configuration by the subnet
+*              manager.
+*
+*      IB_CA_MOD_QKEY_CTR
+*              Used to reset the qkey violation counter associated with the port.
+*
+*      IB_CA_MOD_PKEY_CTR
+*              Used to reset the pkey violation counter associated with the port.
+*
+*      IB_CA_MOD_IS_NOTICE_SUPPORTED
+*              Indicates that this CA supports ability to generate Notices for
+*              Port State changes. (only applicable to switches)
+*
+*      IB_CA_MOD_IS_TRAP_SUPPORTED
+*              Indicates that this management port supports ability to generate
+*              trap messages. (only applicable to switches)
+*
+*      IB_CA_MOD_IS_APM_SUPPORTED
+*              Indicates that this port is capable of performing Automatic Migration.
+*
+*      IB_CA_MOD_IS_SLMAP_SUPPORTED
+*              Indicates this port supports SLMAP capability.
+*
+*      IB_CA_MOD_IS_PKEY_NVRAM_SUPPORTED
+*              Indicates that PKEY is supported in NVRAM
+*
+*      IB_CA_MOD_IS_MKEY_NVRAM_SUPPORTED
+*              Indicates that MKEY is supported in NVRAM
+*
+*      IB_CA_MOD_IS_SYSGUID_SUPPORTED
+*              Indicates System Image GUID support.
+*
+*      IB_CA_MOD_IS_DR_NOTICE_SUPPORTED
+*              Indicate support for generating Direct Routed Notices
+*
+*      IB_CA_MOD_IS_BOOT_MGMT_SUPPORTED
+*              Indicates support for Boot Management
+*
+*      IB_CA_MOD_IS_CAPM_NOTICE_SUPPORTED
+*              Indicates capability to generate notices for changes to CAPMASK
+*
+*      IB_CA_MOD_IS_REINIT_SUPORTED
+*              Indicates type of node init supported. Refer to Chapter 14 for
+*              Initialization actions.
+*
+*      IB_CA_MOD_IS_LEDINFO_SUPPORTED
+*              Indicates support for LED info.
+*
+*      IB_CA_MOD_SHUTDOWN_PORT
+*              Used to modify the port active indicator.
+*
+*      IB_CA_MOD_INIT_TYPE_VALUE
+*              Used to modify the init_type value for the port.
+*
+*      IB_CA_MOD_SYSTEM_IMAGE_GUID
+*              Used to modify the system image GUID for the port.
+*****/
+
+
+/****d* Access Layer/ib_mr_mod_t
+* NAME
+*      ib_mr_mod_t
+*
+* DESCRIPTION
+*      Mask used to specify which attributes of a registered memory region are
+*      being modified.
+*
+* SYNOPSIS
+*/
+typedef uint32_t                                               ib_mr_mod_t;
+#define IB_MR_MOD_ADDR                                 0x00000001
+#define IB_MR_MOD_PD                                   0x00000002
+#define IB_MR_MOD_ACCESS                               0x00000004
+/*
+* PARAMETERS
+*      IB_MEM_MOD_ADDR
+*              The address of the memory region is being modified.
+*
+*      IB_MEM_MOD_PD
+*              The protection domain associated with the memory region is being
+*              modified.
+*
+*      IB_MEM_MOD_ACCESS
+*              The access rights the memory region are being modified.
+*****/
+
+/****d* IBA Base: Constants/IB_SMINFO_STATE_INIT
+* NAME
+*      IB_SMINFO_STATE_INIT
+*
+* DESCRIPTION
+*      Encoded state value used in the SMInfo attribute.
+*
+* SOURCE
+*/
+#define IB_SMINFO_STATE_INIT                                   4
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_HANDOVER
+* NAME
+*      IB_SMINFO_ATTR_MOD_HANDOVER
+*
+* DESCRIPTION
+*      Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_HANDOVER            (CL_NTOH32(0x000001))
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_ACKNOWLEDGE
+* NAME
+*      IB_SMINFO_ATTR_MOD_ACKNOWLEDGE
+*
+* DESCRIPTION
+*      Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_ACKNOWLEDGE         (CL_NTOH32(0x000002))
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_DISABLE
+* NAME
+*      IB_SMINFO_ATTR_MOD_DISABLE
+*
+* DESCRIPTION
+*      Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_DISABLE                     (CL_NTOH32(0x000003))
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_STANDBY
+* NAME
+*      IB_SMINFO_ATTR_MOD_STANDBY
+*
+* DESCRIPTION
+*      Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_STANDBY                     (CL_NTOH32(0x000004))
+/**********/
+
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_DISCOVER
+* NAME
+*      IB_SMINFO_ATTR_MOD_DISCOVER
+*
+* DESCRIPTION
+*      Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.
+*
+* SOURCE
+*/
+#define IB_SMINFO_ATTR_MOD_DISCOVER                    (CL_NTOH32(0x000005))
+/**********/
+
+/****s* Access Layer/ib_ci_op_t
+* NAME
+*      ib_ci_op_t
+*
+* DESCRIPTION
+*      A structure used for vendor specific CA interface communication.
+*
+* SYNOPSIS
+*/
+typedef struct _ib_ci_op
+{
+       IN                              uint32_t                                        command;
+       IN                              uint32_t                                        buf_size;
+       IN                              uint32_t                                        buf_info;
+       IN      OUT                     int32_t                                         status;
+               OUT                     uint32_t                                        num_bytes_ret;
+       IN      OUT                     void* __ptr64                           p_buf OPTIONAL;
+
+}      ib_ci_op_t;
+/*
+* FIELDS
+*      command
+*              A command code that is understood by the verbs provider.
+*
+*      status
+*              The completion status from the verbs provider.  This field should be
+*              initialize to indicate an error to allow detection and cleanup in
+*              case a communication error occurs between user-mode and kernel-mode.
+*
+*      buf_size
+*              The size of the buffer in bytes.
+*
+*      buf_info
+*              Additional buffer information
+*
+*      p_buf
+*              A reference to a buffer containing vendor specific data.  The verbs
+*              provider must not access pointers in the p_buf between user-mode and
+*              kernel-mode.  Any pointers embedded in the p_buf are invalidated by
+*              the user-mode/kernel-mode transition.
+*
+*      num_bytes_ret
+*              The size in bytes of the vendor specific data returned in the buffer.
+*              This field is set by the verbs provider.  The verbs provider should
+*              verify that the buffer size is sufficient to hold the data being
+*              returned.
+*
+* NOTES
+*      This structure is provided to allow the exchange of vendor specific
+*      data between the originator and the verbs provider.  Users of this
+*      structure are expected to know the format of data in the p_buf based
+*      on the structure command field or the usage context.
+*****/
+
+
+#endif // __IB_TYPES_EXTENDED_H__
diff --git a/trunk/ulp/opensm/user/include/opensm/cl_dispatcher.h b/trunk/ulp/opensm/user/include/opensm/cl_dispatcher.h
new file mode 100644 (file)
index 0000000..7b5a3ec
--- /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$
+ */
+
+
+/*
+ * 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/trunk/ulp/opensm/user/include/opensm/cl_event_wheel.h b/trunk/ulp/opensm/user/include/opensm/cl_event_wheel.h
new file mode 100644 (file)
index 0000000..559f2aa
--- /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$
+ */
+
+
+/*
+ * 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/trunk/ulp/opensm/user/include/opensm/osm_attrib_req.h b/trunk/ulp/opensm/user/include/opensm/osm_attrib_req.h
new file mode 100644 (file)
index 0000000..c532c58
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * 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$
+ */
+
+
+#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/trunk/ulp/opensm/user/include/opensm/osm_base.h b/trunk/ulp/opensm/user/include/opensm/osm_base.h
new file mode 100644 (file)
index 0000000..cafde5e
--- /dev/null
@@ -0,0 +1,715 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *     Basic OpenSM definitions and structures.
+ *     This object represents an OpenSM "base class".
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.15 $
+ */
+
+#ifndef _OSM_BASE_H_
+#define _OSM_BASE_H_
+
+#ifdef __WIN__
+#include <vendor/winosm_common.h>
+#define OSM_CDECL __cdecl
+#else
+#define OSM_CDECL
+#endif
+
+#include <complib/cl_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
+
+/****h* OpenSM/Constants
+* NAME
+*      Constants
+*
+* DESCRIPTION
+*      The following constants are used throughout the OpenSM.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+/****h* OpenSM/Base
+* NAME
+*      Base
+*
+* DESCRIPTION
+*      The Base object encapsulates basic information needed by the
+*      OpenSM to manage objects.  Each OpenSM object includes the
+*      Base object as the first member.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+/****s* OpenSM: Base/OSM_VERSION
+* NAME
+*      OSM_VERSION
+*
+* DESCRIPTION
+*      The version String for OpenSM 
+*
+* SYNOPSIS
+*/
+#define OSM_VERSION "OpenSM Rev:openib-1.1.0"
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_M_KEY
+* NAME
+*      OSM_DEFAULT_M_KEY
+*
+* DESCRIPTION
+*      Managment key value used by the OpenSM.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_M_KEY 0
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_SM_KEY
+* NAME
+*      OSM_DEFAULT_SM_KEY
+*
+* DESCRIPTION
+*      Subnet Manager key value used by the OpenSM.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SM_KEY 0
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_LMC
+* NAME
+*      OSM_DEFAULT_LMC
+*
+* DESCRIPTION
+*      Default LMC value used by the OpenSM.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_LMC 0
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_MAX_OP_VLS
+* NAME
+*      OSM_DEFAULT_MAX_OP_VLS
+*
+* DESCRIPTION
+*      Default Maximal Operational VLs to be initialized on 
+*  the link ports PortInfo by the OpenSM.
+*  Default value provides backward compatibility.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_MAX_OP_VLS 5
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_SL
+* NAME
+*      OSM_DEFAULT_SL
+*
+* DESCRIPTION
+*      Default SL value used by the OpenSM.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SL 0
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_SM_PRIORITY
+* NAME
+*      OSM_DEFAULT_SM_PRIORITY
+*
+* DESCRIPTION
+*      Default SM priority value used by the OpenSM,
+*      as defined in the SMInfo attribute.  0 is the highest priority.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SM_PRIORITY 0
+/********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_TMP_DIR
+* NAME
+*      OSM_DEFAULT_TMP_DIR
+*
+* DESCRIPTION
+*      Specifies the default temporary directory for the log file, subnet.lst
+*  and the other log files (with the exception of osm.log for Linux being 
+*  in /var/log).
+*
+* SYNOPSIS
+*/
+#ifdef __WIN__
+#define OSM_DEFAULT_TMP_DIR GetOsmPath()
+#else
+#define OSM_DEFAULT_TMP_DIR "/tmp/"
+#endif
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_CACHE_DIR
+* NAME
+*      OSM_DEFAULT_CACHE_DIR
+*
+* DESCRIPTION
+*      Specifies the default cache directory for the db files.
+*      Note that the directory must appear with "/" ("\\" for windows) at the end.
+*
+* SYNOPSIS
+*/
+#ifdef __WIN__
+#define OSM_DEFAULT_CACHE_DIR GetOsmPath()
+#else
+#define OSM_DEFAULT_CACHE_DIR "/var/cache/osm/"
+#endif
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_LOG_FILE
+* NAME
+*      OSM_DEFAULT_LOG_FILE
+*
+* DESCRIPTION
+*      Specifies the default log file name
+*
+* SYNOPSIS
+*/
+#ifdef __WIN__
+#define OSM_DEFAULT_LOG_FILE strcat(GetOsmPath(),"osm.log")
+#else
+#define OSM_DEFAULT_LOG_FILE "/var/log/osm.log"
+#endif
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_SWEEP_INTERVAL_SECS
+* NAME
+*      OSM_DEFAULT_SWEEP_INTERVAL_SECS
+*
+* DESCRIPTION
+*      Specifies the default number of seconds between subnet sweeps.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SWEEP_INTERVAL_SECS 10
+/***********/
+/****d* OpenSM: Base/OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC
+* NAME
+*      OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC
+*
+* DESCRIPTION
+*      Specifies the default transaction timeout in milliseconds.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC 100
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_SUBNET_TIMEOUT
+* NAME
+*      OSM_DEFAULT_SUBNET_TIMEOUT
+*
+* DESCRIPTION
+*      Specifies the default transaction timeout.
+*      timeout time = 4us * 2^timeout.
+*  We use here ~1sec.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SUBNET_TIMEOUT 0x12
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_SWITCH_PACKET_LIFE
+* NAME
+*      OSM_DEFAULT_SWITCH_PACKET_LIFE
+*
+* DESCRIPTION
+*      Specifies the default max life time for a pcket on the switch.
+*      timeout time = 4us * 2^timeout.
+*  We use here the value of ~1sec
+*  A Value > 19dec disables this mechanism.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SWITCH_PACKET_LIFE 0x12
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_HEAD_OF_QUEUE_LIFE
+* NAME
+*      OSM_DEFAULT_HEAD_OF_QUEUE_LIFE
+*
+* DESCRIPTION
+*      Sets the time a packet can live in the head of the VL Queue
+*  We use here the value of ~1sec
+*  A Value > 19dec disables this mechanism.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_HEAD_OF_QUEUE_LIFE 0x12
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE
+* NAME
+*      OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE
+*
+* DESCRIPTION
+*      Sets the time a packet can live in the head of the VL Queue
+*  of a port that drives a CA port.
+*  We use here the value of ~130usec
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE 0xC
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_LEAF_VL_STALL_COUNT
+* NAME
+*      OSM_DEFAULT_LEAF_VL_STALL_COUNT
+*
+* DESCRIPTION
+*      Sets the number of contigious head of queue life time drops that 
+*  puts the VL into stalled state. In stalled state the port supposed to
+*  drop everything for 8*(head of queue lifetime) 
+*  We use here the value of 1 - so any drop due to HOQ means stalling the VL
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_LEAF_VL_STALL_COUNT 0x1
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT
+* NAME
+*      OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT
+*
+* DESCRIPTION
+*      Specifies the default timeout for ignoring same trap.
+*      timeout time = 5000000us
+*  We use here ~5sec.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT 5000000
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_UNHEALTHY_TIMEOUT
+* NAME
+*      OSM_DEFAULT_UNHEALTHY_TIMEOUT
+*
+* DESCRIPTION
+*      Specifies the default timeout for setting port as un-healthy.
+*      timeout time = 60000000us
+*  We use here ~60sec.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_UNHEALTHY_TIMEOUT 60000000
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_ERROR_THRESHOLD
+* NAME
+*      OSM_DEFAULT_ERROR_THRESHOLD
+*
+* DESCRIPTION
+*      Specifies default link error threshold to be set by SubnMgt(Set.PortInfo).
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_ERROR_THRESHOLD 0x08
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_SMP_MAX_ON_WIRE
+* NAME
+*      OSM_DEFAULT_SMP_MAX_ON_WIRE
+*
+* DESCRIPTION
+*      Specifies the default number of VL15 SMP MADs allowed on 
+*      the wire at any one time.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SMP_MAX_ON_WIRE 1
+/***********/
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP0_RCV_SIZE
+* NAME
+*      OSM_SM_DEFAULT_QP0_RCV_SIZE
+*
+* DESCRIPTION
+*      Specifies the default size (in MADs) of the QP0 receive queue
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_QP0_RCV_SIZE 256
+/***********/
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP0_SEND_SIZE
+* NAME
+*      OSM_SM_DEFAULT_QP0_SEND_SIZE
+*
+* DESCRIPTION
+*      Specifies the default size (in MADs) of the QP0 send queue
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_QP0_SEND_SIZE 256
+/***********/
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP1_RCV_SIZE
+* NAME
+*   OSM_SM_DEFAULT_QP1_RCV_SIZE
+*
+* DESCRIPTION
+*   Specifies the default size (in MADs) of the QP1 receive queue
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_QP1_RCV_SIZE 256
+/***********/
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP1_SEND_SIZE
+* NAME
+*   OSM_SM_DEFAULT_QP1_SEND_SIZE
+*
+* DESCRIPTION
+*   Specifies the default size (in MADs) of the QP1 send queue
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_QP1_SEND_SIZE 256
+
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS
+* NAME
+*   OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS
+*
+* DESCRIPTION
+*   Specifies the polling timeout (in miliseconds) - the timeout
+*   between one poll to another.
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS 10000
+/**********/
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_POLLING_RETRY_NUMBER
+* NAME
+*   OSM_SM_DEFAULT_POLLING_RETRY_NUMBER
+*
+* DESCRIPTION
+*   Specifies the number of polling retries before the SM goes back
+*   to DISCOVERY stage. So the total time for handoff is 3min.
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_POLLING_RETRY_NUMBER 18
+/**********/
+
+/****d* OpenSM: Base/OSM_NO_PATH
+* NAME
+*      OSM_NO_PATH
+*
+* DESCRIPTION
+*      Value indicating there is no path to the given LID.
+*
+* SYNOPSIS
+*/
+#define OSM_NO_PATH                    0xFF
+/**********/
+
+/****d* OpenSM: Base/osm_thread_state_t
+* NAME
+*      osm_thread_state_t
+*
+* DESCRIPTION
+*      Enumerates the possible states of worker threads, such
+*      as the subnet sweeper.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_thread_state
+{
+       OSM_THREAD_STATE_NONE = 0,
+       OSM_THREAD_STATE_INIT,
+       OSM_THREAD_STATE_RUN,
+       OSM_THREAD_STATE_EXIT
+
+} osm_thread_state_t;
+/***********/
+
+/*
+ * OSM_CAP ARE C15-0.1.7 Table 152 
+ */
+
+/****d* OpenSM: Base/OSM_CAP_IS_SUBN_OPT_RECS_SUP
+* Name
+*      OSM_CAP_IS_SUBN_OPT_RECS_SUP
+*
+* DESCRIPTION
+*      Support all optional attributes not including:
+*  MCMemberRecord, TraceRecord, MultPiathRecord
+*
+* SYNOPSIS
+*/
+#define OSM_CAP_IS_SUBN_OPT_RECS_SUP (1 << 8);
+/***********/
+
+/****d* OpenSM: Base/OSM_CAP_IS_UD_MCAST_SUP
+* Name
+*      OSM_CAP_IS_UD_MCAST_SUP
+*
+* DESCRIPTION
+*      Multicast is supported 
+*
+* SYNOPSIS
+*/
+#define OSM_CAP_IS_UD_MCAST_SUP (1 << 9);
+/***********/
+
+/****d* OpenSM: Base/OSM_CAP_IS_MULTI_PATH_SUP
+* Name
+*      OSM_CAP_IS_MULTI_PATH_SUP
+*
+* DESCRIPTION
+*      Multi Path is supported
+*
+* SYNOPSIS
+*/
+#define OSM_CAP_IS_MULTI_PATH_SUP (1 << 10);
+/***********/
+
+/****d* OpenSM: Base/OSM_CAP_IS_REINIT_SUP
+* Name
+*      OSM_CAP_IS_REINIT_SUP
+*
+* DESCRIPTION
+*      SM/SA supports re-initialization supported
+*
+* SYNOPSIS
+*/
+#define OSM_CAP_IS_REINIT_SUP (1 << 11);
+/***********/
+
+/****d* OpenSM: Base/osm_sm_state_t
+* NAME
+*      osm_sm_state_t
+*
+* DESCRIPTION
+*      Enumerates the possible states of the SM object.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_sm_state
+{
+       OSM_SM_STATE_NO_STATE = 0,
+       OSM_SM_STATE_INIT,
+       OSM_SM_STATE_IDLE,
+       OSM_SM_STATE_SWEEP_LIGHT,
+       OSM_SM_STATE_SWEEP_LIGHT_WAIT,
+       OSM_SM_STATE_SWEEP_HEAVY_SELF,
+       OSM_SM_STATE_SWEEP_HEAVY_SUBNET,
+       OSM_SM_STATE_SET_SM_UCAST_LID,
+       OSM_SM_STATE_SET_SM_UCAST_LID_WAIT,
+       OSM_SM_STATE_SET_SM_UCAST_LID_DONE,
+       OSM_SM_STATE_SET_SUBNET_UCAST_LIDS,
+       OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_WAIT,
+       OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_DONE,
+       OSM_SM_STATE_SET_UCAST_TABLES,
+       OSM_SM_STATE_SET_UCAST_TABLES_WAIT,
+       OSM_SM_STATE_SET_UCAST_TABLES_DONE,
+       OSM_SM_STATE_SET_MCAST_TABLES,
+       OSM_SM_STATE_SET_MCAST_TABLES_WAIT,
+       OSM_SM_STATE_SET_MCAST_TABLES_DONE,
+       OSM_SM_STATE_SET_LINK_PORTS,
+       OSM_SM_STATE_SET_LINK_PORTS_WAIT,
+       OSM_SM_STATE_SET_LINK_PORTS_DONE,
+       OSM_SM_STATE_SET_ARMED,
+       OSM_SM_STATE_SET_ARMED_WAIT,
+       OSM_SM_STATE_SET_ARMED_DONE,
+       OSM_SM_STATE_SET_ACTIVE,
+       OSM_SM_STATE_SET_ACTIVE_WAIT,
+       OSM_SM_STATE_LOST_NEGOTIATION,
+       OSM_SM_STATE_STANDBY,
+       OSM_SM_STATE_SUBNET_UP,
+       OSM_SM_STATE_PROCESS_REQUEST,
+       OSM_SM_STATE_PROCESS_REQUEST_WAIT,
+       OSM_SM_STATE_PROCESS_REQUEST_DONE,
+       OSM_SM_STATE_MASTER_OR_HIGHER_SM_DETECTED,
+       OSM_SM_STATE_MAX
+
+} osm_sm_state_t;
+/***********/
+
+/****d* OpenSM: Base/osm_signal_t
+* NAME
+*      osm_signal_t
+*
+* DESCRIPTION
+*      Enumerates the possible signal codes used by the OSM managers
+*      This cannot be an enum type, since conversion to and from
+*      integral types is necessary when passing signals through
+*      the dispatcher.
+*
+* SYNOPSIS
+*/
+#define OSM_SIGNAL_NONE                                                        0
+#define OSM_SIGNAL_SWEEP                                               1
+#define OSM_SIGNAL_CHANGE_DETECTED                             2
+#define OSM_SIGNAL_NO_PENDING_TRANSACTIONS             3
+#define OSM_SIGNAL_DONE                                                        4
+#define OSM_SIGNAL_DONE_PENDING                                        5
+#define OSM_SIGNAL_LOST_SM_NEGOTIATION                 6
+#define OSM_SIGNAL_LIGHT_SWEEP_FAIL                            7
+#define OSM_SIGNAL_IDLE_TIME_PROCESS                   8
+#define OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST   9
+#define OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED                10
+#define OSM_SIGNAL_EXIT_STBY                11
+#define OSM_SIGNAL_MAX                                                 12
+
+typedef uintn_t osm_signal_t;
+/***********/
+
+/****d* OpenSM: Base/osm_state_mgr_mode_t
+* NAME
+*       osm_state_mgr_mode_t
+*
+* DESCRIPTION
+*      Enumerates the possible state progressing codes used by the OSM 
+*      state manager.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_state_mgr_mode
+{
+  OSM_STATE_STEP_CONTINUOUS = 0,
+  OSM_STATE_STEP_TAKE_ONE,
+  OSM_STATE_STEP_BREAK
+} osm_state_mgr_mode_t;
+/*
+* OSM_STATE_STEP_CONTINUOUS 
+*    normal automatic progress mode
+*
+* OSM_STATE_STEP_TAKE_ONE 
+*    Do one step 
+*
+* OSM_STATE_STEP_BREAK
+*    Stop before taking next step (the while loop in the state 
+*    manager automatically change to this state).
+*
+**********/
+
+#define OSM_REPORT_BUF_SIZE                            0x10000
+#define OSM_REPORT_LINE_SIZE                   0x256
+#define OSM_REPORT_BUF_THRESHOLD (OSM_REPORT_BUF_SIZE / OSM_REPORT_LINE_SIZE)
+
+
+/****d* OpenSM: Base/osm_sm_signal_t
+* NAME
+*      osm_sm_signal_t
+*
+* DESCRIPTION
+*      Enumerates the possible signals used by the OSM_SM_MGR
+*
+* SYNOPSIS
+*/
+typedef enum _osm_sm_signal
+{
+  OSM_SM_SIGNAL_INIT = 0,
+  OSM_SM_SIGNAL_DISCOVERY_COMPLETED,
+  OSM_SM_SIGNAL_POLLING_TIMEOUT,
+  OSM_SM_SIGNAL_DISCOVER,
+  OSM_SM_SIGNAL_DISABLE,
+  OSM_SM_SIGNAL_HANDOVER,
+  OSM_SM_SIGNAL_HANDOVER_SENT,
+  OSM_SM_SIGNAL_ACKNOWLEDGE,
+  OSM_SM_SIGNAL_STANDBY,
+  OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED,
+  OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED_DONE,
+  OSM_SM_SIGNAL_WAIT_FOR_HANDOVER,
+  OSM_SM_SIGNAL_MAX
+
+} osm_sm_signal_t;
+/***********/
+
+/****d* OpenSM/osm_mcast_req_type_t
+* NAME
+*      osm_mcast_req_type_t
+*
+* DESCRIPTION
+*      Enumerates the possible signals used by the OSM_MCAST_REQUEST
+*
+* SYNOPSIS
+*/
+typedef enum _osm_mcast_req_type
+{
+  OSM_MCAST_REQ_TYPE_CREATE,
+  OSM_MCAST_REQ_TYPE_JOIN,
+  OSM_MCAST_REQ_TYPE_LEAVE,
+  OSM_MCAST_REQ_TYPE_SUBNET_CHANGE
+
+}      osm_mcast_req_type_t;
+/***********/
+
+/****s* OpenSM: Base/MAX_UPDN_GUID_FILE_LINE_LENGTH
+* NAME
+*      MAX_UPDN_GUID_FILE_LINE_LENGTH
+*
+* DESCRIPTION
+*      The maximum line number when reading updn guid file
+*
+* SYNOPSIS
+*/
+#define MAX_UPDN_GUID_FILE_LINE_LENGTH 120
+/**********/
+
+END_C_DECLS
+
+#endif /* _OSM_BASE_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_base.h.orig b/trunk/ulp/opensm/user/include/opensm/osm_base.h.orig
new file mode 100755 (executable)
index 0000000..8e8a2d4
--- /dev/null
@@ -0,0 +1,717 @@
+/*
+ * 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 a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or 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 3401 2005-09-13 12:58:45Z halr $
+ */
+
+
+/*
+ * Abstract:
+ *     Basic OpenSM definitions and structures.
+ *     This object represents an OpenSM "base class".
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.15 $
+ */
+
+#ifndef _OSM_BASE_H_
+#define _OSM_BASE_H_
+
+#ifdef __WIN__
+#include <vendor/winosm_common.h>
+#define OSM_CDECL __cdecl
+#else
+#define OSM_CDECL
+#endif
+
+#include <complib/cl_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
+
+/****h* OpenSM/Constants
+* NAME
+*      Constants
+*
+* DESCRIPTION
+*      The following constants are used throughout the OpenSM.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+/****h* OpenSM/Base
+* NAME
+*      Base
+*
+* DESCRIPTION
+*      The Base object encapsulates basic information needed by the
+*      OpenSM to manage objects.  Each OpenSM object includes the
+*      Base object as the first member.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+/****s* OpenSM: Base/OSM_VERSION
+* NAME
+*      OSM_VERSION
+*
+* DESCRIPTION
+*      The version String for OpenSM 
+*
+* SYNOPSIS
+*/
+#define OSM_VERSION "OpenSM Rev:openib-1.1.0"
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_M_KEY
+* NAME
+*      OSM_DEFAULT_M_KEY
+*
+* DESCRIPTION
+*      Managment key value used by the OpenSM.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_M_KEY 0
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_SM_KEY
+* NAME
+*      OSM_DEFAULT_SM_KEY
+*
+* DESCRIPTION
+*      Subnet Manager key value used by the OpenSM.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SM_KEY 0
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_LMC
+* NAME
+*      OSM_DEFAULT_LMC
+*
+* DESCRIPTION
+*      Default LMC value used by the OpenSM.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_LMC 0
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_MAX_OP_VLS
+* NAME
+*      OSM_DEFAULT_MAX_OP_VLS
+*
+* DESCRIPTION
+*      Default Maximal Operational VLs to be initialized on 
+*  the link ports PortInfo by the OpenSM.
+*  Default value provides backward compatibility.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_MAX_OP_VLS 5
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_SL
+* NAME
+*      OSM_DEFAULT_SL
+*
+* DESCRIPTION
+*      Default SL value used by the OpenSM.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SL 0
+/********/
+
+/****s* OpenSM: Base/OSM_DEFAULT_SM_PRIORITY
+* NAME
+*      OSM_DEFAULT_SM_PRIORITY
+*
+* DESCRIPTION
+*      Default SM priority value used by the OpenSM,
+*      as defined in the SMInfo attribute.  0 is the highest priority.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SM_PRIORITY 0
+/********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_TMP_DIR
+* NAME
+*      OSM_DEFAULT_TMP_DIR
+*
+* DESCRIPTION
+*      Specifies the default temporary directory for the log file, subnet.lst
+*  and the other log files (with the exception of osm.log for Linux being 
+*  in /var/log).
+*
+* SYNOPSIS
+*/
+#ifdef __WIN__
+#define OSM_DEFAULT_TMP_DIR "C:\\Windows\\Temp\\"
+#else
+#define OSM_DEFAULT_TMP_DIR "/tmp/"
+#endif
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_CACHE_DIR
+* NAME
+*      OSM_DEFAULT_CACHE_DIR
+*
+* DESCRIPTION
+*      Specifies the default cache directory for the db files.
+*
+* SYNOPSIS
+*/
+#ifdef __WIN__
+#define OSM_DEFAULT_CACHE_DIR "C:\\Windows\\Temp\\"
+#else
+#define OSM_DEFAULT_CACHE_DIR "/var/cache/osm"
+#endif
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_LOG_FILE
+* NAME
+*      OSM_DEFAULT_LOG_FILE
+*
+* DESCRIPTION
+*      Specifies the default log file name
+*
+* SYNOPSIS
+*/
+#ifdef __WIN__
+#define OSM_DEFAULT_LOG_FILE "C:\\Windows\\Temp\\osm.log"
+#else
+#define OSM_DEFAULT_LOG_FILE "/var/log/osm.log"
+#endif
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_SWEEP_INTERVAL_SECS
+* NAME
+*      OSM_DEFAULT_SWEEP_INTERVAL_SECS
+*
+* DESCRIPTION
+*      Specifies the default number of seconds between subnet sweeps.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SWEEP_INTERVAL_SECS 10
+/***********/
+/****d* OpenSM: Base/OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC
+* NAME
+*      OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC
+*
+* DESCRIPTION
+*      Specifies the default transaction timeout in milliseconds.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC 100
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_SUBNET_TIMEOUT
+* NAME
+*      OSM_DEFAULT_SUBNET_TIMEOUT
+*
+* DESCRIPTION
+*      Specifies the default transaction timeout.
+*      timeout time = 4us * 2^timeout.
+*  We use here ~1sec.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SUBNET_TIMEOUT 0x12
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_SWITCH_PACKET_LIFE
+* NAME
+*      OSM_DEFAULT_SWITCH_PACKET_LIFE
+*
+* DESCRIPTION
+*      Specifies the default max life time for a pcket on the switch.
+*      timeout time = 4us * 2^timeout.
+*  We use here the value of ~1sec
+*  A Value > 19dec disables this mechanism.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SWITCH_PACKET_LIFE 0x12
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_HEAD_OF_QUEUE_LIFE
+* NAME
+*      OSM_DEFAULT_HEAD_OF_QUEUE_LIFE
+*
+* DESCRIPTION
+*      Sets the time a packet can live in the head of the VL Queue
+*  We use here the value of ~1sec
+*  A Value > 19dec disables this mechanism.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_HEAD_OF_QUEUE_LIFE 0x12
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE
+* NAME
+*      OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE
+*
+* DESCRIPTION
+*      Sets the time a packet can live in the head of the VL Queue
+*  of a port that drives a CA port.
+*  We use here the value of ~130usec
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE 0xC
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_LEAF_VL_STALL_COUNT
+* NAME
+*      OSM_DEFAULT_LEAF_VL_STALL_COUNT
+*
+* DESCRIPTION
+*      Sets the number of contigious head of queue life time drops that 
+*  puts the VL into stalled state. In stalled state the port supposed to
+*  drop everything for 8*(head of queue lifetime) 
+*  We use here the value of 1 - so any drop due to HOQ means stalling the VL
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_LEAF_VL_STALL_COUNT 0x1
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT
+* NAME
+*      OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT
+*
+* DESCRIPTION
+*      Specifies the default timeout for ignoring same trap.
+*      timeout time = 5000000us
+*  We use here ~5sec.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT 5000000
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_UNHEALTHY_TIMEOUT
+* NAME
+*      OSM_DEFAULT_UNHEALTHY_TIMEOUT
+*
+* DESCRIPTION
+*      Specifies the default timeout for setting port as un-healthy.
+*      timeout time = 60000000us
+*  We use here ~60sec.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_UNHEALTHY_TIMEOUT 60000000
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_ERROR_THRESHOLD
+* NAME
+*      OSM_DEFAULT_ERROR_THRESHOLD
+*
+* DESCRIPTION
+*      Specifies default link error threshold to be set by SubnMgt(Set.PortInfo).
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_ERROR_THRESHOLD 0x08
+/***********/
+
+/****d* OpenSM: Base/OSM_DEFAULT_SMP_MAX_ON_WIRE
+* NAME
+*      OSM_DEFAULT_SMP_MAX_ON_WIRE
+*
+* DESCRIPTION
+*      Specifies the default number of VL15 SMP MADs allowed on 
+*      the wire at any one time.
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_SMP_MAX_ON_WIRE 1
+/***********/
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP0_RCV_SIZE
+* NAME
+*      OSM_SM_DEFAULT_QP0_RCV_SIZE
+*
+* DESCRIPTION
+*      Specifies the default size (in MADs) of the QP0 receive queue
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_QP0_RCV_SIZE 256
+/***********/
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP0_SEND_SIZE
+* NAME
+*      OSM_SM_DEFAULT_QP0_SEND_SIZE
+*
+* DESCRIPTION
+*      Specifies the default size (in MADs) of the QP0 send queue
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_QP0_SEND_SIZE 256
+/***********/
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP1_RCV_SIZE
+* NAME
+*   OSM_SM_DEFAULT_QP1_RCV_SIZE
+*
+* DESCRIPTION
+*   Specifies the default size (in MADs) of the QP1 receive queue
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_QP1_RCV_SIZE 256
+/***********/
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP1_SEND_SIZE
+* NAME
+*   OSM_SM_DEFAULT_QP1_SEND_SIZE
+*
+* DESCRIPTION
+*   Specifies the default size (in MADs) of the QP1 send queue
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_QP1_SEND_SIZE 256
+
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS
+* NAME
+*   OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS
+*
+* DESCRIPTION
+*   Specifies the polling timeout (in miliseconds) - the timeout
+*   between one poll to another.
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS 10000
+/**********/
+
+/****d* OpenSM: Base/OSM_SM_DEFAULT_POLLING_RETRY_NUMBER
+* NAME
+*   OSM_SM_DEFAULT_POLLING_RETRY_NUMBER
+*
+* DESCRIPTION
+*   Specifies the number of polling retries before the SM goes back
+*   to DISCOVERY stage. So the total time for handoff is 3min.
+*
+* SYNOPSIS
+*/
+#define OSM_SM_DEFAULT_POLLING_RETRY_NUMBER 18
+/**********/
+
+/****d* OpenSM: Base/OSM_NO_PATH
+* NAME
+*      OSM_NO_PATH
+*
+* DESCRIPTION
+*      Value indicating there is no path to the given LID.
+*
+* SYNOPSIS
+*/
+#define OSM_NO_PATH                    0xFF
+/**********/
+
+/****d* OpenSM: Base/osm_thread_state_t
+* NAME
+*      osm_thread_state_t
+*
+* DESCRIPTION
+*      Enumerates the possible states of worker threads, such
+*      as the subnet sweeper.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_thread_state
+{
+       OSM_THREAD_STATE_NONE = 0,
+       OSM_THREAD_STATE_INIT,
+       OSM_THREAD_STATE_RUN,
+       OSM_THREAD_STATE_EXIT
+
+} osm_thread_state_t;
+/***********/
+
+/*
+ * OSM_CAP ARE C15-0.1.7 Table 152 
+ */
+
+/****d* OpenSM: Base/OSM_CAP_IS_SUBN_OPT_RECS_SUP
+* Name
+*      OSM_CAP_IS_SUBN_OPT_RECS_SUP
+*
+* DESCRIPTION
+*      Support all optional attributes not including:
+*  MCMemberRecord, TraceRecord, MultPiathRecord
+*
+* SYNOPSIS
+*/
+#define OSM_CAP_IS_SUBN_OPT_RECS_SUP (1 << 8);
+/***********/
+
+/****d* OpenSM: Base/OSM_CAP_IS_UD_MCAST_SUP
+* Name
+*      OSM_CAP_IS_UD_MCAST_SUP
+*
+* DESCRIPTION
+*      Multicast is supported 
+*
+* SYNOPSIS
+*/
+#define OSM_CAP_IS_UD_MCAST_SUP (1 << 9);
+/***********/
+
+/****d* OpenSM: Base/OSM_CAP_IS_MULTI_PATH_SUP
+* Name
+*      OSM_CAP_IS_MULTI_PATH_SUP
+*
+* DESCRIPTION
+*      Multi Path is supported
+*
+* SYNOPSIS
+*/
+#define OSM_CAP_IS_MULTI_PATH_SUP (1 << 10);
+/***********/
+
+/****d* OpenSM: Base/OSM_CAP_IS_REINIT_SUP
+* Name
+*      OSM_CAP_IS_REINIT_SUP
+*
+* DESCRIPTION
+*      SM/SA supports re-initialization supported
+*
+* SYNOPSIS
+*/
+#define OSM_CAP_IS_REINIT_SUP (1 << 11);
+/***********/
+
+/****d* OpenSM: Base/osm_sm_state_t
+* NAME
+*      osm_sm_state_t
+*
+* DESCRIPTION
+*      Enumerates the possible states of the SM object.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_sm_state
+{
+       OSM_SM_STATE_NO_STATE = 0,
+       OSM_SM_STATE_INIT,
+       OSM_SM_STATE_IDLE,
+       OSM_SM_STATE_SWEEP_LIGHT,
+       OSM_SM_STATE_SWEEP_LIGHT_WAIT,
+       OSM_SM_STATE_SWEEP_HEAVY_SELF,
+       OSM_SM_STATE_SWEEP_HEAVY_SUBNET,
+       OSM_SM_STATE_SET_SM_UCAST_LID,
+       OSM_SM_STATE_SET_SM_UCAST_LID_WAIT,
+       OSM_SM_STATE_SET_SM_UCAST_LID_DONE,
+       OSM_SM_STATE_SET_SUBNET_UCAST_LIDS,
+       OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_WAIT,
+       OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_DONE,
+       OSM_SM_STATE_SET_UCAST_TABLES,
+       OSM_SM_STATE_SET_UCAST_TABLES_WAIT,
+       OSM_SM_STATE_SET_UCAST_TABLES_DONE,
+       OSM_SM_STATE_SET_MCAST_TABLES,
+       OSM_SM_STATE_SET_MCAST_TABLES_WAIT,
+       OSM_SM_STATE_SET_MCAST_TABLES_DONE,
+       OSM_SM_STATE_SET_LINK_PORTS,
+       OSM_SM_STATE_SET_LINK_PORTS_WAIT,
+       OSM_SM_STATE_SET_LINK_PORTS_DONE,
+       OSM_SM_STATE_SET_ARMED,
+       OSM_SM_STATE_SET_ARMED_WAIT,
+       OSM_SM_STATE_SET_ARMED_DONE,
+       OSM_SM_STATE_SET_ACTIVE,
+       OSM_SM_STATE_SET_ACTIVE_WAIT,
+       OSM_SM_STATE_LOST_NEGOTIATION,
+       OSM_SM_STATE_STANDBY,
+       OSM_SM_STATE_SUBNET_UP,
+       OSM_SM_STATE_PROCESS_REQUEST,
+       OSM_SM_STATE_PROCESS_REQUEST_WAIT,
+       OSM_SM_STATE_PROCESS_REQUEST_DONE,
+       OSM_SM_STATE_MASTER_OR_HIGHER_SM_DETECTED,
+       OSM_SM_STATE_MAX
+
+} osm_sm_state_t;
+/***********/
+
+/****d* OpenSM: Base/osm_signal_t
+* NAME
+*      osm_signal_t
+*
+* DESCRIPTION
+*      Enumerates the possible signal codes used by the OSM managers
+*      This cannot be an enum type, since conversion to and from
+*      integral types is necessary when passing signals through
+*      the dispatcher.
+*
+* SYNOPSIS
+*/
+#define OSM_SIGNAL_NONE                                                        0
+#define OSM_SIGNAL_SWEEP                                               1
+#define OSM_SIGNAL_CHANGE_DETECTED                             2
+#define OSM_SIGNAL_NO_PENDING_TRANSACTIONS             3
+#define OSM_SIGNAL_DONE                                                        4
+#define OSM_SIGNAL_DONE_PENDING                                        5
+#define OSM_SIGNAL_LOST_SM_NEGOTIATION                 6
+#define OSM_SIGNAL_LIGHT_SWEEP_FAIL                            7
+#define OSM_SIGNAL_IDLE_TIME_PROCESS                   8
+#define OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST   9
+#define OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED                10
+#define OSM_SIGNAL_EXIT_STBY                11
+#define OSM_SIGNAL_MAX                                                 12
+
+typedef uintn_t osm_signal_t;
+/***********/
+
+/****d* OpenSM: Base/osm_state_mgr_mode_t
+* NAME
+*       osm_state_mgr_mode_t
+*
+* DESCRIPTION
+*      Enumerates the possible state progressing codes used by the OSM 
+*      state manager.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_state_mgr_mode
+{
+  OSM_STATE_STEP_CONTINUOUS = 0,
+  OSM_STATE_STEP_TAKE_ONE,
+  OSM_STATE_STEP_BREAK
+} osm_state_mgr_mode_t;
+/*
+* OSM_STATE_STEP_CONTINUOUS 
+*    normal automatic progress mode
+*
+* OSM_STATE_STEP_TAKE_ONE 
+*    Do one step 
+*
+* OSM_STATE_STEP_BREAK
+*    Stop before taking next step (the while loop in the state 
+*    manager automatically change to this state).
+*
+**********/
+
+#define OSM_REPORT_BUF_SIZE                            0x10000
+#define OSM_REPORT_LINE_SIZE                   0x256
+#define OSM_REPORT_BUF_THRESHOLD (OSM_REPORT_BUF_SIZE / OSM_REPORT_LINE_SIZE)
+
+
+/****d* OpenSM: Base/osm_sm_signal_t
+* NAME
+*      osm_sm_signal_t
+*
+* DESCRIPTION
+*      Enumerates the possible signals used by the OSM_SM_MGR
+*
+* SYNOPSIS
+*/
+typedef enum _osm_sm_signal
+{
+  OSM_SM_SIGNAL_INIT = 0,
+  OSM_SM_SIGNAL_DISCOVERY_COMPLETED,
+  OSM_SM_SIGNAL_POLLING_TIMEOUT,
+  OSM_SM_SIGNAL_DISCOVER,
+  OSM_SM_SIGNAL_DISABLE,
+  OSM_SM_SIGNAL_HANDOVER,
+  OSM_SM_SIGNAL_HANDOVER_SENT,
+  OSM_SM_SIGNAL_ACKNOWLEDGE,
+  OSM_SM_SIGNAL_STANDBY,
+  OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED,
+  OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED_DONE,
+  OSM_SM_SIGNAL_WAIT_FOR_HANDOVER,
+  OSM_SM_SIGNAL_MAX
+
+} osm_sm_signal_t;
+/***********/
+
+/****d* OpenSM/osm_mcast_req_type_t
+* NAME
+*      osm_mcast_req_type_t
+*
+* DESCRIPTION
+*      Enumerates the possible signals used by the OSM_MCAST_REQUEST
+*
+* SYNOPSIS
+*/
+typedef enum _osm_mcast_req_type
+{
+  OSM_MCAST_REQ_TYPE_CREATE,
+  OSM_MCAST_REQ_TYPE_JOIN,
+  OSM_MCAST_REQ_TYPE_LEAVE,
+  OSM_MCAST_REQ_TYPE_SUBNET_CHANGE
+
+}      osm_mcast_req_type_t;
+/***********/
+
+/****s* OpenSM: Base/MAX_UPDN_GUID_FILE_LINE_LENGTH
+* NAME
+*      MAX_UPDN_GUID_FILE_LINE_LENGTH
+*
+* DESCRIPTION
+*      The maximum line number when reading updn guid file
+*
+* SYNOPSIS
+*/
+#define MAX_UPDN_GUID_FILE_LINE_LENGTH 120
+/**********/
+
+END_C_DECLS
+
+#endif /* _OSM_BASE_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_db.h b/trunk/ulp/opensm/user/include/opensm/osm_db.h
new file mode 100644 (file)
index 0000000..6528629
--- /dev/null
@@ -0,0 +1,455 @@
+/*
+ * 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$
+ */
+
+
+#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
+*  persistant 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 persistant 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 persistant 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 persistant 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/trunk/ulp/opensm/user/include/opensm/osm_db_pack.h b/trunk/ulp/opensm/user/include/opensm/osm_db_pack.h
new file mode 100644 (file)
index 0000000..4c382a4
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * 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$
+ */
+
+
+/****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/trunk/ulp/opensm/user/include/opensm/osm_drop_mgr.h b/trunk/ulp/opensm/user/include/opensm/osm_drop_mgr.h
new file mode 100644 (file)
index 0000000..42d246a
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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/trunk/ulp/opensm/user/include/opensm/osm_errors.h b/trunk/ulp/opensm/user/include/opensm/osm_errors.h
new file mode 100644 (file)
index 0000000..adcd33e
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 Fowarding Receive Controller
+       2000 - 20FF
+
+       Linear Fowarding Receiver
+       2100 - 21FF
+
+       Vendor Specific
+       2200 - 22FF
+
+       SMInfo Receive Controller
+       2300 - 23FF
+
+       SMInfo Info Receiver
+       2400 - 24FF
+
+       Generic Responder
+       2500 - 25FF
+
+       Linear Fowarding Receive Controller
+       2600 - 26FF
+
+       Linear Fowarding 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 Fowarding Receive Controller
+       3900 - 39FF
+
+       Multicast Fowarding 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/trunk/ulp/opensm/user/include/opensm/osm_ft_config_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_ft_config_ctrl.h
new file mode 100644 (file)
index 0000000..d42f36e
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_ft_conf_ctrl_t.
+ *     This object represents a controller that performs a 
+ *     Set(Linear/Random ForwardingTable) for the specified switch.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_FT_CONFIG_CTRL_H_
+#define _OSM_FT_CONFIG_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/Forwarding Table Configuration Controller
+* NAME
+*      Forwarding Table Configuration Controller
+*
+* DESCRIPTION
+*      The Forwarding Table Configuration Controller object encapsulates the
+*      information needed to Set(Linear/Random ForwardingTable) at the
+*      specified switch.
+*
+*      The Forwarding Table Configuration 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: Forwarding Table Configuration Controller/osm_ft_conf_ctrl_t
+* NAME
+*      osm_ft_conf_ctrl_t
+*
+* DESCRIPTION
+*      Forwarding Table Configuration Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_ft_conf_ctrl
+{
+       osm_subn_t                                      *p_subn;
+       osm_log_t                                       *p_log;
+       cl_plock_t                                      *p_lock;
+       cl_dispatcher_t                         *p_disp;
+
+} osm_ft_conf_ctrl_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.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+* SEE ALSO
+*      Forwarding Table Configuration Controller object
+*********/
+/****f* OpenSM: Forwarding Table Configuration Controller/osm_ft_conf_ctrl_construct
+* NAME
+*      osm_ft_conf_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Forwarding Table Configuration Controller object.
+*
+* SYNOPSIS
+*/
+void osm_ft_conf_ctrl_construct(
+       IN osm_ft_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Forwarding Table Configuration Controller object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_ft_conf_ctrl_init, osm_ft_conf_ctrl_destroy
+*
+*      Calling osm_ft_conf_ctrl_construct is a prerequisite to calling any other
+*      method except osm_ft_conf_ctrl_init.
+*
+* SEE ALSO
+*      Forwarding Table Configuration Controller object, osm_ft_conf_ctrl_init,
+*      osm_ft_conf_ctrl_destroy
+*********/
+
+/****f* OpenSM: Forwarding Table Configuration Controller/osm_ft_conf_ctrl_destroy
+* NAME
+*      osm_ft_conf_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_ft_conf_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_ft_conf_ctrl_destroy(
+       IN osm_ft_conf_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
+*      Forwarding Table Configuration Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_ft_conf_ctrl_construct or osm_ft_conf_ctrl_init.
+*
+* SEE ALSO
+*      Forwarding Table Configuration Controller object, osm_ft_conf_ctrl_construct,
+*      osm_ft_conf_ctrl_init
+*********/
+
+/****f* OpenSM: Forwarding Table Configuration Controller/osm_ft_conf_ctrl_init
+* NAME
+*      osm_ft_conf_ctrl_init
+*
+* DESCRIPTION
+*      The osm_ft_conf_ctrl_init function initializes a
+*      Forwarding Table Configuration Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_ft_conf_ctrl_init(
+       IN osm_ft_conf_ctrl_t* const p_ctrl,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_ft_conf_ctrl_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.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Forwarding Table Configuration Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Forwarding Table Configuration Controller methods.
+*
+* SEE ALSO
+*      Forwarding Table Configuration Controller object, osm_ft_conf_ctrl_construct,
+*      osm_ft_conf_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_FT_CONFIG_CTRL_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_fwd_tbl.h b/trunk/ulp/opensm/user/include/opensm/osm_fwd_tbl.h
new file mode 100644 (file)
index 0000000..0045b21
--- /dev/null
@@ -0,0 +1,388 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 Fowarding 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/trunk/ulp/opensm/user/include/opensm/osm_helper.h b/trunk/ulp/opensm/user/include/opensm/osm_helper.h
new file mode 100644 (file)
index 0000000..de35100
--- /dev/null
@@ -0,0 +1,592 @@
+/*
+ * 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$
+ */
+
+
+#ifndef _OSM_HELPER_H_
+#define _OSM_HELPER_H_
+
+#include <iba/ib_types.h>
+#include <opensm/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_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_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_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/trunk/ulp/opensm/user/include/opensm/osm_inform.h b/trunk/ulp/opensm/user/include/opensm/osm_inform.h
new file mode 100644 (file)
index 0000000..e8ad23f
--- /dev/null
@@ -0,0 +1,325 @@
+/*
+ * 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$
+ */
+
+/*
+ * 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;     // a handle of lower level mad srvc
+  osm_infr_rcv_t*          p_infr_rcv; // the receiver of inform_info's
+  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!!
+*
+*  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_rid
+* NAME
+*      osm_infr_get_by_rid
+*
+* DESCRIPTION
+*      Find a matching osm_infr_t in the subnet DB by inform_info_record RID 
+*
+* SYNOPSIS
+*/
+osm_infr_t*
+osm_infr_get_by_rid(
+       IN osm_subn_t   const   *p_subn,
+       IN osm_log_t    *p_log,
+       IN ib_inform_info_record_t* const p_inf_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 with the search RID
+*
+*  RETURN
+*     The matching osm_infr_t
+* 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/trunk/ulp/opensm/user/include/opensm/osm_lid_mgr.h b/trunk/ulp/opensm/user/include/opensm/osm_lid_mgr.h
new file mode 100644 (file)
index 0000000..7fe07c8
--- /dev/null
@@ -0,0 +1,319 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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_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/trunk/ulp/opensm/user/include/opensm/osm_lin_fwd_rcv.h b/trunk/ulp/opensm/user/include/opensm/osm_lin_fwd_rcv.h
new file mode 100644 (file)
index 0000000..9850a7f
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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/trunk/ulp/opensm/user/include/opensm/osm_lin_fwd_rcv_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_lin_fwd_rcv_ctrl.h
new file mode 100644 (file)
index 0000000..a62f5fc
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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/trunk/ulp/opensm/user/include/opensm/osm_lin_fwd_tbl.h b/trunk/ulp/opensm/user/include/opensm/osm_lin_fwd_tbl.h
new file mode 100644 (file)
index 0000000..7d3a674
--- /dev/null
@@ -0,0 +1,374 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <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 Fowarding 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 );
+
+       cl_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/trunk/ulp/opensm/user/include/opensm/osm_link_mgr.h b/trunk/ulp/opensm/user/include/opensm/osm_link_mgr.h
new file mode 100644 (file)
index 0000000..76c9dc8
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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/trunk/ulp/opensm/user/include/opensm/osm_log.h b/trunk/ulp/opensm/user/include/opensm/osm_log.h
new file mode 100644 (file)
index 0000000..c84355f
--- /dev/null
@@ -0,0 +1,480 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 __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
+
+#ifndef PRIx64
+#if __WORDSIZE == 64
+#define __PRI64_PREFIX "l"
+#else
+#define __PRI64_PREFIX "L"
+#endif
+
+#define PRId64         __PRI64_PREFIX"d"
+#define PRIo64         __PRI64_PREFIX"o"
+#define PRIu64         __PRI64_PREFIX"u"
+#define PRIx64         __PRI64_PREFIX"x"
+#endif
+
+#define LOG_ENTRY_SIZE_MAX             4096
+#define BUF_SIZE                               LOG_ENTRY_SIZE_MAX
+
+#define OSM_LOG_DEFINE_FUNC( NAME ) \
+       static const char osm_log_func_name[] = #NAME
+
+#define OSM_LOG_ENTER( OSM_LOG_PTR, NAME ) \
+       OSM_LOG_DEFINE_FUNC( NAME ); \
+       osm_log( OSM_LOG_PTR, OSM_LOG_FUNCS, \
+                "%s: [\n", osm_log_func_name );
+
+#define OSM_LOG_EXIT( OSM_LOG_PTR ) \
+       osm_log( OSM_LOG_PTR, OSM_LOG_FUNCS, \
+                "%s: ]\n", osm_log_func_name );
+
+/****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;
+       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_destroy
+*
+*      Calling osm_log_construct is a prerequisite to calling any other
+*      method except osm_log_init.
+*
+* SEE ALSO
+*      Log object, osm_log_init,
+*      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 or osm_log_init.
+*
+* SEE ALSO
+*      Log object, osm_log_construct,
+*      osm_log_init
+*********/
+
+/****f* OpenSM: Log/osm_log_init
+* NAME
+*      osm_log_init
+*
+* DESCRIPTION
+*      The osm_log_init function initializes a
+*      Log object for use.
+*
+* SYNOPSIS
+*/
+static inline 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)
+{
+  p_log->level = log_flags;
+  p_log->flush = flush;
+
+  if (log_file == NULL)
+  {
+    p_log->out_port = stdout;
+  }
+  else
+  {
+    p_log->out_port = fopen(log_file,"a+");
+    if (!p_log->out_port)
+    {
+      printf("Cannot open %s for appending. Permission denied\n", log_file);
+      return(IB_UNKNOWN_ERROR);
+    }
+  }
+  openlog("OpenSM", LOG_CONS | LOG_PID, LOG_USER);
+
+  if (cl_spinlock_init( &p_log->lock ) == CL_SUCCESS) 
+    return IB_SUCCESS;
+  else
+    return IB_ERROR;
+}
+/*
+* 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_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
+*********/
+
+
+void
+osm_log(
+       IN osm_log_t* const p_log,
+       IN const osm_log_level_t verbosity,
+       IN const char *p_str, ... );
+
+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: Acquire %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/trunk/ulp/opensm/user/include/opensm/osm_mad_pool.h b/trunk/ulp/opensm/user/include/opensm/osm_mad_pool.h
new file mode 100644 (file)
index 0000000..1d55478
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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/trunk/ulp/opensm/user/include/opensm/osm_madw.h b/trunk/ulp/opensm/user/include/opensm/osm_madw.h
new file mode 100644 (file)
index 0000000..3da0057
--- /dev/null
@@ -0,0 +1,1143 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <iba/ib_types.h>
+#include <complib/cl_qlist.h>
+#include <opensm/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;
+} 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;
+/*********/
+/****s* OpenSM: MAD Wrapper/osm_arbitrary_context_t
+* NAME
+*      osm_sa_context_t
+*
+* DESCRIPTION
+*      Context needed by arbitrary recipient.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_arbitrary_context
+{
+  void*             context1;
+  void*             context2;
+} osm_arbitrary_context_t;
+/*********/
+
+/****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_arbitrary_context_t arb_context;
+} 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.
+       */
+       cl_memclr( ((uint8_t *)p_madw) + sizeof( cl_pool_item_t ),
+                       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
+*********/
+/****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
+*********/
+
+/****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/trunk/ulp/opensm/user/include/opensm/osm_matrix.h b/trunk/ulp/opensm/user/include/opensm/osm_matrix.h
new file mode 100644 (file)
index 0000000..98ea62e
--- /dev/null
@@ -0,0 +1,449 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 number of ports in this lid matrix.
+*
+* 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 number of ports in this lid matrix.
+*
+* 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/trunk/ulp/opensm/user/include/opensm/osm_mcast_config_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_mcast_config_ctrl.h
new file mode 100644 (file)
index 0000000..17390ba
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_mcast_conf_ctrl_t.
+ *     This object represents a controller that performs a 
+ *     Set(MulticastForwardingTable) for the specified port.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_MCAST_CONFIG_CTRL_H_
+#define _OSM_MCAST_CONFIG_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/Multicast Forwarding Table Configuration Controller
+* NAME
+*      Multicast Forwarding Table Configuration Controller
+*
+* DESCRIPTION
+*      The Multicast Forwarding Table Configuration Controller object
+*      encapsulates the information needed to Set(MulticastForwardingTable)
+*      at the specified port.
+*
+*      The Multicast Forwarding Table Configuration 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: Multicast Forwarding Table Configuration Controller/osm_mcast_conf_ctrl_t
+* NAME
+*      osm_mcast_conf_ctrl_t
+*
+* DESCRIPTION
+*      Multicast Forwarding Table Configuration Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mcast_conf_ctrl
+{
+       osm_subn_t                                      *p_subn;
+       osm_log_t                                       *p_log;
+       cl_plock_t                                      *p_lock;
+       cl_dispatcher_t                         *p_disp;
+
+} osm_mcast_conf_ctrl_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.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+* SEE ALSO
+*      Multicast Forwarding Table Configuration Controller object
+*********/
+/****f* OpenSM: Multicast Forwarding Table Configuration Controller/osm_mcast_conf_ctrl_construct
+* NAME
+*      osm_mcast_conf_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Multicast Forwarding Table Configuration Controller object.
+*
+* SYNOPSIS
+*/
+void osm_mcast_conf_ctrl_construct(
+       IN osm_mcast_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Multicast Forwarding Table Configuration Controller object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_mcast_conf_ctrl_init, osm_mcast_conf_ctrl_destroy,
+*      and osm_mcast_conf_ctrl_is_inited.
+*
+*      Calling osm_mcast_conf_ctrl_construct is a prerequisite to calling any other
+*      method except osm_mcast_conf_ctrl_init.
+*
+* SEE ALSO
+*      Multicast Forwarding Table Configuration Controller object, osm_mcast_conf_ctrl_init,
+*      osm_mcast_conf_ctrl_destroy, osm_mcast_conf_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Configuration Controller/osm_mcast_conf_ctrl_destroy
+* NAME
+*      osm_mcast_conf_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_mcast_conf_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_mcast_conf_ctrl_destroy(
+       IN osm_mcast_conf_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 Configuration Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_mcast_conf_ctrl_construct or osm_mcast_conf_ctrl_init.
+*
+* SEE ALSO
+*      Multicast Forwarding Table Configuration Controller object, osm_mcast_conf_ctrl_construct,
+*      osm_mcast_conf_ctrl_init
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Configuration Controller/osm_mcast_conf_ctrl_init
+* NAME
+*      osm_mcast_conf_ctrl_init
+*
+* DESCRIPTION
+*      The osm_mcast_conf_ctrl_init function initializes a
+*      Multicast Forwarding Table Configuration Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_mcast_conf_ctrl_init(
+       IN osm_mcast_conf_ctrl_t* const p_ctrl,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_mcast_conf_ctrl_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.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Multicast Forwarding Table Configuration Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Multicast Forwarding Table Configuration Controller methods.
+*
+* SEE ALSO
+*      Multicast Forwarding Table Configuration Controller object, osm_mcast_conf_ctrl_construct,
+*      osm_mcast_conf_ctrl_destroy, osm_mcast_conf_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Configuration Controller/osm_mcast_conf_ctrl_is_inited
+* NAME
+*      osm_mcast_conf_ctrl_is_inited
+*
+* DESCRIPTION
+*      Indicates if the object has been initialized with osm_mcast_conf_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_mcast_conf_ctrl_is_inited(
+       IN const osm_mcast_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_mcast_conf_ctrl_t object.
+*
+* RETURN VALUES
+*      TRUE if the object was initialized successfully,
+*      FALSE otherwise.
+*
+* NOTES
+*      The osm_mcast_conf_ctrl_construct or osm_mcast_conf_ctrl_init must be
+*      called before using     this function.
+*
+* SEE ALSO
+*      Multicast Forwarding Table Configuration Controller object, osm_mcast_conf_ctrl_construct,
+*      osm_mcast_conf_ctrl_init
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Configuration Controller/osm_mcast_conf_ctrl_process
+* NAME
+*      osm_mcast_conf_ctrl_process
+*
+* DESCRIPTION
+*      Initiate a MulticastForwardingTable configuration.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_mcast_conf_ctrl_process(
+       IN const osm_mcast_conf_ctrl_t* const p_ctrl,
+       IN const ib_guid_t guid );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_mcast_conf_ctrl_t object.
+*
+*      guid
+*              [in] Node GUID of switch to configure.
+*
+* RETURN VALUES
+*      CL_SUCCESS if configuration processing was successfully
+*      initiated.
+*
+* NOTES
+*      A success status here does not indicate that
+*      the Multicast Forwarding Table configuration completed successfully.
+*
+* SEE ALSO
+*      Multicast Forwarding Table Configuration Controller
+*********/
+       
+END_C_DECLS
+
+#endif /* _OSM_MCAST_CONFIG_CTRL_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_mcast_fwd_rcv.h b/trunk/ulp/opensm/user/include/opensm/osm_mcast_fwd_rcv.h
new file mode 100644 (file)
index 0000000..9b73e8c
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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/trunk/ulp/opensm/user/include/opensm/osm_mcast_fwd_rcv_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_mcast_fwd_rcv_ctrl.h
new file mode 100644 (file)
index 0000000..b9747fa
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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/trunk/ulp/opensm/user/include/opensm/osm_mcast_mgr.h b/trunk/ulp/opensm/user/include/opensm/osm_mcast_mgr.h
new file mode 100644 (file)
index 0000000..477bf92
--- /dev/null
@@ -0,0 +1,383 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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
+* NAME
+*      osm_mcast_mgr_process_mgrp
+*
+* DESCRIPTION
+*      Processes a specific multicast group.  This function is called
+*      by the SM to process a multicast group.  Note that this function
+*      returns BEFORE the switch tables have been configured over the wire,
+*      and AFTER switch table configuration MADs are all placed in the
+*      VL15 FIFOs.  In other words, the switch table configuration is
+*      imminent but probably not yet complete at the time this call returns.
+*
+* SYNOPSIS
+*/
+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 );
+/*
+* PARAMETERS
+*      p_mgr
+*              [in] Pointer to an osm_mcast_mgr_t object.
+*
+*      p_mgrp
+*              [in] Pointer to the multicast group to process.
+*
+*  req_type
+*     [in] Type of the multicast request that caused this processing
+*          (MC create/join/leave).
+*
+*  port_guid
+*     [in] Port guid of the port that was added/removed due to this call.
+*
+* RETURN VALUES
+*      OSM_SIGNAL_DONE
+*      OSM_SIGNAL_DONE_PENDING
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****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/trunk/ulp/opensm/user/include/opensm/osm_mcast_tbl.h b/trunk/ulp/opensm/user/include/opensm/osm_mcast_tbl.h
new file mode 100644 (file)
index 0000000..7588d9d
--- /dev/null
@@ -0,0 +1,484 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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: Switch/osm_switch_get_mcast_tbl_block
+* NAME
+*      osm_switch_get_mcast_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: Switch/osm_switch_get_max_block
+* NAME
+*      osm_switch_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: Switch/osm_switch_get_max_block
+* NAME
+*      osm_switch_get_max_block
+*
+* 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: Switch/osm_switch_get_max_position
+* NAME
+*      osm_switch_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/trunk/ulp/opensm/user/include/opensm/osm_mcm_info.h b/trunk/ulp/opensm/user/include/opensm/osm_mcm_info.h
new file mode 100644 (file)
index 0000000..fe7ca2a
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <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 )
+{
+       cl_memclr( p_mcm, 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/trunk/ulp/opensm/user/include/opensm/osm_mcm_port.h b/trunk/ulp/opensm/user/include/opensm/osm_mcm_port.h
new file mode 100644 (file)
index 0000000..7a23240
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * 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$
+ */
+
+/*
+ * 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/trunk/ulp/opensm/user/include/opensm/osm_mcmember.h b/trunk/ulp/opensm/user/include/opensm/osm_mcmember.h
new file mode 100644 (file)
index 0000000..ab47ea2
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_mcmember_t.
+ *     This object represents an IBA mcmember.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_MCMEMBER_H_
+#define _OSM_MCMEMBER_H_
+
+#include <complib/cl_qmap.h>
+#include <complib/cl_qlist.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/MCMember
+* NAME
+*      MCMember
+*
+* DESCRIPTION
+*      The MCMember object encapsulates the information needed by the
+*      OpenSM to manage mcmembers.  The OpenSM allocates one MCMember object
+*      per mcmember in the IBA subnet.
+*
+*      The MCMember 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
+*      Ranjit Pandit, Intel
+*
+*********/
+/****s* OpenSM: MCMember/osm_mcmember_t
+* NAME
+*      osm_mcmember_t
+*
+* DESCRIPTION
+*      MCMember structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mcmember
+{
+       cl_map_item_t                           map_item;
+       ib_member_rec_t                         mcmember_rec;
+       cl_qlist_t                                      mcmember_port_list;
+
+} osm_mcmember_t;
+
+/*
+* FIELDS
+*      map_item
+*              Linkage structure for cl_qmap.  MUST BE FIRST MEMBER!
+*
+*      mcmember_rec
+*              The IBA defined MCMemberRecord data for this mcmember.
+*
+*      member_port_list
+*              List of Port specific information for each port that in
+*              member of a MultiCast Group.
+*
+* SEE ALSO
+*      MCMember object
+*********/
+
+/****s* OpenSM: MCMember/osm_mcmember_t
+* NAME
+*   osm_mcmember_t
+*
+* DESCRIPTION
+*   MCMember structure.
+*
+*   This object should be treated as opaque and should
+*   be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mcmember_port
+{
+    cl_list_item_t         list_item;
+       ib_gid_t                                port_gid;
+       uint8_t                                 scope_state;
+
+} osm_mcmember_port_t;
+
+/*
+* FIELDS
+*      list_item
+*              DESCRIPTION???
+*
+*      port_gid
+*              DESCRIPTION???
+*
+*      scope_state
+*              description???
+*
+* SEE ALSO
+*      MCMember object
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MCMEMBER_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_msgdef.h b/trunk/ulp/opensm/user/include/opensm/osm_msgdef.h
new file mode 100644 (file)
index 0000000..665782e
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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_MAX
+};
+
+END_C_DECLS
+
+#endif /* _OSM_MSGDEF_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_mtl_bind.h b/trunk/ulp/opensm/user/include/opensm/osm_mtl_bind.h
new file mode 100644 (file)
index 0000000..c424772
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * 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$
+ */
+
+#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/trunk/ulp/opensm/user/include/opensm/osm_mtree.h b/trunk/ulp/opensm/user/include/opensm/osm_mtree.h
new file mode 100644 (file)
index 0000000..77de6e9
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <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 )
+{
+       cl_memclr( p_mtn, 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/trunk/ulp/opensm/user/include/opensm/osm_multicast.h b/trunk/ulp/opensm/user/include/opensm/osm_multicast.h
new file mode 100644 (file)
index 0000000..17962ca
--- /dev/null
@@ -0,0 +1,769 @@
+/*
+ * 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$
+ */
+
+/*
+ * 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/trunk/ulp/opensm/user/include/opensm/osm_node.h b/trunk/ulp/opensm/user/include/opensm/osm_node.h
new file mode 100644 (file)
index 0000000..244edaf
--- /dev/null
@@ -0,0 +1,945 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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
+
+/****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;
+       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!
+*
+*      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 managment 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/trunk/ulp/opensm/user/include/opensm/osm_node_desc_rcv.h b/trunk/ulp/opensm/user/include/opensm/osm_node_desc_rcv.h
new file mode 100644 (file)
index 0000000..72cc1fe
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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/trunk/ulp/opensm/user/include/opensm/osm_node_desc_rcv_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_node_desc_rcv_ctrl.h
new file mode 100644 (file)
index 0000000..d62991a
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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/trunk/ulp/opensm/user/include/opensm/osm_node_info_rcv.h b/trunk/ulp/opensm/user/include/opensm/osm_node_info_rcv.h
new file mode 100644 (file)
index 0000000..d5e589d
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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/trunk/ulp/opensm/user/include/opensm/osm_node_info_rcv_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_node_info_rcv_ctrl.h
new file mode 100644 (file)
index 0000000..d9c9cea
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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/trunk/ulp/opensm/user/include/opensm/osm_opensm.h b/trunk/ulp/opensm/user/include/opensm/osm_opensm.h
new file mode 100644 (file)
index 0000000..d3dce38
--- /dev/null
@@ -0,0 +1,422 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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>
+#include <opensm/osm_ucast_updn.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_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;
+  updn_t         *p_updn_ucast_routing;
+  osm_stats_t          stats;
+} osm_opensm_t;
+/*
+* FIELDS
+*      subn
+*              Subnet object for this subnet.
+*
+*      sm
+*              The Subnet Manger (SM) object for this subnet.
+*
+*      sa
+*              The Subnet Administrator (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.
+*
+*      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 int osm_exit_flag;
+/* 
+* DESCRIPTION 
+*  Set to one to cause all threads to leave 
+*********/
+
+#ifndef __WIN__
+/****f* OpenSM: OpenSM/osm_reg_sig_handler
+* NAME
+*       osm_reg_sig_handler
+*
+* DESCRIPTION
+*      Registers the common signal handler
+*
+* SYNOPSIS
+*/
+void osm_reg_sig_handler(
+IN osm_opensm_t* const p_osm);
+/*
+* PARAMETERS
+*      p_osm
+*              [in] Pointer to a OpenSM object to handle signals on.
+*
+* RETURN VALUES
+*      None
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+#endif
+
+END_C_DECLS
+
+#endif /* _OSM_OPENSM_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_partition.h b/trunk/ulp/opensm/user/include/opensm/osm_partition.h
new file mode 100644 (file)
index 0000000..b4e1ed6
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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_
+
+#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
+{
+       uint16_t                                                pkey;
+       cl_map                                                  port_guid_tbl;
+
+} osm_prtn_t;
+/*
+* FIELDS
+*      pkey
+*              The IBA defined P_KEY of this Partition.
+*
+*      port_guid_tbl
+*              Container of pointers to all Port objects in the Partition,
+*              indexed by port GUID.
+*
+* SEE ALSO
+*      Partition
+*********/
+
+/****f* OpenSM: Partition/osm_prtn_construct
+* NAME
+*      osm_prtn_construct
+*
+* DESCRIPTION
+*      This function constructs a Partition.
+*
+* SYNOPSIS
+*/
+void osm_prtn_construct(
+       IN osm_prtn_t* const p_prtn );
+/*
+* PARAMETERS
+*      p_prtn
+*              [in] Pointer to a Partition to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_prtn_init, osm_prtn_destroy, and osm_prtn_is_inited.
+*
+*      Calling osm_prtn_construct is a prerequisite to calling any other
+*      method except osm_prtn_init.
+*
+* SEE ALSO
+*      Partition, osm_prtn_init, osm_prtn_destroy, osm_prtn_is_inited
+*********/
+
+/****f* OpenSM: Partition/osm_prtn_destroy
+* NAME
+*      osm_prtn_destroy
+*
+* DESCRIPTION
+*      The osm_prtn_destroy function destroys a Partition, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_prtn_destroy(
+       IN osm_prtn_t* const p_prtn );
+/*
+* PARAMETERS
+*      p_prtn
+*              [in] Pointer to a Partition to destroy.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Performs any necessary cleanup of the specified Partition.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to osm_prtn_construct or
+*      osm_prtn_init.
+*
+* SEE ALSO
+*      Partition, osm_prtn_construct, osm_prtn_init
+*********/
+
+/****f* OpenSM: Partition/osm_prtn_init
+* NAME
+*      osm_prtn_init
+*
+* DESCRIPTION
+*      The osm_prtn_init function initializes a Partition for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_prtn_init(
+       IN osm_prtn_t* const p_prtn );
+/*
+* PARAMETERS
+*      p_prtn
+*              [in] Pointer to an osm_prtn_t object to initialize.
+*
+* RETURN VALUES
+*      CL_SUCCESS if initialization was successful.
+*
+* NOTES
+*      Allows calling other Partition methods.
+*
+* SEE ALSO
+*      Partition, osm_prtn_construct, osm_prtn_destroy,
+*      osm_prtn_is_inited
+*********/
+
+/****f* OpenSM: Partition/osm_prtn_is_inited
+* NAME
+*      osm_prtn_is_inited
+*
+* DESCRIPTION
+*      Indicates if the object has been initialized with osm_prtn_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_ptrn_is_inited(
+       IN const osm_prtn_t* const p_prtn );
+/*
+* PARAMETERS
+*      p_prtn
+*              [in] Pointer to an osm_prtn_t object.
+*
+* RETURN VALUES
+*      TRUE if the object was initialized successfully,
+*      FALSE otherwise.
+*
+* NOTES
+*      The osm_prtn_construct or osm_prtn_init must be called before using
+*      this function.
+*
+* SEE ALSO
+*      Partition, osm_prtn_construct, osm_prtn_init
+*********/
+
+/****f* OpenSM: Partition/osm_prtn_is_guid
+* NAME
+*      osm_prtn_is_guid
+*
+* DESCRIPTION
+*      Indicates if a port is a member of the partition.
+*
+* SYNOPSIS
+*/
+boolean_t osm_prtn_is_guid(
+       IN const osm_prtn_t* const p_prtn,
+       IN const uint64 guid );
+/*
+* 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_get_pkey
+* NAME
+*      osm_prtn_get_pkey
+*
+* DESCRIPTION
+*      Gets the IBA defined P_KEY value for this Partition.
+*
+* SYNOPSIS
+*/
+uint16_t osm_prtn_get_pkey(
+       IN const osm_prtn_t* const p_prtn );
+/*
+* PARAMETERS
+*      p_prtn
+*              [in] Pointer to an osm_prtn_t object.
+*
+* RETURN VALUES
+*      P_KEY value for this Partition.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PARTITION_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_path.h b/trunk/ulp/opensm/user/include/opensm/osm_path.h
new file mode 100644 (file)
index 0000000..21faf3b
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * 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$
+ */
+
+
+#ifndef _OSM_PATH_H_
+#define _OSM_PATH_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. */
+       cl_memclr( p_path, sizeof(*p_path) );
+       p_path->h_bind = OSM_BIND_INVALID_HANDLE;
+}
+
+/*
+* PARAMETERS
+*      p_path
+*              [in] Pointer to a directed route path oject 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;
+       cl_memcpy( p_path->path, path, IB_SUBNET_PATH_HOPS_MAX );
+}
+
+/*
+* PARAMETERS
+*      p_path
+*              [in] Pointer to a directed route path oject 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 oject 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 oject 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/trunk/ulp/opensm/user/include/opensm/osm_pi_config_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_pi_config_ctrl.h
new file mode 100644 (file)
index 0000000..ab5ea3a
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_pi_conf_ctrl_t.
+ *     This object represents a controller that performs a 
+ *     Set(PortInfo) for the specified port.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_PI_CONFIG_CTRL_H_
+#define _OSM_PI_CONFIG_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/Port Info Configuration Controller
+* NAME
+*      Port Info Configuration Controller
+*
+* DESCRIPTION
+*      The Port Info Configuration Controller object encapsulates the
+*      information needed to Set(PortInfo) at the specified port.
+*
+*      The Port Info Configuration 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 Configuration Controller/osm_pi_conf_ctrl_t
+* NAME
+*      osm_pi_conf_ctrl_t
+*
+* DESCRIPTION
+*      Port Info Configuration Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pi_conf_ctrl
+{
+       osm_subn_t                                      *p_subn;
+       osm_log_t                                       *p_log;
+       cl_plock_t                                      *p_lock;
+       cl_dispatcher_t                         *p_disp;
+
+} osm_pi_conf_ctrl_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.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+* SEE ALSO
+*      Port Info Configuration Controller object
+*********/
+/****f* OpenSM: Port Info Configuration Controller/osm_pi_conf_ctrl_construct
+* NAME
+*      osm_pi_conf_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Port Info Configuration Controller object.
+*
+* SYNOPSIS
+*/
+void osm_pi_conf_ctrl_construct(
+       IN osm_pi_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Port Info Configuration Controller object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_pi_conf_ctrl_init, osm_pi_conf_ctrl_destroy,
+*      and osm_pi_conf_ctrl_is_inited.
+*
+*      Calling osm_pi_conf_ctrl_construct is a prerequisite to calling any other
+*      method except osm_pi_conf_ctrl_init.
+*
+* SEE ALSO
+*      Port Info Configuration Controller object, osm_pi_conf_ctrl_init,
+*      osm_pi_conf_ctrl_destroy, osm_pi_conf_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Port Info Configuration Controller/osm_pi_conf_ctrl_destroy
+* NAME
+*      osm_pi_conf_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_pi_conf_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_pi_conf_ctrl_destroy(
+       IN osm_pi_conf_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 Configuration Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_pi_conf_ctrl_construct or osm_pi_conf_ctrl_init.
+*
+* SEE ALSO
+*      Port Info Configuration Controller object, osm_pi_conf_ctrl_construct,
+*      osm_pi_conf_ctrl_init
+*********/
+
+/****f* OpenSM: Port Info Configuration Controller/osm_pi_conf_ctrl_init
+* NAME
+*      osm_pi_conf_ctrl_init
+*
+* DESCRIPTION
+*      The osm_pi_conf_ctrl_init function initializes a
+*      Port Info Configuration Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pi_conf_ctrl_init(
+       IN osm_pi_conf_ctrl_t* const p_ctrl,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_pi_conf_ctrl_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.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the Port Info Configuration Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Port Info Configuration Controller methods.
+*
+* SEE ALSO
+*      Port Info Configuration Controller object, osm_pi_conf_ctrl_construct,
+*      osm_pi_conf_ctrl_destroy, osm_pi_conf_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Port Info Configuration Controller/osm_pi_conf_ctrl_is_inited
+* NAME
+*      osm_pi_conf_ctrl_is_inited
+*
+* DESCRIPTION
+*      Indicates if the object has been initialized with osm_pi_conf_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_pi_conf_ctrl_is_inited(
+       IN const osm_pi_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_pi_conf_ctrl_t object.
+*
+* RETURN VALUES
+*      TRUE if the object was initialized successfully,
+*      FALSE otherwise.
+*
+* NOTES
+*      The osm_pi_conf_ctrl_construct or osm_pi_conf_ctrl_init must be
+*      called before using     this function.
+*
+* SEE ALSO
+*      Port Info Configuration Controller object, osm_pi_conf_ctrl_construct,
+*      osm_pi_conf_ctrl_init
+*********/
+
+/****f* OpenSM: Port Info Configuration Controller/osm_pi_conf_ctrl_process
+* NAME
+*      osm_pi_conf_ctrl_process
+*
+* DESCRIPTION
+*      Initiate a PortInfo configuration.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pi_conf_ctrl_process(
+       IN const osm_pi_conf_ctrl_t* const p_ctrl,
+       IN const ib_guid_t guid );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_pi_conf_ctrl_t object.
+*
+*      guid
+*              [in] GUID of port to configure.
+*
+* RETURN VALUES
+*      CL_SUCCESS if configuration processing was successfully
+*      initiated.
+*
+* NOTES
+*      A success status here does not indicate that
+*      the PortInfo configuration process completed successfully.
+*
+* SEE ALSO
+*      Port Info Configuration Controller
+*********/
+       
+END_C_DECLS
+
+#endif /* _OSM_PI_CONFIG_CTRL_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_pkey.h b/trunk/ulp/opensm/user/include/opensm/osm_pkey.h
new file mode 100644 (file)
index 0000000..b2d405a
--- /dev/null
@@ -0,0 +1,489 @@
+/*
+ * 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$
+ */
+
+#ifndef _OSM_PKEY_H_
+#define _OSM_PKEY_H_
+
+#include <iba/ib_types.h>
+#include <opensm/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_map_t        keys;
+} osm_pkey_tbl_t;
+/*
+* FIELDS
+*      blocks
+*              The IBA defined blocks of pkey values
+*
+*      keys
+*              A set holding all keys
+*
+*********/
+
+/****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
+*/
+int 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 pointer to the IB PKey table block stored in the object
+*
+* 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)
+{
+  CL_ASSERT(block < cl_ptr_vector_get_size(&p_pkey_tbl->blocks));
+  return(cl_ptr_vector_get(&p_pkey_tbl->blocks, block));
+};
+/*
+*  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_set
+* NAME
+*  osm_pkey_tbl_set
+*
+* DESCRIPTION
+*  Set the PKey table block provided in the PKey object.
+*
+* SYNOPSIS
+*/
+int 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_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/trunk/ulp/opensm/user/include/opensm/osm_pkey_config_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_pkey_config_ctrl.h
new file mode 100644 (file)
index 0000000..070399d
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_pkey_conf_ctrl_t.
+ *     This object represents a controller that performs a 
+ *     Set(P_KeyTable) for the specified port.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_PKEY_CONFIG_CTRL_H_
+#define _OSM_PKEY_CONFIG_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/P_Key Table Configuration Controller
+* NAME
+*      P_Key Table Configuration Controller
+*
+* DESCRIPTION
+*      The P_Key Table Configuration Controller object encapsulates the
+*      information needed to Set(PortInfo) at the specified port.
+*
+*      The P_Key Table Configuration 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: P_Key Table Configuration Controller/osm_pkey_conf_ctrl_t
+* NAME
+*      osm_pkey_conf_ctrl_t
+*
+* DESCRIPTION
+*      P_Key Table Configuration Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pkey_conf_ctrl
+{
+       osm_subn_t                                      *p_subn;
+       osm_log_t                                       *p_log;
+       cl_plock_t                                      *p_lock;
+       cl_dispatcher_t                         *p_disp;
+
+} osm_pkey_conf_ctrl_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.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+* SEE ALSO
+*      P_Key Table Configuration Controller object
+*********/
+/****f* OpenSM: P_Key Table Configuration Controller/osm_pkey_conf_ctrl_construct
+* NAME
+*      osm_pkey_conf_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a P_Key Table Configuration Controller object.
+*
+* SYNOPSIS
+*/
+void osm_pkey_conf_ctrl_construct(
+       IN osm_pkey_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a P_Key Table Configuration Controller object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_pkey_conf_ctrl_init, osm_pkey_conf_ctrl_destroy,
+*      and osm_pkey_conf_ctrl_is_inited.
+*
+*      Calling osm_pkey_conf_ctrl_construct is a prerequisite to calling any other
+*      method except osm_pkey_conf_ctrl_init.
+*
+* SEE ALSO
+*      P_Key Table Configuration Controller object, osm_pkey_conf_ctrl_init,
+*      osm_pkey_conf_ctrl_destroy, osm_pkey_conf_ctrl_is_inited
+*********/
+
+/****f* OpenSM: P_Key Table Configuration Controller/osm_pkey_conf_ctrl_destroy
+* NAME
+*      osm_pkey_conf_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_pkey_conf_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_pkey_conf_ctrl_destroy(
+       IN osm_pkey_conf_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 Table Configuration Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_pkey_conf_ctrl_construct or osm_pkey_conf_ctrl_init.
+*
+* SEE ALSO
+*      P_Key Table Configuration Controller object, osm_pkey_conf_ctrl_construct,
+*      osm_pkey_conf_ctrl_init
+*********/
+
+/****f* OpenSM: P_Key Table Configuration Controller/osm_pkey_conf_ctrl_init
+* NAME
+*      osm_pkey_conf_ctrl_init
+*
+* DESCRIPTION
+*      The osm_pkey_conf_ctrl_init function initializes a
+*      P_Key Table Configuration Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pkey_conf_ctrl_init(
+       IN osm_pkey_conf_ctrl_t* const p_ctrl,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_pkey_conf_ctrl_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.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the P_Key Table Configuration Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other P_Key Table Configuration Controller methods.
+*
+* SEE ALSO
+*      P_Key Table Configuration Controller object, osm_pkey_conf_ctrl_construct,
+*      osm_pkey_conf_ctrl_destroy, osm_pkey_conf_ctrl_is_inited
+*********/
+
+/****f* OpenSM: P_Key Table Configuration Controller/osm_pkey_conf_ctrl_is_inited
+* NAME
+*      osm_pkey_conf_ctrl_is_inited
+*
+* DESCRIPTION
+*      Indicates if the object has been initialized with osm_pkey_conf_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_pkey_conf_ctrl_is_inited(
+       IN const osm_pkey_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_pkey_conf_ctrl_t object.
+*
+* RETURN VALUES
+*      TRUE if the object was initialized successfully,
+*      FALSE otherwise.
+*
+* NOTES
+*      The osm_pkey_conf_ctrl_construct or osm_pkey_conf_ctrl_init must be
+*      called before using     this function.
+*
+* SEE ALSO
+*      P_Key Table Configuration Controller object, osm_pkey_conf_ctrl_construct,
+*      osm_pkey_conf_ctrl_init
+*********/
+
+/****f* OpenSM: P_Key Table Configuration Controller/osm_pkey_conf_ctrl_process
+* NAME
+*      osm_pkey_conf_ctrl_process
+*
+* DESCRIPTION
+*      Initiate a P_KeyTable configuration.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pkey_conf_ctrl_process(
+       IN const osm_pkey_conf_ctrl_t* const p_ctrl,
+       IN const ib_guid_t guid );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_pkey_conf_ctrl_t object.
+*
+*      guid
+*              [in] GUID of port to configure.
+*
+* RETURN VALUES
+*      CL_SUCCESS if configuration processing was successfully
+*      initiated.
+*
+* NOTES
+*      A success status here does not indicate that
+*      the P_Key Table configuration completed successfully.
+*
+* SEE ALSO
+*      P_Key Table Configuration Controller
+*********/
+       
+END_C_DECLS
+
+#endif /* _OSM_PKEY_CONFIG_CTRL_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_pkey_rcv.h b/trunk/ulp/opensm/user/include/opensm/osm_pkey_rcv.h
new file mode 100644 (file)
index 0000000..b97987a
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * 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$
+ */
+
+
+
+#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/trunk/ulp/opensm/user/include/opensm/osm_pkey_rcv_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_pkey_rcv_ctrl.h
new file mode 100644 (file)
index 0000000..459c1b8
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * 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$
+ */
+
+
+
+#ifndef _OSM_PKEY_RCV_CTRL_H_
+#define _OSM_PKEY_RCV_CTRL_H_
+
+
+#include <opensm/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/trunk/ulp/opensm/user/include/opensm/osm_port.h b/trunk/ulp/opensm/user/include/opensm/osm_port.h
new file mode 100644 (file)
index 0000000..21cf041
--- /dev/null
@@ -0,0 +1,1980 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <complib/cl_qmap.h>
+#include <complib/cl_memory.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 each 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, port_estroy, osm_port_is_inited
+*********/
+/****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.
+*
+* 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 ) );
+       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_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_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
+*      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_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 dispostion.
+*
+* 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 )
+{
+       cl_memclr( p_port, sizeof(*p_port) );
+       cl_qlist_init( &p_port->mcm_list );
+}
+/*
+* PARAMETERS
+*      p_port
+*              [in] Pointer to a Port oject to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_port_init, osm_port_destroy, and osm_port_is_inited.
+*
+*      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, osm_port_is_inited
+*********/
+
+/****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 oject 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, osm_port_is_inited
+*********/
+/****f* OpenSM: Port/osm_port_destroy
+* NAME
+*      osm_port_destroy
+*
+* 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 );
+       cl_free( *pp_port );
+       *pp_port = NULL;
+}
+/*
+* PARAMETERS
+*      pp_port
+*              [in][out] Pointer to a pointer to a Port oject 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 oject 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 oject.
+*
+* 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 oject.
+*
+* 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 oject.
+*
+* 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 oject.
+*
+* 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 oject.
+*
+*      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_phys_ptr
+* NAME
+*      osm_port_get_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 oject.
+*
+* 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 specified Physical Port 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 oject.
+*
+*      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 oject.
+*
+*      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_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 oject.
+*
+*      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/trunk/ulp/opensm/user/include/opensm/osm_port_info_rcv.h b/trunk/ulp/opensm/user/include/opensm/osm_port_info_rcv.h
new file mode 100644 (file)
index 0000000..c2e0b21
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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
+*      CL_SUCCESS if the PortInfo processing was successful.
+*
+* 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/trunk/ulp/opensm/user/include/opensm/osm_port_info_rcv_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_port_info_rcv_ctrl.h
new file mode 100644 (file)
index 0000000..dd0c1e4
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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/trunk/ulp/opensm/user/include/opensm/osm_port_profile.h b/trunk/ulp/opensm/user/include/opensm/osm_port_profile.h
new file mode 100644 (file)
index 0000000..de20850
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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.7 $
+ */
+
+#ifndef _OSM_PORT_PROFILE_H_
+#define _OSM_PORT_PROFILE_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_pro_construct
+* NAME
+*      osm_port_pro_construct
+*
+* DESCRIPTION
+*      
+*
+* SYNOPSIS
+*/
+static inline void
+osm_port_pro_construct(
+       IN osm_port_profile_t* const p_pro )
+{
+       CL_ASSERT( p_pro );
+       cl_memclr( p_pro, sizeof(*p_pro) );
+}
+/*
+* PARAMETERS
+*      p_pro
+*              [in] Pointer to the Port Profile object to construct.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Port Profile/osm_port_pro_path_count_inc
+* NAME
+*      osm_port_pro_path_count_inc
+*
+* DESCRIPTION
+*      Increments the count of the number of paths going through this port.
+*      
+*
+* SYNOPSIS
+*/
+static inline void
+osm_port_pro_path_count_inc(
+       IN osm_port_profile_t* const p_pro )
+{
+       CL_ASSERT( p_pro );
+       p_pro->num_paths++;
+}
+/*
+* PARAMETERS
+*      p_pro
+*              [in] Pointer to the Port Profile object.
+*
+* RETURN VALUE
+*      None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Port Profile/osm_port_pro_path_count_get
+* NAME
+*      osm_port_pro_path_count_get
+*
+* DESCRIPTION
+*      Returns the count of the number of paths going through this port.
+*
+* SYNOPSIS
+*/
+static inline uint32_t
+osm_port_pro_path_count_get(
+       IN const osm_port_profile_t* const p_pro )
+{
+       return( p_pro->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_pro_is_ignored_port
+* NAME
+*      osm_port_pro_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_pro_ignore_guids.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_port_pro_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_pro_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_pro_set_ignored_port
+* NAME
+*      osm_port_pro_set_ignored_port
+*
+* DESCRIPTION
+*      Set the ignored property of the port.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_port_pro_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_pro_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 | (1 << port_num);
+  cl_map_insert(&(p_subn->opt.port_pro_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/trunk/ulp/opensm/user/include/opensm/osm_rand_fwd_tbl.h b/trunk/ulp/opensm/user/include/opensm/osm_rand_fwd_tbl.h
new file mode 100644 (file)
index 0000000..74130c7
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <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 Fowarding 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!
+       */
+       cl_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/trunk/ulp/opensm/user/include/opensm/osm_remote_sm.h b/trunk/ulp/opensm/user/include/opensm/osm_remote_sm.h
new file mode 100644 (file)
index 0000000..8ce22a9
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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;
+       boolean_t                                                       is_opensm;
+
+} 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.
+*
+*      is_opensm
+*              TRUE if this SM is an OpenSM.
+*              FALSE otherwise.
+*
+* 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
+*/
+ib_api_status_t
+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
+*      IB_SUCCESS if the SM object was initialized successfully.
+*
+* 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/trunk/ulp/opensm/user/include/opensm/osm_req.h b/trunk/ulp/opensm/user/include/opensm/osm_req.h
new file mode 100644 (file)
index 0000000..72e4ff0
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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, osm_req_destroy,
+*      and osm_req_is_inited.
+*
+*      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, osm_req_is_inited
+*********/
+
+/****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, osm_req_is_inited
+*********/
+
+/****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 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.
+*
+*      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/trunk/ulp/opensm/user/include/opensm/osm_req_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_req_ctrl.h
new file mode 100644 (file)
index 0000000..960143b
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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, osm_req_ctrl_destroy,
+*      and osm_req_ctrl_is_inited.
+*
+*      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, osm_req_ctrl_is_inited
+*********/
+
+/****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,
+*      osm_req_ctrl_is_inited
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_REQ_CTRL_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_resp.h b/trunk/ulp/opensm/user/include/opensm/osm_resp.h
new file mode 100644 (file)
index 0000000..3d3c107
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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/trunk/ulp/opensm/user/include/opensm/osm_sa.h b/trunk/ulp/opensm/user/include/opensm/osm_sa.h
new file mode 100644 (file)
index 0000000..afd79c9
--- /dev/null
@@ -0,0 +1,524 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/osm_stats.h>
+#include <opensm/cl_dispatcher.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_link_record_ctrl.h>
+#include <opensm/osm_sa_path_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>
+
+#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 Administrator 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_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;
+       
+  /* 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;
+  
+} 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
+*********/
+
+/****f* OpenSM: SA/osm_sa_add_well_known_mc_record
+* NAME
+*      osm_sa_add_well_known_mc_record
+*
+* DESCRIPTION
+*      Adds the well known Multicast group to the SA database. This 
+*      should be called by SM before programming the switches and after
+*      SA has been initialized
+*
+* SYNOPSIS
+*/
+
+void
+osm_sa_add_well_known_mc_record(
+       osm_mcmr_recv_t* const p_ctrl,
+       const ib_member_rec_t * const p_well_know_mc_rec);
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_mcmr_recv_t object.
+*
+*      p_well_know_mc_rec
+*              [in] pointer to ib_member_rec_t structure.
+*
+*
+* RETURN VALUES
+*      None
+*
+* NOTES
+*      Called by SM after SA has been initialized and before programming the switches
+*
+* SEE ALSO
+*********/
+
+
+/****f* OpenSM: SA/osm_sa_create_template_record_ipoib
+* NAME
+*      osm_sa_create_template_record_ipoib
+*
+* DESCRIPTION
+*      Creates the well known MC record and calls osm_sa_add_well_known_mc_record. This 
+*      should be called by SM before programming the switches and after
+*      SA has been initialized
+*
+* SYNOPSIS
+*/
+void
+osm_sa_create_template_record_ipoib(
+       IN osm_sa_t* const p_sa,
+       IN const osm_subn_opt_t* const p_opt );
+
+/*
+* PARAMETERS
+*      p_sa
+*              [in] Pointer to an osm_sa_t object.
+*
+*      p_opt
+*              [in] pointer to cmd line option structure.
+*
+*
+* RETURN VALUES
+*      None
+*
+* NOTES
+*      Called by SM after SA has been initialized and before programming the switches
+*
+* SEE ALSO
+*********/
+
+/****g* OpenSM: SA/osm_ipoib_mgid
+* NAME
+*      osm_ipoib_mgid
+*
+* DESCRIPTION
+*      The MGID of the IPoIB Multicast Group
+*
+* SYNOPSIS
+*/
+extern ib_gid_t osm_ipoib_mgid;
+/*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif         /* _OSM_SA_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_class_port_info.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_class_port_info.h
new file mode 100644 (file)
index 0000000..6ea1929
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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/trunk/ulp/opensm/user/include/opensm/osm_sa_class_port_info_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_class_port_info_ctrl.h
new file mode 100644 (file)
index 0000000..2a558b3
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_pr_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.2 $
+ */
+
+
+#ifndef _OSM_CPICTRL_H_
+#define _OSM_CPICTRL_H_
+
+
+#include <opensm/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/trunk/ulp/opensm/user/include/opensm/osm_sa_informinfo.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_informinfo.h
new file mode 100644 (file)
index 0000000..f8d6be8
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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;
+} 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.
+*
+* 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
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SA_INFR_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_informinfo_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_informinfo_ctrl.h
new file mode 100644 (file)
index 0000000..69873f7
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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;
+  
+} 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/trunk/ulp/opensm/user/include/opensm/osm_sa_lft_record.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_lft_record.h
new file mode 100644 (file)
index 0000000..83047f2
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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.
+*
+* 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/trunk/ulp/opensm/user/include/opensm/osm_sa_lft_record_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_lft_record_ctrl.h
new file mode 100644 (file)
index 0000000..5ca80cb
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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 LinearFowrardingTable attribute
+*  from a switch node.
+*
+*      The Linear Forwarding Table 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/trunk/ulp/opensm/user/include/opensm/osm_sa_link_record.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_link_record.h
new file mode 100644 (file)
index 0000000..694e28c
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 reponder.
+*
+*      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, Node Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LR_RCV_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_link_record_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_link_record_ctrl.h
new file mode 100644 (file)
index 0000000..60615f8
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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 Recrod Receive Controller
+* NAME
+*      Link Recrod Receive Controller
+*
+* DESCRIPTION
+*      The Link Recrod Receive Controller object encapsulates
+*      the information needed to receive the NodeInfo attribute from a node.
+*
+*      The Link Recrod 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 Recrod Receive Controller/osm_lr_rcv_ctrl_t
+* NAME
+*      osm_lr_rcv_ctrl_t
+*
+* DESCRIPTION
+*      Link Recrod 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 Recrod 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 Recrod Receive Controller/osm_lr_rcv_ctrl_construct
+* NAME
+*      osm_lr_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Link Recrod 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 Recrod 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 Recrod Receive Controller object, osm_lr_rcv_ctrl_init,
+*      osm_lr_rcv_ctrl_destroy, osm_lr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Link Recrod 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 Recrod 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 Recrod Receive Controller object, osm_lr_rcv_ctrl_construct,
+*      osm_lr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Link Recrod Receive Controller/osm_lr_rcv_ctrl_init
+* NAME
+*      osm_lr_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_lr_rcv_ctrl_init function initializes a
+*      Link Recrod 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 Recrod Receive Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Link Recrod Receive Controller methods.
+*
+* SEE ALSO
+*      Link Recrod Receive Controller object, osm_lr_rcv_ctrl_construct,
+*      osm_lr_rcv_ctrl_destroy, osm_lr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Link Recrod 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 Recrod Receive Controller object, osm_lr_rcv_ctrl_construct,
+*      osm_lr_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LR_CTRL_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_mad_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_mad_ctrl.h
new file mode 100644 (file)
index 0000000..8107b2e
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_sa_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_SA_MAD_CTRL_H_
+#define _OSM_SA_MAD_CTRL_H_
+
+#include <opensm/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, osm_sa_mad_ctrl_destroy,
+*      and osm_sa_mad_ctrl_is_inited.
+*
+*      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, osm_sa_mad_ctrl_is_inited
+*********/
+
+/****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, osm_sa_mad_ctrl_is_inited
+*********/
+
+/****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/trunk/ulp/opensm/user/include/opensm/osm_sa_mcmember_record.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_mcmember_record.h
new file mode 100644 (file)
index 0000000..af2d1bf
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_mcmr_recv_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.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/Node Info Receiver
+* NAME
+*      Node Info Receiver
+*
+* DESCRIPTION
+*      The Node Info Receiver object encapsulates the information
+*      needed to receive the NodeRecord 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
+*      Anil Keshavamurthy, Intel
+*
+*********/
+/****s* OpenSM: Node Info Receiver/osm_mcmr_recv_t
+* NAME
+*      osm_mcmr_recv_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_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
+*      Node Info Receiver object
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_mcmr_rcv_construct
+* NAME
+*      osm_mcmr_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a Node Info Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_mcmr_rcv_construct(
+       IN osm_mcmr_recv_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_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
+*      Node Info Receiver object, osm_mcmr_init,
+*      osm_mcmr_rcv_destroy
+*********/
+
+/****f* OpenSM: Node Info 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
+*      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_mcmr_rcv_construct or osm_mcmr_init.
+*
+* SEE ALSO
+*      Node Info Receiver object, osm_mcmr_rcv_construct,
+*      osm_mcmr_init
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_mcmr_rcv_init
+* NAME
+*      osm_mcmr_init
+*
+* DESCRIPTION
+*      The osm_mcmr_init function initializes a
+*      Node Info 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 Node Info Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Node Info Receiver methods.
+*
+* SEE ALSO
+*      Node Info Receiver object, osm_mcmr_rcv_construct,
+*      osm_mcmr_rcv_destroy
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_mcmr_mcmrocess
+* NAME
+*      osm_mcmr_mcmrocess
+*
+* DESCRIPTION
+*      Process the NodeRecord 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 NodeRecord attribute.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the NodeRecord processing was successful.
+*
+* NOTES
+*      This function processes a NodeRecord attribute.
+*
+* SEE ALSO
+*      Node Info Receiver, Node Info 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, 
+                                                                         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 (256 bytes)
+*  Note it includes the MTUSelector which is set to "Greater Then"
+*  But this means really greater or equal ...
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_MGRP_MTU 0x01
+/***********/
+
+/****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 Then"
+*  But this means really greater or equal ...
+*
+* SYNOPSIS
+*/
+#define OSM_DEFAULT_MGRP_RATE 0x03
+/***********/
+
+/* These Component Mask fields comply with IB Spec 1.0.M3 */
+#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/trunk/ulp/opensm/user/include/opensm/osm_sa_mcmember_record_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_mcmember_record_ctrl.h
new file mode 100644 (file)
index 0000000..b295c43
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_mcmr_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_MCMRCTRL_H
+#define _OSM_MCMRCTRL_H
+
+
+#include <opensm/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/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
+*      Ranjit Pandit, Intel
+*
+*********/
+/****s* OpenSM: Node Info Receive Controller/osm_mcmr_rcv_ctrl_t
+* NAME
+*      osm_mcmr_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_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 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_mcmr_rcv_ctrl_construct
+* NAME
+*      osm_mcmr_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Node Info 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 Node Info 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
+*      Node Info Receive Controller object, osm_mcmr_rcv_ctrl_init,
+*      osm_mcmr_rcv_ctrl_destroy, osm_mcmr_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Node Info 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
+*      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_mcmr_rcv_ctrl_construct or osm_mcmr_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Node Info Receive Controller object, osm_mcmr_rcv_ctrl_construct,
+*      osm_mcmr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_mcmr_rcv_ctrl_init
+* NAME
+*      osm_mcmr_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_mcmr_rcv_ctrl_init function initializes a
+*      Node Info 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 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_mcmr_rcv_ctrl_construct,
+*      osm_mcmr_rcv_ctrl_destroy, osm_mcmr_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Node Info 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
+*      Node Info Receive Controller object, osm_mcmr_rcv_ctrl_construct,
+*      osm_mcmr_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MCMRCTRL_H */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_node_record.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_node_record.h
new file mode 100644 (file)
index 0000000..5d41ed2
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 reponder.
+*
+*      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/trunk/ulp/opensm/user/include/opensm/osm_sa_node_record_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_node_record_ctrl.h
new file mode 100644 (file)
index 0000000..2da33ee
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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/trunk/ulp/opensm/user/include/opensm/osm_sa_path_record.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_path_record.h
new file mode 100644 (file)
index 0000000..23f65fd
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 reponses.
+*
+* 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, Node Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PR_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_path_record_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_path_record_ctrl.h
new file mode 100644 (file)
index 0000000..4e18ff4
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_pr_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_PRCTRL_H_
+#define _OSM_PRCTRL_H_
+
+
+#include <opensm/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/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
+*      Ranjit Pandit, Intel
+*
+*********/
+/****s* OpenSM: Node Info Receive Controller/osm_pr_rcv_ctrl_t
+* NAME
+*      osm_pr_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_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 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_pr_rcv_ctrl_construct
+* NAME
+*      osm_pr_rcv_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Node Info 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 Node Info 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
+*      Node Info Receive Controller object, osm_pr_rcv_ctrl_init,
+*      osm_pr_rcv_ctrl_destroy, osm_pr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Node Info 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
+*      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_pr_rcv_ctrl_construct or osm_pr_rcv_ctrl_init.
+*
+* SEE ALSO
+*      Node Info Receive Controller object, osm_pr_rcv_ctrl_construct,
+*      osm_pr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_pr_rcv_ctrl_init
+* NAME
+*      osm_pr_rcv_ctrl_init
+*
+* DESCRIPTION
+*      The osm_pr_rcv_ctrl_init function initializes a
+*      Node Info 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 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_pr_rcv_ctrl_construct,
+*      osm_pr_rcv_ctrl_destroy, osm_pr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Node Info 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
+*      Node Info Receive Controller object, osm_pr_rcv_ctrl_construct,
+*      osm_pr_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PRCTRL_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_pkey_record.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_pkey_record.h
new file mode 100644 (file)
index 0000000..89362e8
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * 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$
+ */
+
+
+
+#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 reponder.
+*
+*  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/trunk/ulp/opensm/user/include/opensm/osm_sa_pkey_record_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_pkey_record_ctrl.h
new file mode 100644 (file)
index 0000000..b71f33a
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * 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$
+ */
+
+
+
+#ifndef _OSM_PKEY_REC_CTRL_H_
+#define _OSM_PKEY_REC_CTRL_H_
+
+
+#include <opensm/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/trunk/ulp/opensm/user/include/opensm/osm_sa_portinfo_record.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_portinfo_record.h
new file mode 100644 (file)
index 0000000..89ad79c
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_pir_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_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 NodeRecord 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
+{
+       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_pir_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+*      p_resp
+*              Pointer to the SA reponder.
+*
+*      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 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_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 NodeRecord 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 NodeRecord attribute.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the NodeRecord processing was successful.
+*
+* NOTES
+*      This function processes a NodeRecord attribute.
+*
+* SEE ALSO
+*      PortInfo Record Receiver, PortInfo Record Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PIR_RCV_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_portinfo_record_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_portinfo_record_ctrl.h
new file mode 100644 (file)
index 0000000..81bea3b
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_pir_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_PIR_CTRL_H_
+#define _OSM_PIR_CTRL_H_
+
+
+#include <opensm/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 NodeInfo 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/trunk/ulp/opensm/user/include/opensm/osm_sa_response.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_response.h
new file mode 100644 (file)
index 0000000..a7c2369
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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, osm_sa_resp_destroy,
+*      and osm_sa_resp_is_inited.
+*
+*      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, osm_sa_resp_is_inited
+*********/
+
+/****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, osm_sa_resp_is_inited
+*********/
+
+/****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 reponse 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, osm_sa_resp_is_inited
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SA_RESP_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_service_record.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_service_record.h
new file mode 100644 (file)
index 0000000..a5ca56e
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 reponses.
+*
+* 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/trunk/ulp/opensm/user/include/opensm/osm_sa_service_record_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_service_record_ctrl.h
new file mode 100644 (file)
index 0000000..464a28e
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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/trunk/ulp/opensm/user/include/opensm/osm_sa_slvl_record.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_slvl_record.h
new file mode 100644 (file)
index 0000000..9a5de46
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 reponder.
+*
+*      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/trunk/ulp/opensm/user/include/opensm/osm_sa_slvl_record_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_slvl_record_ctrl.h
new file mode 100644 (file)
index 0000000..0acfc62
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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/trunk/ulp/opensm/user/include/opensm/osm_sa_sminfo_record.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_sminfo_record.h
new file mode 100644 (file)
index 0000000..d67977d
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_smir_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_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/Node Info Receiver
+* NAME
+*      Node Info Receiver
+*
+* DESCRIPTION
+*      The Node Info Receiver object encapsulates the information
+*      needed to receive the NodeRecord 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
+*      Ranjit Pandit, Intel
+*
+*********/
+/****s* OpenSM: Node Info Receiver/osm_smir_rcv_t
+* NAME
+*      osm_smir_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_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;
+
+} osm_smir_rcv_t;
+/*
+* FIELDS
+*      p_subn
+*              Pointer to the Subnet object for this subnet.
+*
+* SEE ALSO
+*      Node Info Receiver object
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_smir_rcv_construct
+* NAME
+*      osm_smir_rcv_construct
+*
+* DESCRIPTION
+*      This function constructs a Node Info Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_smir_rcv_construct(
+       IN osm_smir_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_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
+*      Node Info Receiver object, osm_smir_rcv_init, osm_smir_rcv_destroy
+*********/
+
+/****f* OpenSM: Node 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
+*      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_smir_rcv_construct or osm_smir_rcv_init.
+*
+* SEE ALSO
+*      Node Info Receiver object, osm_smir_rcv_construct,
+*      osm_smir_rcv_init
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_smir_rcv_init
+* NAME
+*      osm_smir_rcv_init
+*
+* DESCRIPTION
+*      The osm_smir_rcv_init function initializes a
+*      Node 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 Node Info Receiver object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Node Info Receiver methods.
+*
+* SEE ALSO
+*      Node Info Receiver object, osm_smir_rcv_construct, osm_smir_rcv_destroy
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_smir_rcv_process
+* NAME
+*      osm_smir_rcv_process
+*
+* DESCRIPTION
+*      Process the NodeRecord 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 NodeRecord attribute.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the NodeRecord processing was successful.
+*
+* NOTES
+*      This function processes a NodeRecord attribute.
+*
+* SEE ALSO
+*      Node Info Receiver, Node Info Response Controller
+*********/
+#if 0
+/*
+  These Component Mask fields comply with IB Spec 1.0.M3
+*/
+#define SMIR_LID_COMPMASK              0x1
+#define SMIR_GUID_COMPMASK             0x4
+#define SMIR_SMKEY_COMPMASK            0x8
+#define SMIR_ACTCOUNT_COMPMASK 0x10 
+#define SMIR_PRIORITY_COMPMASK 0x20
+#define SMIR_STATE_COMPMASK            0x40
+#endif
+
+END_C_DECLS
+
+#endif /* _OSM_SMIR_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_sminfo_record_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_sminfo_record_ctrl.h
new file mode 100644 (file)
index 0000000..fd3cd5e
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_smir_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_SMIR_CTRL_H_
+#define _OSM_SMIR_CTRL_H_
+
+
+#include <opensm/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/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
+*      Ranjit Pandit, Intel
+*
+*********/
+/****s* OpenSM: Node Info Receive Controller/osm_smir_ctrl_t
+* NAME
+*      osm_smir_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_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 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_smir_ctrl_construct
+* NAME
+*      osm_smir_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Node 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 Node 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
+*      Node Info Receive Controller object, osm_smir_ctrl_init,
+*      osm_smir_ctrl_destroy
+*********/
+
+/****f* OpenSM: Node 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
+*      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_smir_ctrl_construct or osm_smir_ctrl_init.
+*
+* SEE ALSO
+*      Node Info Receive Controller object, osm_smir_ctrl_construct,
+*      osm_smir_ctrl_init
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_smir_ctrl_init
+* NAME
+*      osm_smir_ctrl_init
+*
+* DESCRIPTION
+*      The osm_smir_ctrl_init function initializes a
+*      Node 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 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_smir_ctrl_construct,
+*      osm_smir_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SMIR_CTRL_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sa_vlarb_record.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_vlarb_record.h
new file mode 100644 (file)
index 0000000..3522d15
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_vlarb_rec_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.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 reponder.
+*
+*      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/trunk/ulp/opensm/user/include/opensm/osm_sa_vlarb_record_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sa_vlarb_record_ctrl.h
new file mode 100644 (file)
index 0000000..4698e37
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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/trunk/ulp/opensm/user/include/opensm/osm_service.h b/trunk/ulp/opensm/user/include/opensm/osm_service.h
new file mode 100644 (file)
index 0000000..dde2369
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * 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$
+ */
+
+
+#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_net64_t                                              svc_id;
+       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/trunk/ulp/opensm/user/include/opensm/osm_slvl_map_rcv.h b/trunk/ulp/opensm/user/include/opensm/osm_slvl_map_rcv.h
new file mode 100644 (file)
index 0000000..fddfaae
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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/trunk/ulp/opensm/user/include/opensm/osm_slvl_map_rcv_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_slvl_map_rcv_ctrl.h
new file mode 100644 (file)
index 0000000..29bfeec
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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/trunk/ulp/opensm/user/include/opensm/osm_sm.h b/trunk/ulp/opensm/user/include/opensm/osm_sm.h
new file mode 100644 (file)
index 0000000..78efd12
--- /dev/null
@@ -0,0 +1,567 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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;
+  char*                    p_report_buf;
+
+} 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_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_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_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
+*********/
+
+END_C_DECLS
+
+#endif         /* _OSM_SM_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sm_info_get_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sm_info_get_ctrl.h
new file mode 100644 (file)
index 0000000..52a43ce
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_smi_get_ctrl_t.
+ *     This object represents a controller that receives the IBA SMInfo
+ *     query from a node.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SM_INFO_GET_CTRL_H_
+#define _OSM_SM_INFO_GET_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/SM Info Get Controller
+* NAME
+*      SM Info Get Controller
+*
+* DESCRIPTION
+*      The SM Info Get Controller object encapsulates the information
+*      needed to handle the SwitchInfo query from a node.
+*
+*      The SM Info Get 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 Info Get Controller/osm_smi_get_ctrl_t
+* NAME
+*      osm_smi_get_ctrl_t
+*
+* DESCRIPTION
+*      SM Info Get Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_smi_get_ctrl
+{
+       osm_sminfo_t                            *p_smi;
+       osm_mad_pool_t                          *p_pool;
+       osm_log_t                                       *p_log;
+       cl_plock_t                                      *p_lock;
+       cl_dispatcher_t                         *p_disp;
+
+} osm_smi_get_ctrl_t;
+/*
+* FIELDS
+*      p_smi
+*              Pointer to the SM Info object of the SM.
+*
+*      p_pool
+*              Pointer to the MAD pool.
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      p_lock
+*              Pointer to the serializing lock.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+* SEE ALSO
+*      SM Info Get Controller object
+*********/
+
+/****f* OpenSM: SM Info Get Controller/osm_smi_get_ctrl_construct
+* NAME
+*      osm_smi_get_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a SM Info Get Controller object.
+*
+* SYNOPSIS
+*/
+void osm_smi_get_ctrl_construct(
+       IN osm_smi_get_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a SM Info Get Controller object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_smi_get_ctrl_init, osm_smi_get_ctrl_destroy,
+*      and osm_smi_get_ctrl_is_inited.
+*
+*      Calling osm_smi_get_ctrl_construct is a prerequisite to calling any other
+*      method except osm_smi_get_ctrl_init.
+*
+* SEE ALSO
+*      SM Info Get Controller object, osm_smi_get_ctrl_init,
+*      osm_smi_get_ctrl_destroy, osm_smi_get_ctrl_is_inited
+*********/
+
+/****f* OpenSM: SM Info Get Controller/osm_smi_get_ctrl_destroy
+* NAME
+*      osm_smi_get_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_smi_get_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_smi_get_ctrl_destroy(
+       IN osm_smi_get_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 Get Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_smi_get_ctrl_construct or osm_smi_get_ctrl_init.
+*
+* SEE ALSO
+*      SM Info Get Controller object, osm_smi_get_ctrl_construct,
+*      osm_smi_get_ctrl_init
+*********/
+
+/****f* OpenSM: SM Info Get Controller/osm_smi_get_ctrl_init
+* NAME
+*      osm_smi_get_ctrl_init
+*
+* DESCRIPTION
+*      The osm_smi_get_ctrl_init function initializes a
+*      SM Info Get Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_smi_get_ctrl_init(
+       IN osm_smi_get_ctrl_t* const p_ctrl,
+       IN osm_sminfo_t* const p_smi,
+       IN osm_mad_pool_t* const p_mad_pool,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_smi_get_ctrl_t object to initialize.
+*
+*      p_smi
+*              [in] Pointer to the SMInfo object of the SM.
+*
+*      p_mad_pool
+*              [in] Pointer to the MAD pool.
+*
+*      p_log
+*              [in] Pointer to the log object.
+*
+*      p_lock
+*              [in] Pointer to the OpenSM serializing lock.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      CL_SUCCESS if the SM Info Get Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other SM Info Get Controller methods.
+*
+* SEE ALSO
+*      SM Info Get Controller object, osm_smi_get_ctrl_construct,
+*      osm_smi_get_ctrl_destroy, osm_smi_get_ctrl_is_inited
+*********/
+
+/****f* OpenSM: SM Info Get Controller/osm_smi_get_ctrl_is_inited
+* NAME
+*      osm_smi_get_ctrl_is_inited
+*
+* DESCRIPTION
+*      Indicates if the object has been initialized with osm_smi_get_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_smi_get_ctrl_is_inited(
+       IN const osm_smi_get_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_smi_get_ctrl_t object.
+*
+* RETURN VALUES
+*      TRUE if the object was initialized successfully,
+*      FALSE otherwise.
+*
+* NOTES
+*      The osm_smi_get_ctrl_construct or osm_smi_get_ctrl_init must be
+*      called before using     this function.
+*
+* SEE ALSO
+*      SM Info Get Controller object, osm_smi_get_ctrl_construct,
+*      osm_smi_get_ctrl_init
+*********/
+
+/****f* OpenSM: SM Info Get Controller/osm_smi_get_ctrl_process
+* NAME
+*      osm_smi_get_ctrl_process
+*
+* DESCRIPTION
+*      Process the SwitchInfo attribute.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_smi_get_ctrl_process(
+       IN const osm_smi_get_ctrl_t* const p_ctrl,
+       IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_smi_get_ctrl_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
+*      SM Info Get Controller, SM Info Response Controller
+*********/
+       
+END_C_DECLS
+
+#endif /* _OSM_SM_INFO_GET_CTRL_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sm_mad_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sm_mad_ctrl.h
new file mode 100644 (file)
index 0000000..3cf6bac
--- /dev/null
@@ -0,0 +1,340 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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, osm_sm_mad_ctrl_destroy,
+*      and osm_sm_mad_ctrl_is_inited.
+*
+*      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, osm_sm_mad_ctrl_is_inited
+*********/
+
+/****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, osm_sm_mad_ctrl_is_inited
+*********/
+
+/****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/trunk/ulp/opensm/user/include/opensm/osm_sm_state_mgr.h b/trunk/ulp/opensm/user/include/opensm/osm_sm_state_mgr.h
new file mode 100644 (file)
index 0000000..bde3404
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 gaurding 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/trunk/ulp/opensm/user/include/opensm/osm_sminfo_rcv.h b/trunk/ulp/opensm/user/include/opensm/osm_sminfo_rcv.h
new file mode 100644 (file)
index 0000000..d8cf218
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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/trunk/ulp/opensm/user/include/opensm/osm_sminfo_rcv_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sminfo_rcv_ctrl.h
new file mode 100644 (file)
index 0000000..1a438da
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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/trunk/ulp/opensm/user/include/opensm/osm_state_mgr.h b/trunk/ulp/opensm/user/include/opensm/osm_state_mgr.h
new file mode 100644 (file)
index 0000000..0d83607
--- /dev/null
@@ -0,0 +1,527 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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;
+  char                                            *p_report_buf;
+  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 gaurding 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.
+*
+*      p_report_buf
+*              Pointer to the large log buffer used for user reports.
+*
+*      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 char*                                        const p_report_buf,
+       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_report_buf
+*              [in] Pointer to the large log buffer used for user reports.
+*
+*      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/trunk/ulp/opensm/user/include/opensm/osm_state_mgr_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_state_mgr_ctrl.h
new file mode 100644 (file)
index 0000000..ad49a8e
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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, osm_state_mgr_ctrl_destroy,
+*      and osm_state_mgr_ctrl_is_inited.
+*
+*      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/trunk/ulp/opensm/user/include/opensm/osm_stats.h b/trunk/ulp/opensm/user/include/opensm/osm_stats.h
new file mode 100644 (file)
index 0000000..944b9bf
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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/trunk/ulp/opensm/user/include/opensm/osm_subnet.h b/trunk/ulp/opensm/user/include/opensm/osm_subnet.h
new file mode 100644 (file)
index 0000000..4e0793d
--- /dev/null
@@ -0,0 +1,1018 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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
+
+
+/****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 funciton (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 funciton (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_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                                   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;
+  uint8_t                  max_op_vls;
+  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                  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;
+  cl_map_t                 port_pro_ignore_guids;
+  boolean_t                port_profile_switch_nodes;
+  uint32_t                 max_port_profile;
+  osm_pfn_ui_extension_t   pfn_ui_pre_lid_assign;
+  void *                   ui_pre_lid_assign_ctx;
+  osm_pfn_ui_extension_t   pfn_ui_ucast_fdb_assign;
+  void *                   ui_ucast_fdb_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;
+  boolean_t                updn_activate;
+  char *                   updn_guid_file;
+} osm_subn_opt_t;
+/*
+* FIELDS
+*
+*      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.
+*
+*  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 try to preserve as much LIDs as posible.
+*
+*  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 SM's 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 then one message in the queue and the last message
+*     stayed in the queue more then 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))
+*
+*  head_of_queue_lifetime
+*     The maximal time a packet can live at the head of a VL queue
+*     on any port not driving an HCA 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
+*
+*      local_phy_errors_threshold
+*     Threshold of local phy errors for sending Trap 129
+*
+*      overrun_errors_threshold
+*     Threshold of credits over-run 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.
+*
+*  port_pro_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.
+*
+*  max_port_profile
+*     Prevent routing through a port subscribed with more then this
+*     number of routes.
+*
+*  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_ucast_fdb_assign
+*     A UI function to be called instead of the ucast manager FDB
+*     configuration.
+*
+*  ui_ucast_fdb_assign_ctx
+*     A UI context (void *) to be provided to the pfn_ui_ucast_fdb_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.
+*
+*  updn_activate
+*     Object that indicates if we are running the UPDN algorithm (TRUE) or 
+*     Min Hop Algorithm (FALSE)
+*
+*  updn_guid_file
+*     Pointer to name of the UPDN guid file given by User
+*
+* 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
+{
+  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 Other SM objects representing other SM's
+*              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 asssign to
+*     ignore existing legal LFT settings.
+*     The value will be set according to :
+*     - During SM init set to the reassign_lfts flag value
+*     - Comming 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 on 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 un-healthy, 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, osm_subn_destroy, and osm_subn_is_inited.
+*
+*      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, osm_subn_is_inited
+*********/
+
+/****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 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,
+*      osm_subn_is_inited
+*********/
+
+/*
+  Forward reference.
+*/
+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 requestor gid in the mad address.
+*
+* Note: This code is not thread safe. Need to grab the lock before
+* calling it.
+*
+* SYNOPSIS
+*/
+ib_gid_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 );
+/*
+* 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
+*      Requestor gid object if found. Null otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Helper/osm_get_physp_by_mad_addr
+* NAME
+*      osm_get_physp_by_mad_addr
+*
+* DESCRIPTION
+*      Looks for the requestor 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 requestor 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 requestor 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 requestor port object if found. Null otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Subnet/osm_get_switch_by_guid
+* NAME
+*      osm_get_switch_by_guid
+*
+* DESCRIPTION
+*      The 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.
+*  NOTE: should be called only after osm_subn_is_inited
+*
+* SEE ALSO g529
+
+*      Subnet object, osm_subn_construct, osm_subn_destroy,
+*      osm_subn_is_inited, 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.
+*  NOTE: should be called only after osm_subn_is_inited
+*
+* SEE ALSO
+*      Subnet object, osm_subn_construct, osm_subn_destroy,
+*      osm_subn_is_inited, 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.
+*  NOTE: should be called only after osm_subn_is_inited
+*
+* SEE ALSO
+*      Subnet object, osm_subn_construct, osm_subn_destroy,
+*      osm_subn_is_inited, osm_port_t
+*********/
+
+/****f* OpenSM: Helper/osm_get_physp_by_mad_addr
+* NAME
+*      osm_get_physp_by_mad_addr
+*
+* DESCRIPTION
+*      Looks for the requestor 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 requestor 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,
+*      osm_subn_is_inited
+*********/
+
+/****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,
+*      osm_subn_is_inited
+*********/
+
+/****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,
+*      osm_subn_is_inited
+*********/
+
+/****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,
+*      osm_subn_is_inited
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SUBNET_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_subnet_config_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_subnet_config_ctrl.h
new file mode 100644 (file)
index 0000000..18fddb8
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *     Declaration of osm_subn_conf_ctrl_t.
+ *     This object represents a controller that initiates configuration
+ *     of the subnet after the discovery phase is complete.
+ *     This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SUBNET_CONFIG_CTRL_H_
+#define _OSM_SUBNET_CONFIG_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/Subnet Configuration Controller
+* NAME
+*      Subnet Configuration Controller
+*
+* DESCRIPTION
+*      The Subnet Configuration Controller object encapsulates the
+*      information needed to initiate a subnet configuration pass.
+*      The Subnet Configuration Controller sends Dispatcher messages
+*      to controllers responsible for configuring LIDs,
+*      switch forwarding tables, etc.
+*
+*      The Subnet Configuration 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: Subnet Configuration Controller/osm_subn_conf_ctrl_t
+* NAME
+*      osm_subn_conf_ctrl_t
+*
+* DESCRIPTION
+*      Subnet Configuration Controller structure.
+*
+*      This object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_subn_conf_ctrl
+{
+       osm_subn_t                                      *p_subn;
+       osm_log_t                                       *p_log;
+       cl_plock_t                                      *p_lock;
+       cl_dispatcher_t                         *p_disp;
+
+} osm_subn_conf_ctrl_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.
+*
+*      p_disp
+*              Pointer to the Dispatcher.
+*
+* SEE ALSO
+*      Subnet Configuration Controller object
+*********/
+
+/****f* OpenSM: Subnet Configuration Controller/osm_subn_conf_ctrl_construct
+* NAME
+*      osm_subn_conf_ctrl_construct
+*
+* DESCRIPTION
+*      This function constructs a Subnet Configuration Controller object.
+*
+* SYNOPSIS
+*/
+void osm_subn_conf_ctrl_construct(
+       IN osm_subn_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to a Subnet Configuration Controller object to construct.
+*
+* RETURN VALUE
+*      This function does not return a value.
+*
+* NOTES
+*      Allows calling osm_subn_conf_ctrl_init, osm_subn_conf_ctrl_destroy,
+*      and osm_subn_conf_ctrl_is_inited.
+*
+*      Calling osm_subn_conf_ctrl_construct is a prerequisite to calling any other
+*      method except osm_subn_conf_ctrl_init.
+*
+* SEE ALSO
+*      Subnet Configuration Controller object, osm_subn_conf_ctrl_init,
+*      osm_subn_conf_ctrl_destroy, osm_subn_conf_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Subnet Configuration Controller/osm_subn_conf_ctrl_destroy
+* NAME
+*      osm_subn_conf_ctrl_destroy
+*
+* DESCRIPTION
+*      The osm_subn_conf_ctrl_destroy function destroys the object, releasing
+*      all resources.
+*
+* SYNOPSIS
+*/
+void osm_subn_conf_ctrl_destroy(
+       IN osm_subn_conf_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
+*      Subnet Configuration Controller object.
+*      Further operations should not be attempted on the destroyed object.
+*      This function should only be called after a call to
+*      osm_subn_conf_ctrl_construct or osm_subn_conf_ctrl_init.
+*
+* SEE ALSO
+*      Subnet Configuration Controller object, osm_subn_conf_ctrl_construct,
+*      osm_subn_conf_ctrl_init
+*********/
+
+/****f* OpenSM: Subnet Configuration Controller/osm_subn_conf_ctrl_init
+* NAME
+*      osm_subn_conf_ctrl_init
+*
+* DESCRIPTION
+*      The osm_subn_conf_ctrl_init function initializes a
+*      Subnet Configuration Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_subn_conf_ctrl_init(
+       IN osm_subn_conf_ctrl_t* const p_ctrl,
+       IN osm_subn_t* const p_subn,
+       IN osm_log_t* const p_log,
+       IN cl_plock_t* const p_lock,
+       IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_subn_conf_ctrl_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.
+*
+*      p_disp
+*              [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+*      IB_SUCCESS if the Subnet Configuration Controller object was initialized
+*      successfully.
+*
+* NOTES
+*      Allows calling other Subnet Configuration Controller methods.
+*
+* SEE ALSO
+*      Subnet Configuration Controller object, osm_subn_conf_ctrl_construct,
+*      osm_subn_conf_ctrl_destroy, osm_subn_conf_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Subnet Configuration Controller/osm_subn_conf_ctrl_is_inited
+* NAME
+*      osm_subn_conf_ctrl_is_inited
+*
+* DESCRIPTION
+*      Indicates if the object has been initialized with osm_subn_conf_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_subn_conf_ctrl_is_inited(
+       IN const osm_subn_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_subn_conf_ctrl_t object.
+*
+* RETURN VALUES
+*      TRUE if the object was initialized successfully,
+*      FALSE otherwise.
+*
+* NOTES
+*      The osm_subn_conf_ctrl_construct or osm_subn_conf_ctrl_init must be
+*      called before using     this function.
+*
+* SEE ALSO
+*      Subnet Configuration Controller object, osm_subn_conf_ctrl_construct,
+*      osm_subn_conf_ctrl_init
+*********/
+
+/****f* OpenSM: Subnet Configuration Controller/osm_subn_conf_ctrl_process
+* NAME
+*      osm_subn_conf_ctrl_process
+*
+* DESCRIPTION
+*      Initiate a subnet configuration pass.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_subn_conf_ctrl_process(
+       IN const osm_subn_conf_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+*      p_ctrl
+*              [in] Pointer to an osm_subn_conf_ctrl_t object.
+*
+* RETURN VALUES
+*      IB_SUCCESS if configuration processing was successfully
+*      initiated.
+*
+* NOTES
+*      A success status here does not indicate that
+*      the entire subnet configuration process completed successfully.
+*      Only one configuration pass is active at one time.
+*
+* SEE ALSO
+*      Subnet Configuration Controller
+*********/
+       
+END_C_DECLS
+
+#endif /* _OSM_SUBNET_CONFIG_CTRL_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_sw_info_rcv.h b/trunk/ulp/opensm/user/include/opensm/osm_sw_info_rcv.h
new file mode 100644 (file)
index 0000000..ff238d0
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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/trunk/ulp/opensm/user/include/opensm/osm_sw_info_rcv_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sw_info_rcv_ctrl.h
new file mode 100644 (file)
index 0000000..f282d16
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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/trunk/ulp/opensm/user/include/opensm/osm_sweep_fail_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_sweep_fail_ctrl.h
new file mode 100644 (file)
index 0000000..0f515b2
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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/trunk/ulp/opensm/user/include/opensm/osm_switch.h b/trunk/ulp/opensm/user/include/opensm/osm_switch.h
new file mode 100644 (file)
index 0000000..320a45b
--- /dev/null
@@ -0,0 +1,1455 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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
+*
+*********/
+
+/****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;
+       osm_port_profile_t                      *p_pro;
+       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.
+*
+*      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, osm_switch_destroy, and osm_switch_is_inited.
+*
+*      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, osm_switch_is_inited
+*********/
+
+/****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,
+*      osm_switch_is_inited
+*********/
+/****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_hops
+* NAME
+*      osm_switch_set_hops
+*
+* 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_lid
+* NAME
+*      osm_switch_get_lid
+*
+* DESCRIPTION
+*      Gets the switch's LID.
+*
+* SYNOPSIS
+*/
+ib_net16_t
+osm_switch_get_lid(
+       IN const osm_switch_t* const p_sw );
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+*      Returns the switch's LID.  A value of zero means no LID has
+*      been assigned to the switch.
+*
+* 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 alogrithm ), i.e. cases where port is
+     unreachable through a switch (we put a OSM_NO_PATH value at 
+     the port entry , we do not assert on unreachable lids 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_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 uint32_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 LID matrix 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 )
+{
+       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_set_path
+* NAME
+*      osm_switch_set_path
+*
+* DESCRIPTION
+*      Sets the port to route the specified LID.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_switch_set_path(
+       IN osm_switch_t* const p_sw,
+       IN const uint16_t lid_ho,
+       IN const uint8_t port,
+       IN const boolean_t ignore_port_pro
+       )
+{
+       CL_ASSERT( p_sw );
+       osm_fwd_tbl_set( &p_sw->fwd_tbl, lid_ho, port );
+       if (! ignore_port_pro)
+         osm_port_pro_path_count_inc( &p_sw->p_pro[port] );
+}
+/*
+* PARAMETERS
+*      p_sw
+*              [in] Pointer to the switch 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: 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_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,
+       IN const uint32_t max_routes_subscribed,
+       IN boolean_t      ui_ucast_fdb_assign_func_defined
+ );
+/*
+* 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.
+*
+*  max_routes_subscribed
+*     [in] The maximum allowed number of target lids routed through 
+*     a specific port of the switch. If the port already assigned 
+*     (in the lfdb) this number of target lids - it will not be used
+*     even if it has the smallest hops count to the target lid.
+*
+*  ui_ucast_fdb_assign_func_defined
+*     [in] If TRUE - this means that there is a ui ucast_fdb_assign table
+*     function defined (in pfn_ui_ucast_fdb_assign in subnet opts). This
+*     means that all current entries in the fdbs will be used.
+*     If FALSE - such function isn't defined. Do the minimum hop checks 
+*     before accepting the current fdbs.
+*
+* 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_pro_path_count_get( &p_sw->p_pro[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/trunk/ulp/opensm/user/include/opensm/osm_trap_rcv.h b/trunk/ulp/opensm/user/include/opensm/osm_trap_rcv.h
new file mode 100644 (file)
index 0000000..5a3945f
--- /dev/null
@@ -0,0 +1,325 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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_tap_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/trunk/ulp/opensm/user/include/opensm/osm_trap_rcv_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_trap_rcv_ctrl.h
new file mode 100644 (file)
index 0000000..483d13f
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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/trunk/ulp/opensm/user/include/opensm/osm_ts_useraccess.h b/trunk/ulp/opensm/user/include/opensm/osm_ts_useraccess.h
new file mode 100644 (file)
index 0000000..fb2feba
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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$
+ */
+
+#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/trunk/ulp/opensm/user/include/opensm/osm_ucast_mgr.h b/trunk/ulp/opensm/user/include/opensm/osm_ucast_mgr.h
new file mode 100644 (file)
index 0000000..af86f2a
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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_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;
+       char                                            *p_report_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.
+*
+* 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 char* const p_report_buf,
+       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_report_buf
+*              [in] Pointer to the large log buffer used for user reporting.
+*
+*      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_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/trunk/ulp/opensm/user/include/opensm/osm_ucast_updn.h b/trunk/ulp/opensm/user/include/opensm/osm_ucast_updn.h
new file mode 100644 (file)
index 0000000..b82582e
--- /dev/null
@@ -0,0 +1,472 @@
+/*
+ * 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$
+ */
+
+
+#ifndef _OSM_UCAST_UPDN_H_
+#define _OSM_UCAST_UPDN_H_
+
+
+/*
+ * Abstract:
+ *     Implementation of Up Down Algorithm using ranking & Min Hop 
+ *      Calculation functions
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.0 $
+ */
+/* LS : This code is useless since we integrate it with opensm */
+/*
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_node.h>
+#include <complib/cl_list.h>
+#include <opensm/osm_subnet.h>
+#include <osmsh/osmsh_ext_ifc.h> 
+#include <opensm/osm_ucast_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
+
+/* //////////////////////////// */
+/*  ENUM TypeDefs */
+/* /////////////////////////// */
+
+/*
+* DESCRIPTION
+*       This enum respresent available directions of arcs in the graph
+* SYNOPSIS
+*/
+typedef enum _updn_switch_dir
+  {
+    UP = 0,
+    DOWN
+
+  } updn_switch_dir_t;
+
+/*
+ * TYPE DEFINITIONS
+ *    UP 
+ *      Current switch direction in propogating the subnet is up
+ *    DOWN 
+ *      Current switch direction in propogating the subnet is down
+ *
+ */
+
+
+/*
+* DESCRIPTION
+*       This enum respresent available states in the UPDN algorithm
+* SYNOPSIS
+*/
+typedef enum _updn_state
+  {
+    UPDN_INIT = 0,
+    UPDN_RANK,
+    UPDN_MIN_HOP_CALC,
+  } updn_state_t;
+
+/*
+ * TYPE DEFINITIONS
+ * UPDN_INIT - loading the package but still not performing anything
+ * UPDN_RANK - post ranking algorithm
+ * UPDN_MIN_HOP_CALC - post min hop table calculation
+ */
+
+
+/* ////////////////////////////////// */
+/*  Struct TypeDefs */
+/* ///////////////////////////////// */
+
+/****s* UPDN: Rank element/updn_rank_t
+* NAME
+*      updn_rank_t
+*
+* DESCRIPTION
+*      This object represents a rank type element in a list
+*
+*      The updn_rank_t object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+
+typedef struct _updn_rank
+{
+  cl_map_item_t map_item;
+  uint8_t rank;
+} updn_rank_t;
+
+/*
+* FIELDS
+*      map_item
+*              Linkage structure for cl_qmap.  MUST BE FIRST MEMBER!
+*
+*      rank
+*              Rank value of this node
+*
+*/
+
+/****s* UPDN: Histogram element/updn_hist_t
+* NAME
+*      updn_hist_t
+*
+* DESCRIPTION
+*      This object represents a histogram type element in a list
+*
+*      The updn_hist_t object should be treated as opaque and should
+*      be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+
+typedef struct _updn_hist
+{
+  cl_map_item_t map_item;
+  uint32_t bar_value;
+} updn_hist_t;
+
+/*
+* FIELDS
+*      map_item
+*              Linkage structure for cl_qmap.  MUST BE FIRST MEMBER!
+*
+*      bar_value
+*              The number of occurences of the same hop value 
+*
+*/
+
+typedef struct _updn_next_step
+{
+  updn_switch_dir_t state;
+  osm_switch_t *p_sw;
+} updn_next_step_t;
+
+/*****s* updn: updn/updn_input_t
+* NAME  updn_t
+*       
+*
+* DESCRIPTION
+*       updn input fields structure.
+*
+* SYNOPSIS
+*/
+
+typedef struct _updn_input
+{
+  uint32_t num_guids;
+  uint64_t * guid_list;
+} updn_input_t;
+
+/*
+* FIELDS
+*       num_guids
+*            number of guids given at the UI
+*
+*       guid_list
+*            guids specified as an array (converted from a list given in the UI) 
+*
+*
+* SEE ALSO
+*      
+*********/
+
+
+/*****s* updn: updn/updn_t
+* NAME  updn_t
+*       
+*
+* DESCRIPTION
+*       updn structure.
+*
+* SYNOPSIS
+*/
+
+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;
+} updn_t;
+
+/*
+* FIELDS
+*       state
+*            state of the updn algorithm which basically should pass through Init 
+*            - Ranking - UpDn algorithm
+*
+*       guid_rank_tbl
+*            guid 2 rank mapping vector , indexed by guid in network order
+*
+*
+* SEE ALSO
+*      
+*********/
+
+
+/* ////////////////////////////// */
+/*  Function  */
+/* ////////////////////////////// */
+
+/***f** Osmsh: Updn/updn_construct
+* NAME
+*       updn_construct
+*
+* DESCRIPTION
+*      Allocation of updn_t struct
+*
+* SYNOPSIS
+*/
+
+updn_t*
+updn_construct(void);
+
+/*
+* PARAMETERS
+*
+*
+* RETURN VALUE
+*       Return a pointer to an updn struct. Null if fails to do so.
+*
+* NOTES
+*       First step of the creation of updn_t
+*/
+
+/****s* Osmsh: Updn/updn_destroy
+* NAME
+*       updn_destroy
+*
+* DESCRIPTION
+*      release of updn_t struct
+*
+* SYNOPSIS
+*/
+
+void
+updn_destroy(
+  IN updn_t* const p_updn );
+
+/*
+* PARAMETERS
+*       p_updn
+*               A pointer to the updn_t struct that is goining to be released
+*
+* RETURN VALUE
+*      
+* NOTES
+*       Final step of the releasing of updn_t
+*
+* SEE ALSO
+*       updn_construct
+*********/
+
+/****f* Osmsh: Updn/updn_init
+* NAME
+*       updn_init
+*
+* DESCRIPTION
+*      Initialization of an updn_t struct
+*
+* SYNOPSIS
+*/
+cl_status_t
+updn_init(
+  IN updn_t* const p_updn );
+
+/*
+* PARAMETERS
+*       p_updn
+*               A pointer to the updn_t struct that is goining to be initilized
+*
+* RETURN VALUE
+*       The status of the function.
+*      
+* NOTES
+*       
+* SEE ALSO
+*       updn_construct
+********/
+
+
+
+
+/****** Osmsh: Updn/updn_subn_rank
+* NAME
+*      updn_subn_rank
+*
+* DESCRIPTION
+*      This function ranks the subnet for credit loop free algorithm
+*
+* SYNOPSIS
+*/
+
+int
+updn_subn_rank(
+             IN uint64_t  root_guid ,
+             IN uint8_t base_rank,
+             IN updn_t* p_updn);
+
+/*
+* PARAMETERS
+*      p_subn
+*              [in] Pointer to a Subnet object to construct.
+*
+*       base_rank
+*              [in] The base ranking value (lowest value)
+*
+*      p_updn
+*              [in] Pointer to updn structure which includes state & lid2rank table
+*
+* RETURN VALUE
+*      This function returns 0 when rankning has succeded , otherwise 1.
+******/
+
+
+/****** Osmsh: UpDown/osm_subn_set_up_down_min_hop_table
+* NAME
+*      osm_subn_set_up_down_min_hop_table
+*
+* DESCRIPTION
+*      This function set min hop table of all switches by BFS through each
+*       port guid at the subnet using ranking done before.
+*
+* SYNOPSIS
+*/
+
+int
+osm_subn_set_up_down_min_hop_table(
+             IN updn_t* p_updn);
+
+/*
+* PARAMETERS
+*      p_updn
+*              [in] Pointer to updn structure which includes state & lid2rank table
+*
+* RETURN VALUE
+*      This function returns 0 when rankning has succeded , otherwise 1.
+******/
+
+
+
+
+/****** Osmsh: UpDown/osm_subn_calc_up_down_min_hop_table
+* NAME
+*      osm_subn_calc_up_down_min_hop_table
+*
+* DESCRIPTION
+*      This function perform ranking and setting of all switches' min hop table
+*        by UP DOWN algorithm
+*
+* SYNOPSIS
+*/
+
+int
+osm_subn_calc_up_down_min_hop_table(
+  IN uint32_t num_guids,
+  IN uint64_t* guid_list,
+  IN updn_t* p_updn);
+
+/*
+* PARAMETERS
+*
+*      guid_list
+*              [in] Guid list from which to start ranking .
+*
+*      p_updn
+*              [in] Pointer to updn structure which includes state & lid2rank table
+* RETURN VALUE
+*      This function returns 0 when rankning has succeded , otherwise 1.
+******/
+
+/****f* OpenSM: OpenSM/osm_updn_reg_calc_min_hop_table
+* NAME
+*      osm_updn_reg_calc_min_hop_table 
+*
+* DESCRIPTION
+*       Registration function to ucast routing manager (instead of 
+*       Min Hop Algorithm) 
+*
+* SYNOPSIS
+*/
+int
+osm_updn_reg_calc_min_hop_table(
+  IN updn_t * p_updn,
+  IN osm_subn_opt_t* p_opt );
+/*
+* PARAMETERS
+*
+* RETURN VALUES
+*      0 - on success , 1 - on failure
+*
+* NOTES
+*
+* SEE ALSO
+* osm_subn_calc_up_down_min_hop_table
+*********/
+
+/****** Osmsh: UpDown/osm_updn_find_root_nodes_by_min_hop
+* NAME
+*      osm_updn_find_root_nodes_by_min_hop
+*
+* DESCRIPTION
+*      This function perform auto identification of root nodes for UPDN ranking phase
+*
+* SYNOPSIS
+*/
+int
+osm_updn_find_root_nodes_by_min_hop( OUT updn_t *  p_updn );
+
+/*
+* PARAMETERS
+*      p_root_nodes_list
+*       
+*              [out] Pointer to the root nodes list found in the subnet
+*
+* RETURN VALUE
+*      This function returns 0 when auto identification had succeeded
+******/
+
+
+END_C_DECLS
+
+#endif /* _OSM_UCAST_UPDN_H_ */
diff --git a/trunk/ulp/opensm/user/include/opensm/osm_umadt.h b/trunk/ulp/opensm/user/include/opensm/osm_umadt.h
new file mode 100644 (file)
index 0000000..3285ceb
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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/trunk/ulp/opensm/user/include/opensm/osm_vl15intf.h b/trunk/ulp/opensm/user/include/opensm/osm_vl15intf.h
new file mode 100644 (file)
index 0000000..2c07ed3
--- /dev/null
@@ -0,0 +1,390 @@
+/*
+ * 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$
+ */
+
+/*
+ * 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 <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>
+
+#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_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.
+*
+* 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 );
+/*
+* 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.
+*
+* 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/trunk/ulp/opensm/user/include/opensm/osm_vl_arb_rcv.h b/trunk/ulp/opensm/user/include/opensm/osm_vl_arb_rcv.h
new file mode 100644 (file)
index 0000000..d957342
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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/trunk/ulp/opensm/user/include/opensm/osm_vl_arb_rcv_ctrl.h b/trunk/ulp/opensm/user/include/opensm/osm_vl_arb_rcv_ctrl.h
new file mode 100644 (file)
index 0000000..dc91343
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/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/trunk/ulp/opensm/user/include/opensm/st.h b/trunk/ulp/opensm/user/include/opensm/st.h
new file mode 100644 (file)
index 0000000..2e53298
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * 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$
+ */
+
+
+/* @(#) st.h 5.1 89/12/14 */
+
+#ifndef ST_INCLUDED
+#define ST_INCLUDED
+
+#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 *, int);
+st_table *st_init_numtable(void);
+st_table *st_init_numtable_with_size(int);
+st_table *st_init_strtable(void);
+st_table *st_init_strtable_with_size(int);
+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/trunk/ulp/opensm/user/include/vendor/osm_vendor.h b/trunk/ulp/opensm/user/include/vendor/osm_vendor.h
new file mode 100644 (file)
index 0000000..21baaee
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *     Include file used by OpenSM to pull in the correct vendor file.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+/*
+  this is the generic include file which includes
+  the proper vendor specific file
+*/
+#include <vendor/osm_vendor_select.h>
+
+#if defined( OSM_VENDOR_INTF_TEST )
+#include <vendor/osm_vendor_test.h>
+#elif defined( OSM_VENDOR_INTF_UMADT )
+#include <vendor/osm_vendor_umadt.h>
+#elif defined( OSM_VENDOR_INTF_MTL )
+/* HACK - I do not know how to prevent complib from loading kernel H files */
+#undef __init
+#include <vendor/osm_vendor_mlx.h>
+#elif defined( OSM_VENDOR_INTF_TS )
+#undef __init
+#include <vendor/osm_vendor_mlx.h>
+#elif defined( OSM_VENDOR_INTF_ANAFA )
+#undef __init
+#include <vendor/osm_vendor_mlx.h>
+#elif defined( OSM_VENDOR_INTF_SIM )
+#undef __init
+#include <vendor/osm_vendor_mlx.h>
+#elif defined( OSM_VENDOR_INTF_OPENIB )
+#include <vendor/osm_vendor_ibumad.h>
+#elif defined( OSM_VENDOR_INTF_AL )
+#include <vendor/osm_vendor_al.h>
+#elif
+#error No MAD Interface selected!
+#error Choose an interface in osm_vendor_select.h
+#endif
+
diff --git a/trunk/ulp/opensm/user/include/vendor/osm_vendor_al.h b/trunk/ulp/opensm/user/include/vendor/osm_vendor_al.h
new file mode 100644 (file)
index 0000000..44b9086
--- /dev/null
@@ -0,0 +1,371 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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_VENDOR_AL_H_
+#define _OSM_VENDOR_AL_H_
+
+#include <iba/ib_types.h>
+#include <iba/ib_al.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_thread.h>
+#include <opensm/osm_base.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/Vendor AL
+* NAME
+*      Vendor AL
+*
+* DESCRIPTION
+*
+*      The Vendor AL object is thread safe.
+*
+*      This object should be treated as opaque and should be
+*      manipulated only through the provided functions.
+*
+*      Enable various hacks to compensate for bugs in external code...
+*
+*
+* AUTHOR
+*      
+*
+*********/
+
+
+
+/****h* OpenSM/Vendor Access Layer (AL)
+* NAME
+*      Vendor AL
+*
+* DESCRIPTION
+*      This file is the vendor specific file for the AL Infiniband API.
+*
+* AUTHOR
+*      Steve King, Intel
+*
+*********/
+
+#define OSM_AL_SQ_SGE 256
+#define OSM_AL_RQ_SGE 256
+#define OSM_DEFAULT_RETRY_COUNT 3
+
+/* AL supports RMPP */
+#define VENDOR_RMPP_SUPPORT 1
+
+/****s* OpenSM: Vendor AL/osm_ca_info_t
+* NAME
+*   osm_ca_info_t
+*
+* DESCRIPTION
+*      Structure containing information about local Channle Adapters.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_ca_info
+{
+       ib_net64_t                              guid;
+       uint32_t                                        attr_size;
+       ib_ca_attr_t                    *p_attr;
+
+} osm_ca_info_t;
+/*
+* FIELDS
+*      guid
+*              Node GUID of the local CA.
+*
+*      attr_size
+*              Size of the CA attributes for this CA.
+*
+*      p_attr
+*              Pointer to dynamicly allocated CA Attribute structure.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: CA Info/osm_ca_info_get_num_ports
+* NAME
+*      osm_ca_info_get_num_ports
+*
+* DESCRIPTION
+*      Returns the number of ports owned by this CA.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_ca_info_get_num_ports(
+       IN const osm_ca_info_t* const p_ca_info )
+{
+       return( p_ca_info->p_attr->num_ports );
+}
+/*
+* PARAMETERS
+*      p_ca_info
+*              [in] Pointer to a CA Info object.
+*
+* RETURN VALUE
+*      Returns the number of ports owned by this CA.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: CA Info/osm_ca_info_get_port_guid
+* NAME
+*      osm_ca_info_get_port_guid
+*
+* DESCRIPTION
+*      Returns the port GUID of the specified port owned by this CA.
+*
+* SYNOPSIS
+*/
+static inline ib_net64_t
+osm_ca_info_get_port_guid(
+       IN const osm_ca_info_t* const p_ca_info,
+       IN const uint8_t index )
+{
+       return( p_ca_info->p_attr->p_port_attr[index].port_guid );
+}
+/*
+* PARAMETERS
+*      p_ca_info
+*              [in] Pointer to a CA Info object.
+*
+*      index
+*              [in] Port "index" for which to retrieve the port GUID.
+*              The index is the offset into the ca's internal array
+*              of port attributes.
+*
+* RETURN VALUE
+*      Returns the port GUID of the specified port owned by this CA.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: CA Info/osm_ca_info_get_port_num
+* NAME
+*      osm_ca_info_get_port_num
+*
+* DESCRIPTION
+*      Returns the port number of the specified port owned by this CA.
+*      Port numbers start with 1 for HCA's.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_ca_info_get_port_num(
+       IN const osm_ca_info_t* const p_ca_info,
+       IN const uint8_t index )
+{
+       return( p_ca_info->p_attr->p_port_attr[index].port_num );
+}
+/*
+* PARAMETERS
+*      p_ca_info
+*              [in] Pointer to a CA Info object.
+*
+*      index
+*              [in] Port "index" for which to retrieve the port GUID.
+*              The index is the offset into the ca's internal array
+*              of port attributes.
+*
+* RETURN VALUE
+*      Returns the port GUID of the specified port owned by this CA.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: CA Info/osm_ca_info_get_ca_guid
+* NAME
+*      osm_ca_info_get_ca_guid
+*
+* DESCRIPTION
+*      Returns the GUID of the specified CA.
+*
+* SYNOPSIS
+*/
+static inline ib_net64_t
+osm_ca_info_get_ca_guid(
+       IN const osm_ca_info_t* const p_ca_info )
+{
+       return( p_ca_info->p_attr->ca_guid );
+}
+/*
+* PARAMETERS
+*      p_ca_info
+*              [in] Pointer to a CA Info object.
+*
+* RETURN VALUE
+*      Returns the GUID of the specified CA.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****s* OpenSM: Vendor AL/osm_bind_handle_t
+* NAME
+*   osm_bind_handle_t
+*
+* DESCRIPTION
+*      handle returned by the vendor transport bind call.
+*
+* SYNOPSIS
+*/
+typedef        struct _osm_vendor
+{
+       ib_al_handle_t          h_al;
+       osm_log_t                       *p_log;
+       size_t                  ca_count;
+       osm_ca_info_t           *p_ca_info;
+       uint32_t                        timeout;
+       ib_ca_handle_t          h_ca;
+       ib_pd_handle_t          h_pd;
+
+} osm_vendor_t;
+/*
+* FIELDS
+*      h_al
+*              Handle returned by AL open call (ib_open_al).   
+*
+*      p_log
+*              Pointer to the log object.
+*
+*      ca_count
+*              Number of CA's in the array pointed to by p_ca_info.
+*
+*      p_ca_info
+*              Pointer to dynamically allocated array of CA info objects.
+*
+*      h_pool
+*              MAD Pool handle returned by ib_create_mad_pool at init time.
+*
+*      timeout
+*              Transaction timeout time in milliseconds.
+*
+* SEE ALSO
+*********/
+
+
+#ifndef OSM_BIND_INVALID_HANDLE
+#define OSM_BIND_INVALID_HANDLE NULL
+#endif
+
+
+/****s* OpenSM: Vendor AL/osm_bind_handle_t
+* NAME
+*   osm_bind_handle_t
+*
+* DESCRIPTION
+*      handle returned by the vendor transport bind call.
+*
+* SYNOPSIS
+*/
+typedef        void*   osm_bind_handle_t;
+/***********/
+
+/****s* OpenSM/osm_vend_wrap_t
+* NAME
+*   AL Vendor MAD Wrapper
+*
+* DESCRIPTION
+*      AL specific MAD wrapper. AL transport layer uses this for
+*      housekeeping.
+*
+* SYNOPSIS
+*********/
+typedef struct _osm_vend_wrap_t
+{
+    uint32_t                                   size;
+       osm_bind_handle_t                       h_bind;
+       ib_mad_element_t                        *p_elem;
+       ib_av_handle_t                          h_av;
+       void*                                           p_resp_madw;
+
+}osm_vend_wrap_t;
+/*
+* FIELDS
+*      size
+*              Size of the allocated MAD
+*
+*      h_bind
+*              Bind handle used on this transaction
+*
+*      p_elem
+*              Pointer to the mad element structure associated with
+*              this mad.
+*
+*      h_av
+*              Address vector handle used for this transaction.
+*
+*      p_resp_madw
+*              Pointer to the mad wrapper structure used to hold the pending
+*              reponse to the mad, if any.  If a response is expected, the
+*              wrapper for the reponse is allocated during the send call.
+*
+* SEE ALSO
+*********/
+
+
+END_C_DECLS
+
+#endif /* _OSM_VENDOR_AL_H_ */
diff --git a/trunk/ulp/opensm/user/include/vendor/osm_vendor_api.h b/trunk/ulp/opensm/user/include/vendor/osm_vendor_api.h
new file mode 100644 (file)
index 0000000..f37b386
--- /dev/null
@@ -0,0 +1,528 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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/trunk/ulp/opensm/user/include/vendor/osm_vendor_sa_api.h b/trunk/ulp/opensm/user/include/vendor/osm_vendor_sa_api.h
new file mode 100644 (file)
index 0000000..5c4cd9c
--- /dev/null
@@ -0,0 +1,775 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *     Specification of the OpenSM SA 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_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 into 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
+*              into 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 into 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 the subnet administrator 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_net64_t                              comp_mask;
+       void                                      *p_attr;
+
+}      osmv_user_query_t;
+/*
+* FIELDS
+*
+*      method
+*              Method to be run
+*
+*      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.
+*
+*      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_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 the subnet administrator 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 the subnet administrator, 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_pfn_query_cb_t
+* NAME
+*      osmv_pfn_query_cb_t
+*
+* DESCRIPTION
+*      User-defined callback invoked on completion of a subnet administrator
+*      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 the subnet administrator.
+*
+*      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 the subnet
+*      administrator.
+*
+* 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 the subnet administrator.  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 erquest was sent).
+*
+* NOTES
+*
+* SEE ALSO
+* osmv_bind_sa
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_VENDOR_SA_API_H_ */
diff --git a/trunk/ulp/opensm/user/include/vendor/osm_vendor_select.h b/trunk/ulp/opensm/user/include/vendor/osm_vendor_select.h
new file mode 100644 (file)
index 0000000..9f53458
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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/trunk/ulp/opensm/user/include/vendor/winosm_common.h b/trunk/ulp/opensm/user/include/vendor/winosm_common.h
new file mode 100644 (file)
index 0000000..da538ce
--- /dev/null
@@ -0,0 +1,221 @@
+#ifndef _OSM_COMMON_H_
+#define _OSM_COMMON_H_
+
+#include <winsock2.h>
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+#pragma warning(disable : 4996)
+#pragma warning(disable : 4100)
+
+struct timezone {
+        int     tz_minuteswest; /* minutes west of Greenwich */
+        int     tz_dsttime;     /* type of dst correction */
+};
+
+
+# define no_argument           0
+# define required_argument     1
+# define optional_argument     2
+/* Global variables for getopt_long */
+char *optarg;
+/*
+extern int optind;
+extern int opterr;
+extern int optopt;
+extern int iArg;
+  */
+struct option
+{
+  const char *name;
+  int has_arg;
+  int *flag;
+  int val;
+};
+
+
+/************************************************************************/
+static char* 
+get_char_option(const char* optstring,
+                             char*const* argv,int argc, 
+                             int iArg, int* opt_ind,char* opt_p);   
+int 
+getopt_long_only(int argc, char *const*argv,
+                         const char *optstring,
+                         const struct option *longopts, int *longindex);
+/**************************************************************************/
+static __inline
+void FileTimeToTimeval(LPFILETIME pft, struct timeval * ptv)
+{ /* Note that LONGLONG is a 64-bit value */
+LONGLONG ll;
+
+if(!pft || !ptv)
+goto Exit;
+
+ll = ((LONGLONG) pft->dwHighDateTime << 32);
+ll += (LONGLONG) pft->dwLowDateTime;
+#ifdef __GNUC__
+ll -= 116444736000000000ll;
+#else
+ll -= 116444736000000000;
+#endif
+
+ptv->tv_sec = (long) (ll / 10000000);
+ptv->tv_usec = (long) (ll - ((LONGLONG)(ptv->tv_sec) * 10000000)) / 10;
+
+Exit:;
+}/* FileTimeToTimeval */
+
+/********************************************************************************/
+static __inline
+int gettimeofday(struct timeval *ptv, struct timezone *tzp)
+{
+static int QueryCounter = 2;
+FILETIME CurrentTime;
+/* TODO : We need to add it , since in DDK - compiler does not like vars that are not in use */
+UNREFERENCED_PARAMETER(tzp);     
+if(!ptv)
+goto Exit;
+
+if(QueryCounter)
+{
+static LARGE_INTEGER Frequency;
+static LARGE_INTEGER Offset; /* counter offset for right time*/
+static LARGE_INTEGER LastCounter;
+LARGE_INTEGER Time;
+LARGE_INTEGER Counter;
+/* HANDLE hThread = GetCurrentThread();
+int ThreadPrio = GetThreadPriority(hThread);
+
+SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL); */
+GetSystemTimeAsFileTime(&CurrentTime);
+QueryPerformanceCounter(&Counter);
+/* SetThreadPriority(hThread, ThreadPrio); */
+
+if(QueryCounter == 2)
+{
+QueryCounter = 1;
+if(!QueryPerformanceFrequency(&Frequency))
+{
+QueryCounter = 0;
+Frequency.QuadPart = 10000000; /* prevent division by 0 */
+}
+
+/* get time as a large integer */
+Counter.HighPart &= 0x7fl; /* Clear the highest bits to prevent overflows */
+Offset.LowPart = CurrentTime.dwLowDateTime;
+Offset.HighPart = (LONG) CurrentTime.dwHighDateTime;
+Offset.QuadPart -= Counter.QuadPart * 10000000 / Frequency.QuadPart;
+}
+
+/* Convert counter to a 100 nanoseconds resolution timer value. */
+
+Counter.HighPart &= 0x7fl; /* Clear the highest bits to prevent overflows */
+Counter.QuadPart *= 10000000; /* Because we need time stamp in units of 100 ns */
+Counter.QuadPart /= Frequency.QuadPart; /* counter of 0.1 microseconds */
+
+if(LastCounter.QuadPart > Counter.QuadPart)
+{ /* Counter value wrapped */
+#ifdef __GNUC__
+Offset.QuadPart += (0x7f00000000ll * 10000000ll) / Frequency.QuadPart;
+#else
+Offset.QuadPart += (0x7f00000000 * 10000000) / Frequency.QuadPart;
+#endif
+}
+LastCounter = Counter;
+
+/* Add the in previous call calculated offset */
+Counter.QuadPart += Offset.QuadPart;
+
+/* get time as a large integer */
+Time.LowPart = CurrentTime.dwLowDateTime;
+Time.HighPart = (LONG) CurrentTime.dwHighDateTime;
+
+/* keep time difference within an interval of +- 0.1 seconds
+relative to the time function by adjusting the counters offset */
+
+if(((Time.QuadPart + 1000000) < Counter.QuadPart) ||
+((Time.QuadPart - 1000000) > Counter.QuadPart))
+{ /* Adjust the offset */
+Offset.QuadPart += Time.QuadPart - Counter.QuadPart;
+Counter.QuadPart = Time.QuadPart;
+}
+
+/* Now let's use the adjusted performance counter time for the time stamp */
+CurrentTime.dwLowDateTime = Counter.LowPart;
+CurrentTime.dwHighDateTime = Counter.HighPart;
+}
+else
+{
+GetSystemTimeAsFileTime(&CurrentTime);
+}
+
+FileTimeToTimeval(&CurrentTime,ptv);
+
+Exit:;
+return(0);
+}/* int gettimeofday(struct timeval *ptv, void *tzp) */
+/*****************************************************************************/
+
+
+
+
+#define getpid() GetCurrentProcessId()
+#define sleep(sec) SleepEx((sec)*1000,TRUE)
+#define usleep(usec) SleepEx(usec/1000,TRUE)
+//#define MT_ALIGN8    __declspec(align(8))
+/* Verify the correct ETIMEDOUT value is defined in all compiled files */
+#ifndef ETIMEDOUT
+#define ETIMEDOUT              (10060)
+#endif
+#define strtoull _strtoui64
+#define OSM_MAX_LOG_NAME_SIZE 2048
+#define unlink(str) _unlink(str)
+#define strnicmp _strnicmp
+
+/* The following defines replace syslog.h */
+#define openlog(a,b,c)
+
+#define closelog()
+
+static __inline void
+syslog(int priority, ...) {}
+
+#define LOG_ERR 0
+#define LOG_WARNING 1
+#define LOG_INFO 2
+/*****************************************/
+
+/****f* OpenSM: osm_common/GetOsmPath
+* NAME
+*      GetOsmPath
+*
+* DESCRIPTION
+*      The function retrieve the temp path defined in Windows using its API
+*
+* SYNOPSIS
+*/
+char*
+GetOsmPath(void);
+/*
+* PARAMETERS
+*      NONE
+*
+* RETURN VALUE
+*      This function returns string containing the default temp path in windows
+*
+* NOTES
+*/
+
+/* Implementation of strtok_r for windows: since strtok in windows is safe,
+   just ignore the last variable, and call strtok. */
+static inline 
+char *strtok_r(char *s1, const char *s2, char **lasts)
+{
+  return strtok(s1, s2);
+}
+#endif         /* _OSM_COMMON_H_ */
diff --git a/trunk/ulp/opensm/user/libopensm/Makefile b/trunk/ulp/opensm/user/libopensm/Makefile
new file mode 100755 (executable)
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/trunk/ulp/opensm/user/libopensm/SOURCES b/trunk/ulp/opensm/user/libopensm/SOURCES
new file mode 100644 (file)
index 0000000..370e2bc
--- /dev/null
@@ -0,0 +1,63 @@
+!if $(FREEBUILD)
+TARGETNAME=opensm_ibal
+!else
+TARGETNAME=opensm_ibald
+!endif
+TARGETTYPE=LIBRARY
+
+!if !defined(WINIBHOME)
+WINIBHOME=..\..\..\..
+!endif
+
+LIBPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)
+
+!if defined(OSM_TARGET)
+TARGETPATH=$(OSM_TARGET)\bin\user\obj$(BUILD_ALT_DIR)
+!else
+TARGETPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)
+!endif
+
+USE_NTDLL=1
+OVR_DIR=..\addon
+
+
+SOURCES=\
+   osm_log.c \
+   osm_mad_pool.c \
+   osm_helper.c
+
+OSM_HOME=..
+
+TARGETLIBS=\
+!if $(FREEBUILD)
+                       $(LIBPATH)\*\ibal.lib \
+                       $(LIBPATH)\*\complib.lib \
+                       $(TARGETPATH)\*\osmv_ibal.lib \
+                       $(CRT_LIB_PATH)\msvcrt.lib
+
+!else
+                       $(LIBPATH)\*\ibald.lib \
+                       $(LIBPATH)\*\complibd.lib \
+                       $(TARGETPATH)\*\osmv_ibald.lib \
+                       $(CRT_LIB_PATH)\msvcrt.lib
+!endif
+
+#DO NOT TOUCH the order of search path , until ib_types.h merging process will be done
+INCLUDES= \
+       $(OSM_HOME)\include; \
+       $(OSM_HOME); \
+       $(WINIBHOME)\inc; \
+       $(WINIBHOME)\inc\user;
+
+# Could be any special flag needed for this project 
+USER_C_FLAGS=$(USER_C_FLAGS) /MD
+#Add preproccessor definitions
+C_DEFINES=$(C_DEFINES) -DWIN32 -D__WIN__ -D__i386__ -Dinline=__inline -DMT_LITTLE_ENDIAN -DOSM_VENDOR_INTF_AL
+!if !$(FREEBUILD)
+#C_DEFINES=$(C_DEFINES) -D_DEBUG -DDEBUG -DDBG
+C_DEFINES=$(C_DEFINES) 
+!endif
+
+LINKER_FLAGS= $(LINKER_FLAGS)
+MSC_WARNING_LEVEL= /W3
+#MSC_OPTIMIZATION= /O0
diff --git a/trunk/ulp/opensm/user/libopensm/osm_helper.c b/trunk/ulp/opensm/user/libopensm/osm_helper.c
new file mode 100644 (file)
index 0000000..6700805
--- /dev/null
@@ -0,0 +1,2006 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of opensm helper functions.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.19 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <complib/cl_memory.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_log.h>
+
+#define LINE_LENGTH 256
+
+/* we use two tables - one for queries and one for responses */
+const char* const __ib_sa_method_str[] =
+{
+  "RESERVED",                 /* 0 */
+  "SubnAdmGet",             /* 1 */
+  "SubnAdmSet",             /* 2 */
+  "RESERVED",                  /* 3 */
+  "RESERVED",                  /* 4 */
+  "RESERVED",                  /* 5 */
+  "SubnAdmReport",          /* 6 */
+  "RESERVED",                  /* 7 */
+  "RESERVED",                  /* 8 */
+  "RESERVED",                  /* 9 */
+  "RESERVED",                  /* A */
+  "RESERVED",                  /* B */
+  "RESERVED",                  /* C */
+  "RESERVED",                  /* D */
+  "RESERVED",                  /* E */
+  "RESERVED",                  /* F */
+  "RESERVED",                  /* 10 */
+  "RESERVED",                  /* 11 */
+  "SubnAdmGetTable",           /* 12 */
+  "SubnAdmGetTraceTable",      /* 13 */
+  "SubnAdmGetMulti",           /* 14 */
+  "SubnAdmDelete",          /* 15 */
+  "UNKNOWN"                   /* 16 */
+};
+
+const char* const __ib_sa_resp_method_str[] =
+{
+  "RESERVED",                 /* 80 */
+  "SubnAdmGetResp",            /* 81 */
+  "RESERVED (SetResp?)",    /* 82 */
+  "RESERVED",                  /* 83 */
+  "RESERVED",                  /* 84 */
+  "RESERVED",                  /* 85 */
+  "SubnAdmReportResp",         /* 86 */
+  "RESERVED",                  /* 87 */
+  "RESERVED",                  /* 88 */
+  "RESERVED",                  /* 89 */
+  "RESERVED",                  /* 8A */
+  "RESERVED",                  /* 8B */
+  "RESERVED",                  /* 8C */
+  "RESERVED",                  /* 8D */
+  "RESERVED",                  /* 8E */
+  "RESERVED",                  /* 8F */
+  "RESERVED",                  /* 90 */
+  "RESERVED",                  /* 91 */
+  "SubnAdmGetTableResp",       /* 92 */
+  "RESERVED",                  /* 93 */
+  "SubnAdmGetMultiResp",    /* 94 */
+  "SubnAdmDeleteResp",         /* 95 */
+  "UNKNOWN"
+};
+
+#define OSM_SA_METHOD_STR_UNKNOWN_VAL 0x16
+
+const char* const __ib_sm_method_str[] =
+{
+  "RESERVED0",              /* 0 */
+  "SubnGet",              /* 1 */
+  "SubnSet",              /* 2 */
+  "RESERVED3",               /* 3 */
+  "RESERVED4",               /* 4 */
+  "SubnTrap",                /* 5 */
+  "RESERVED6",               /* 6 */
+  "SubnTrapRepress",         /* 7 */
+  "RESERVED8",               /* 8 */
+  "RESERVED9",               /* 9 */
+  "RESERVEDA",               /* A */
+  "RESERVEDB",               /* B */
+  "RESERVEDC",               /* C */
+  "RESERVEDD",               /* D */
+  "RESERVEDE",               /* E */
+  "RESERVEDF",               /* F */
+  "RESERVED10",              /* 10 */
+  "SubnGetResp",             /* 11 */
+  "RESERVED12",           /* 12 */
+  "RESERVED13",           /* 13 */
+  "RESERVED14",           /* 14 */
+  "RESERVED15",           /* 15 */
+  "RESERVED16",              /* 16 */
+  "RESERVED17",           /* 17 */
+  "RESERVED18",           /* 18 */
+  "RESERVED19",           /* 19 */
+  "RESERVED1A",           /* 1A */
+  "RESERVED1B",           /* 1B */
+  "RESERVED1C",           /* 1C */
+  "RESERVED1D",           /* 1D */
+  "RESERVED1E",             /* 1E */
+  "RESERVED1F",             /* 1F */
+  "UNKNOWN"                  /* 20 */
+};
+
+#define OSM_SM_METHOD_STR_UNKNOWN_VAL 0x21
+
+const char* const __ib_sm_attr_str[] =
+{
+  "RESERVED",                     /* 0 */
+  "ClassPortInfo",             /* 1 */
+  "Notice",                    /* 2 */
+  "InformInfo",                /* 3 */
+  "RESERVED",                     /* 4 */
+  "RESERVED",                     /* 5 */
+  "RESERVED",                     /* 6 */
+  "RESERVED",                     /* 7 */
+  "RESERVED",                     /* 8 */
+  "RESERVED",                     /* 9 */
+  "RESERVED",                     /* A */
+  "RESERVED",                     /* B */
+  "RESERVED",                     /* C */
+  "RESERVED",                     /* D */
+  "RESERVED",                     /* E */
+  "RESERVED",                     /* F */
+  "NodeDescription",           /* 10 */
+  "NodeInfo",                     /* 11 */
+  "SwitchInfo",                /* 12 */
+  "UNKNOWN",                   /* 13 */
+  "GUIDInfo",                     /* 14 */
+  "PortInfo",                     /* 15 */
+  "P_KeyTable",                /* 16 */
+  "SLtoVLMappingTable",           /* 17 */
+  "VLArbitrationTable",           /* 18 */
+  "LinearForwardingTable",        /* 19 */
+  "RandomForwardingTable",        /* 1A */
+  "MulticastForwardingTable",        /* 1B */
+  "UNKNOWN",                   /* 1C */
+  "UNKNOWN",                   /* 1D */
+  "UNKNOWN",                   /* 1E */
+  "UNKNOWN",                   /* 1F */
+  "SMInfo",                    /* 20 */
+  "UNKNOWN"                    /* 21 - always highest value*/
+};
+
+#define OSM_SM_ATTR_STR_UNKNOWN_VAL 0x21
+
+const char* const __ib_sa_attr_str[] =
+{
+  "RESERVED",                     /* 0 */
+  "ClassPortInfo",             /* 1 */
+  "Notice",                    /* 2 */
+  "InformInfo",                /* 3 */
+  "RESERVED",                     /* 4 */
+  "RESERVED",                     /* 5 */
+  "RESERVED",                     /* 6 */
+  "RESERVED",                     /* 7 */
+  "RESERVED",                     /* 8 */
+  "RESERVED",                     /* 9 */
+  "RESERVED",                     /* A */
+  "RESERVED",                     /* B */
+  "RESERVED",                     /* C */
+  "RESERVED",                     /* D */
+  "RESERVED",                     /* E */
+  "RESERVED",                     /* F */
+  "RESERVED",                     /* 10 */
+  "NodeRecord",                /* 11 */
+  "PortInfoRecord",               /* 12 */
+  "SLtoVLMappingTableRecord",        /* 13 */
+  "SwitchInfoRecord",             /* 14 */
+  "LinearForwardingTableRecord",     /* 15 */
+  "RandomForwardingTableRecord",     /* 16 */
+  "MulticastForwardingTableRecord",  /* 17 */
+  "SMInfoRecord",                 /* 18 */
+  "RESERVED",                     /* 19 */
+  "RandomForwardingTable",        /* 1A */
+  "MulticastForwardingTable",        /* 1B */
+  "UNKNOWN",                   /* 1C */
+  "UNKNOWN",                   /* 1D */
+  "UNKNOWN",                   /* 1E */
+  "UNKNOWN",                   /* 1F */
+  "LinkRecord",                /* 20 */
+  "UNKNOWN",                   /* 21 */
+  "UNKNOWN",                   /* 22 */
+  "UNKNOWN",                   /* 23 */
+  "UNKNOWN",                   /* 24 */
+  "UNKNOWN",                   /* 25 */
+  "UNKNOWN",                   /* 26 */
+  "UNKNOWN",                   /* 27 */
+  "UNKNOWN",                   /* 28 */
+  "UNKNOWN",                   /* 29 */
+  "UNKNOWN",                   /* 2A */
+  "UNKNOWN",                   /* 2B */
+  "UNKNOWN",                   /* 2C */
+  "UNKNOWN",                   /* 2D */
+  "UNKNOWN",                   /* 2E */
+  "UNKNOWN",                   /* 2F */
+  "GuidInfoRecord",               /* 30 */
+  "ServiceRecord",             /* 31 */
+  "UNKNOWN",                   /* 32 */
+  "P_KeyTableRecord",             /* 33 */
+  "UNKNOWN",                   /* 34 */
+  "PathRecord",                /* 35 */
+  "VLArbitrationTableRecord",        /* 36 */
+  "UNKNOWN",                   /* 37 */
+  "MCMemberRecord",               /* 38 */
+  "TraceRecord",                  /* 39 */
+  "MultiPathRecord",              /* 3A */
+  "ServiceAssociationRecord",        /* 3B */
+  "UNKNOWN"                    /* 3C - always highest value*/
+};
+
+#define OSM_SA_ATTR_STR_UNKNOWN_VAL 0x3C
+
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+ib_get_sa_method_str(
+  IN uint8_t method )
+{
+  if (method & 0x80)
+  {
+    method = method & 0x7f;
+    if( method >= OSM_SA_METHOD_STR_UNKNOWN_VAL  )
+      method = OSM_SA_METHOD_STR_UNKNOWN_VAL;
+    /* it is a response - use the reponse table */
+    return( __ib_sa_resp_method_str[method] );
+  }
+  else
+  {
+    if( method >= OSM_SA_METHOD_STR_UNKNOWN_VAL  )
+      method = OSM_SA_METHOD_STR_UNKNOWN_VAL;
+    return( __ib_sa_method_str[method] );
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+ib_get_sm_method_str(
+  IN uint8_t method )
+{
+  if (method & 0x80) method = (method & 0x0F) | 0x10;
+  if( method >= OSM_SM_METHOD_STR_UNKNOWN_VAL  )
+    method = OSM_SM_METHOD_STR_UNKNOWN_VAL;
+  return( __ib_sm_method_str[method] );
+}
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+ib_get_sm_attr_str(
+  IN ib_net16_t attr )
+{
+  uint16_t host_attr;
+  host_attr = cl_ntoh16( attr );
+
+  if( host_attr >= OSM_SM_ATTR_STR_UNKNOWN_VAL  )
+    host_attr = OSM_SM_ATTR_STR_UNKNOWN_VAL;
+
+  return( __ib_sm_attr_str[host_attr] );
+}
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+ib_get_sa_attr_str(
+  IN ib_net16_t attr )
+{
+  uint16_t host_attr;
+  host_attr = cl_ntoh16( attr );
+
+  if( host_attr >= OSM_SA_ATTR_STR_UNKNOWN_VAL  )
+    host_attr = OSM_SA_ATTR_STR_UNKNOWN_VAL;
+
+  return( __ib_sa_attr_str[host_attr] );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_dbg_do_line(
+  IN char** pp_local,
+  IN const uint32_t buf_size,
+  IN const char* const p_prefix_str,
+  IN const char* const p_new_str,
+  IN uint32_t* const p_total_len )
+{
+  char line[LINE_LENGTH];
+  uint32_t len;
+
+  sprintf( line, "%s%s", p_prefix_str, p_new_str );
+  len = (uint32_t) strlen( line );
+  *p_total_len += len;
+  if( *p_total_len + sizeof('\0') > buf_size )
+    return( IB_INSUFFICIENT_MEMORY );
+
+  strcpy( *pp_local, line );
+  *pp_local += len;
+  return( IB_SUCCESS );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dbg_get_capabilities_str(
+  IN char* p_buf,
+  IN const uint32_t buf_size,
+  IN const char* const p_prefix_str,
+  IN const ib_port_info_t* const p_pi )
+{
+  uint32_t total_len = 0;
+  char *p_local = p_buf;
+
+  strcpy( p_local, "Capabilities Mask:\n" );
+  p_local += strlen( p_local );
+
+  if( p_pi->capability_mask & IB_PORT_CAP_RESV0 )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_RESV0\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_IS_SM )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_IS_SM\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_NOTICE )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_HAS_NOTICE\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_TRAP )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_HAS_TRAP\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_IPD )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_HAS_IPD\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_AUTO_MIG )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_HAS_AUTO_MIG\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_SL_MAP )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_HAS_SL_MAP\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_NV_MKEY )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_HAS_NV_MKEY\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_NV_PKEY )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_HAS_NV_PKEY\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_LED_INFO )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_HAS_LED_INFO\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_SM_DISAB )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_SM_DISAB\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_SYS_IMG_GUID )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_HAS_SYS_IMG_GUID\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_PKEY_SW_EXT_PORT_TRAP )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_PKEY_SW_EXT_PORT_TRAP\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_RESV13 )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_RESV13\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_RESV14 )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_RESV14\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_RESV15 )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_RESV15\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_COM_MGT )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_HAS_COM_MGT\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_SNMP )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_HAS_SNMP\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_REINIT )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_REINIT\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_DEV_MGT )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_HAS_DEV_MGT\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_VEND_CLS )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_HAS_VEND_CLS\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_DR_NTC )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_HAS_DR_NTC\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_CAP_NTC )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_HAS_CAP_NTC\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_BM )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_HAS_BM\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_LINK_RT_LATENCY )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_HAS_LINK_RT_LATENCY\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_HAS_CLIENT_REREG )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_HAS_CLIENT_REREG\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_RESV26 )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_RESV26\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_RESV27 )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_RESV27\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_RESV28)
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_RESV28\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_RESV29 )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_RESV29\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_RESV30 )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_RESV30\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+  if( p_pi->capability_mask & IB_PORT_CAP_RESV31 )
+  {
+    if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,
+                         "IB_PORT_CAP_RESV31\n", &total_len ) != IB_SUCCESS )
+      return;
+  }
+
+  return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+  char buf[BUF_SIZE];
+
+  if( osm_log_is_active( p_log, log_level ) )
+  {
+    osm_log( p_log, log_level,
+             "PortInfo dump:\n"
+             "\t\t\t\tport number.............0x%X\n"
+             "\t\t\t\tnode_guid...............0x%016" PRIx64 "\n"
+             "\t\t\t\tport_guid...............0x%016" PRIx64 "\n"
+             "\t\t\t\tm_key...................0x%016" PRIx64 "\n"
+             "\t\t\t\tsubnet_prefix...........0x%016" PRIx64 "\n"
+             "\t\t\t\tbase_lid................0x%X\n"
+             "\t\t\t\tmaster_sm_base_lid......0x%X\n"
+             "\t\t\t\tcapability_mask.........0x%X\n"
+             "\t\t\t\tdiag_code...............0x%X\n"
+             "\t\t\t\tm_key_lease_period......0x%X\n"
+             "\t\t\t\tlocal_port_num..........0x%X\n"
+             "\t\t\t\tlink_width_enabled......0x%X\n"
+             "\t\t\t\tlink_width_supported....0x%X\n"
+             "\t\t\t\tlink_width_active.......0x%X\n"
+             "\t\t\t\tlink_speed_supported....0x%X\n"
+             "\t\t\t\tport_state..............%s\n"
+             "\t\t\t\tstate_info2.............0x%X\n"
+             "\t\t\t\tm_key_protect_bits......0x%X\n"
+             "\t\t\t\tlmc.....................0x%X\n"
+             "\t\t\t\tlink_speed..............0x%X\n"
+             "\t\t\t\tmtu_smsl................0x%X\n"
+             "\t\t\t\tvl_cap_init_type........0x%X\n"
+             "\t\t\t\tvl_high_limit...........0x%X\n"
+             "\t\t\t\tvl_arb_high_cap.........0x%X\n"
+             "\t\t\t\tvl_arb_low_cap..........0x%X\n"
+             "\t\t\t\tinit_rep_mtu_cap........0x%X\n"
+             "\t\t\t\tvl_stall_life...........0x%X\n"
+             "\t\t\t\tvl_enforce..............0x%X\n"
+             "\t\t\t\tm_key_violations........0x%X\n"
+             "\t\t\t\tp_key_violations........0x%X\n"
+             "\t\t\t\tq_key_violations........0x%X\n"
+             "\t\t\t\tguid_cap................0x%X\n"
+             "\t\t\t\tsubnet_timeout..........0x%X\n"
+             "\t\t\t\tresp_time_value.........0x%X\n"
+             "\t\t\t\terror_threshold.........0x%X\n"
+             "",
+             port_num,
+             cl_ntoh64( node_guid ),
+             cl_ntoh64( port_guid ),
+             cl_ntoh64( p_pi->m_key ),
+             cl_ntoh64( p_pi->subnet_prefix ),
+             cl_ntoh16( p_pi->base_lid ),
+             cl_ntoh16( p_pi->master_sm_base_lid ),
+             cl_ntoh32( p_pi->capability_mask ),
+             cl_ntoh16( p_pi->diag_code ),
+             cl_ntoh16( p_pi->m_key_lease_period ),
+             p_pi->local_port_num,
+             p_pi->link_width_enabled,
+             p_pi->link_width_supported,
+             p_pi->link_width_active,
+             ib_port_info_get_link_speed_sup( p_pi ),
+             ib_get_port_state_str( ib_port_info_get_port_state( p_pi ) ),
+             p_pi->state_info2,
+             ib_port_info_get_mpb( p_pi ),
+             ib_port_info_get_lmc( p_pi ),
+             p_pi->link_speed,
+             p_pi->mtu_smsl,
+             p_pi->vl_cap,
+             p_pi->vl_high_limit,
+             p_pi->vl_arb_high_cap,
+             p_pi->vl_arb_low_cap,
+             p_pi->mtu_cap,
+             p_pi->vl_stall_life,
+             p_pi->vl_enforce,
+             cl_ntoh16( p_pi->m_key_violations ),
+             cl_ntoh16( p_pi->p_key_violations ),
+             cl_ntoh16( p_pi->q_key_violations ),
+             p_pi->guid_cap,
+             ib_port_info_get_timeout(p_pi),
+             p_pi->resp_time_value,
+             p_pi->error_threshold
+             );
+
+    /*  show the capabilities mask */
+    osm_dbg_get_capabilities_str( buf, BUF_SIZE, "\t\t\t\t", p_pi );
+
+    osm_log( p_log, log_level,
+             "%s", buf );
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+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 )
+{
+  char buf[BUF_SIZE];
+  const ib_port_info_t * const p_pi = &p_pir->port_info;
+
+  if( osm_log_is_active( p_log, log_level ) )
+  {
+    osm_log( p_log, log_level,
+             "PortInfo Record dump:\n"
+             "\t\t\t\tRID\n"
+             "\t\t\t\tEndPortLid..............0x%X\n"
+             "\t\t\t\tPortNum.................0x%X\n"
+             "\t\t\t\tReserved................0x%X\n"
+             "\t\t\t\tPortInfo dump\n"
+             "\t\t\t\tm_key...................0x%016" PRIx64 "\n"
+             "\t\t\t\tsubnet_prefix...........0x%016" PRIx64 "\n"
+             "\t\t\t\tbase_lid................0x%X\n"
+             "\t\t\t\tmaster_sm_base_lid......0x%X\n"
+             "\t\t\t\tcapability_mask.........0x%X\n"
+             "\t\t\t\tdiag_code...............0x%X\n"
+             "\t\t\t\tm_key_lease_period......0x%X\n"
+             "\t\t\t\tlocal_port_num..........0x%X\n"
+             "\t\t\t\tlink_width_enabled......0x%X\n"
+             "\t\t\t\tlink_width_supported....0x%X\n"
+             "\t\t\t\tlink_width_active.......0x%X\n"
+             "\t\t\t\tlink_speed_supported....0x%X\n"
+             "\t\t\t\tport_state..............%s\n"
+             "\t\t\t\tstate_info2.............0x%X\n"
+             "\t\t\t\tm_key_protect_bits......0x%X\n"
+             "\t\t\t\tlmc.....................0x%X\n"
+             "\t\t\t\tlink_speed..............0x%X\n"
+             "\t\t\t\tmtu_smsl................0x%X\n"
+             "\t\t\t\tvl_cap_init_type........0x%X\n"
+             "\t\t\t\tvl_high_limit...........0x%X\n"
+             "\t\t\t\tvl_arb_high_cap.........0x%X\n"
+             "\t\t\t\tvl_arb_low_cap..........0x%X\n"
+             "\t\t\t\tinit_rep_mtu_cap........0x%X\n"
+             "\t\t\t\tvl_stall_life...........0x%X\n"
+             "\t\t\t\tvl_enforce..............0x%X\n"
+             "\t\t\t\tm_key_violations........0x%X\n"
+             "\t\t\t\tp_key_violations........0x%X\n"
+             "\t\t\t\tq_key_violations........0x%X\n"
+             "\t\t\t\tguid_cap................0x%X\n"
+             "\t\t\t\tsubnet_timeout..........0x%X\n"
+             "\t\t\t\tresp_time_value.........0x%X\n"
+             "\t\t\t\terror_threshold.........0x%X\n"
+             "",
+             cl_ntoh16(p_pir->lid),
+             p_pir->port_num,
+             p_pir->resv,
+             cl_ntoh64( p_pi->m_key ),
+             cl_ntoh64( p_pi->subnet_prefix ),
+             cl_ntoh16( p_pi->base_lid ),
+             cl_ntoh16( p_pi->master_sm_base_lid ),
+             cl_ntoh32( p_pi->capability_mask ),
+             cl_ntoh16( p_pi->diag_code ),
+             cl_ntoh16( p_pi->m_key_lease_period ),
+             p_pi->local_port_num,
+             p_pi->link_width_enabled,
+             p_pi->link_width_supported,
+             p_pi->link_width_active,
+             ib_port_info_get_link_speed_sup( p_pi ),
+             ib_get_port_state_str( ib_port_info_get_port_state( p_pi ) ),
+             p_pi->state_info2,
+             ib_port_info_get_mpb( p_pi ),
+             ib_port_info_get_lmc( p_pi ),
+             p_pi->link_speed,
+             p_pi->mtu_smsl,
+             p_pi->vl_cap,
+             p_pi->vl_high_limit,
+             p_pi->vl_arb_high_cap,
+             p_pi->vl_arb_low_cap,
+             p_pi->mtu_cap,
+             p_pi->vl_stall_life,
+             p_pi->vl_enforce,
+             cl_ntoh16( p_pi->m_key_violations ),
+             cl_ntoh16( p_pi->p_key_violations ),
+             cl_ntoh16( p_pi->q_key_violations ),
+             p_pi->guid_cap,
+             ib_port_info_get_timeout( p_pi ),
+             p_pi->resp_time_value,
+             p_pi->error_threshold
+             );
+
+    /*  show the capabilities mask */
+    osm_dbg_get_capabilities_str( buf, BUF_SIZE, "\t\t\t\t", p_pi );
+
+    osm_log( p_log, log_level,
+             "%s", buf );
+  }
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+  if( osm_log_is_active( p_log, log_level ) )
+  {
+    osm_log( p_log, log_level,
+             "NodeInfo dump:\n"
+             "\t\t\t\tbase_version............0x%X\n"
+             "\t\t\t\tclass_version...........0x%X\n"
+             "\t\t\t\tnode_type...............%s\n"
+             "\t\t\t\tnum_ports...............0x%X\n"
+             "\t\t\t\tsys_guid................0x%016" PRIx64 "\n"
+             "\t\t\t\tnode_guid...............0x%016" PRIx64 "\n"
+             "\t\t\t\tport_guid...............0x%016" PRIx64 "\n"
+             "\t\t\t\tpartition_cap...........0x%X\n"
+             "\t\t\t\tdevice_id...............0x%X\n"
+             "\t\t\t\trevision................0x%X\n"
+             "\t\t\t\tport_num................0x%X\n"
+             "\t\t\t\tvendor_id...............0x%X\n"
+             "",
+             p_ni->base_version,
+             p_ni->class_version,
+             ib_get_node_type_str( p_ni->node_type ),
+             p_ni->num_ports,
+             cl_ntoh64( p_ni->sys_guid ),
+             cl_ntoh64( p_ni->node_guid ),
+             cl_ntoh64( p_ni->port_guid ),
+             cl_ntoh16( p_ni->partition_cap ),
+             cl_ntoh16( p_ni->device_id ),
+             cl_ntoh32( p_ni->revision ),
+             ib_node_info_get_local_port_num( p_ni ),
+             cl_ntoh32( ib_node_info_get_vendor_id( p_ni ) )
+             );
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+  const ib_node_info_t * const p_ni = &p_nr->node_info;
+
+  if( osm_log_is_active( p_log, log_level ) )
+  {
+    osm_log( p_log, log_level,
+             "NodeRecord dump:\n"
+             "\t\t\t\tRID\n"
+             "\t\t\t\tLid.....................0x%X\n"
+             "\t\t\t\tReserved................0x%X\n"
+             "\t\t\t\tNodeInfoDump\n"
+             "\t\t\t\tbase_version............0x%X\n"
+             "\t\t\t\tclass_version...........0x%X\n"
+             "\t\t\t\tnode_type...............%s\n"
+             "\t\t\t\tnum_ports...............0x%X\n"
+             "\t\t\t\tsys_guid................0x%016" PRIx64 "\n"
+             "\t\t\t\tnode_guid...............0x%016" PRIx64 "\n"
+             "\t\t\t\tport_guid...............0x%016" PRIx64 "\n"
+             "\t\t\t\tpartition_cap...........0x%X\n"
+             "\t\t\t\tdevice_id...............0x%X\n"
+             "\t\t\t\trevision................0x%X\n"
+             "\t\t\t\tport_num................0x%X\n"
+             "\t\t\t\tvendor_id...............0x%X\n"
+             "\t\t\t\tNodeDescription\n"
+             "\t\t\t\t%s\n"
+             "",
+             cl_ntoh16(p_nr->lid),
+             cl_ntoh16(p_nr->resv),
+             p_ni->base_version,
+             p_ni->class_version,
+             ib_get_node_type_str( p_ni->node_type ),
+             p_ni->num_ports,
+             cl_ntoh64( p_ni->sys_guid ),
+             cl_ntoh64( p_ni->node_guid ),
+             cl_ntoh64( p_ni->port_guid ),
+             cl_ntoh16( p_ni->partition_cap ),
+             cl_ntoh16( p_ni->device_id ),
+             cl_ntoh32( p_ni->revision ),
+             ib_node_info_get_local_port_num( p_ni ),
+             cl_ntoh32( ib_node_info_get_vendor_id( p_ni )),
+             p_nr->node_desc.description
+             );
+
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+  if( osm_log_is_active( p_log, log_level ) )
+  {
+    osm_log( p_log, log_level,
+             "PathRecord dump:\n"
+             "\t\t\t\tresv0...................0x%016" PRIx64 "\n"
+             "\t\t\t\tdgid....................0x%016" PRIx64 " : "
+             "0x%016" PRIx64 "\n"
+             "\t\t\t\tsgid....................0x%016" PRIx64 " : "
+             "0x%016" PRIx64 "\n"
+             "\t\t\t\tdlid....................0x%X\n"
+             "\t\t\t\tslid....................0x%X\n"
+             "\t\t\t\thop_flow_raw............0x%X\n"
+             "\t\t\t\ttclass..................0x%X\n"
+             "\t\t\t\tnum_path_revers.........0x%X\n"
+             "\t\t\t\tpkey....................0x%X\n"
+             "\t\t\t\tsl......................0x%X\n"
+             "\t\t\t\tmtu.....................0x%X\n"
+             "\t\t\t\trate....................0x%X\n"
+             "\t\t\t\tpkt_life................0x%X\n"
+             "\t\t\t\tpreference..............0x%X\n"
+             "\t\t\t\tresv2...................0x%X\n"
+             "\t\t\t\tresv3...................0x%X\n"
+             "",
+             *(uint64_t*)p_pr->resv0,
+             cl_ntoh64( p_pr->dgid.unicast.prefix ),
+             cl_ntoh64( p_pr->dgid.unicast.interface_id ),
+             cl_ntoh64( p_pr->sgid.unicast.prefix ),
+             cl_ntoh64( p_pr->sgid.unicast.interface_id ),
+             cl_ntoh16( p_pr->dlid ),
+             cl_ntoh16( p_pr->slid ),
+             cl_ntoh32( p_pr->hop_flow_raw ),
+             p_pr->tclass,
+             p_pr->num_path,
+             cl_ntoh16( p_pr->pkey ),
+             cl_ntoh16( p_pr->sl ),
+             cl_ntoh16( p_pr->sl ),
+             p_pr->mtu,
+             p_pr->rate,
+             p_pr->pkt_life,
+             p_pr->preference,
+             *(uint32_t*)&p_pr->resv2,
+             *((uint16_t*)&p_pr->resv2 + 2)
+             );
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+
+  if( osm_log_is_active( p_log, log_level ) )
+  {
+    osm_log( p_log, log_level,
+             "MCMember Record dump:\n"
+             "\t\t\t\tMGID....................0x%016" PRIx64 " : "
+             "0x%016" PRIx64 "\n"
+             "\t\t\t\tPortGid.................0x%016" PRIx64 " : "
+             "0x%016" PRIx64 "\n"
+             "\t\t\t\tqkey....................0x%X\n"
+             "\t\t\t\tMlid....................0x%X\n"
+             "\t\t\t\tScopeState..............0x%X\n"
+             "\t\t\t\tRate....................0x%X\n"
+             "\t\t\t\tMtu.....................0x%X\n"
+             "\t\t\t\tTClass..................0x%X\n"
+             "\t\t\t\tSLFlowLabelHopLimit.....0x%X\n"
+             "",
+             cl_ntoh64( p_mcmr->mgid.unicast.prefix ),
+             cl_ntoh64( p_mcmr->mgid.unicast.interface_id ),
+             cl_ntoh64( p_mcmr->port_gid.unicast.prefix ),
+             cl_ntoh64( p_mcmr->port_gid.unicast.interface_id ),
+             cl_ntoh32( p_mcmr->qkey ),
+             cl_ntoh16( p_mcmr->mlid ),
+             p_mcmr->scope_state,
+             p_mcmr->rate,
+             p_mcmr->mtu,
+             p_mcmr->tclass,
+             cl_ntoh32( p_mcmr->sl_flow_hop )
+             );
+  }
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+  char buf_service_key[33];
+  char buf_service_name[65];
+
+  if( osm_log_is_active( p_log, log_level ) )
+  {
+    sprintf(buf_service_key,
+            "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+            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]);
+    strncpy(buf_service_name, (char *)p_sr->service_name, 64);
+    buf_service_name[64] = '\0';
+
+    osm_log( p_log, log_level,
+             "ServiceRecord dump:\n"
+             "\t\t\t\tServiceID...............0x%016" PRIx64 "\n"
+             "\t\t\t\tServiceGID..............0x%016" PRIx64 " : "
+             "0x%016" PRIx64 "\n"
+             "\t\t\t\tServiceP_Key............0x%X\n"
+             "\t\t\t\tServiceLease............0x%X\n"
+             "\t\t\t\tServiceKey..............%s\n"
+             "\t\t\t\tServiceName.............%s\n"
+             "\t\t\t\tServiceData8.1..........0x%X\n"
+             "\t\t\t\tServiceData8.2..........0x%X\n"
+             "\t\t\t\tServiceData8.3..........0x%X\n"
+             "\t\t\t\tServiceData8.4..........0x%X\n"
+             "\t\t\t\tServiceData8.5..........0x%X\n"
+             "\t\t\t\tServiceData8.6..........0x%X\n"
+             "\t\t\t\tServiceData8.7..........0x%X\n"
+             "\t\t\t\tServiceData8.8..........0x%X\n"
+             "\t\t\t\tServiceData8.9..........0x%X\n"
+             "\t\t\t\tServiceData8.10.........0x%X\n"
+             "\t\t\t\tServiceData8.11.........0x%X\n"
+             "\t\t\t\tServiceData8.12.........0x%X\n"
+             "\t\t\t\tServiceData8.13.........0x%X\n"
+             "\t\t\t\tServiceData8.14.........0x%X\n"
+             "\t\t\t\tServiceData8.15.........0x%X\n"
+             "\t\t\t\tServiceData8.16.........0x%X\n"
+             "\t\t\t\tServiceData16.1.........0x%X\n"
+             "\t\t\t\tServiceData16.2.........0x%X\n"
+             "\t\t\t\tServiceData16.3.........0x%X\n"
+             "\t\t\t\tServiceData16.4.........0x%X\n"
+             "\t\t\t\tServiceData16.5.........0x%X\n"
+             "\t\t\t\tServiceData16.6.........0x%X\n"
+             "\t\t\t\tServiceData16.7.........0x%X\n"
+             "\t\t\t\tServiceData16.8.........0x%X\n"
+             "\t\t\t\tServiceData32.1.........0x%X\n"
+             "\t\t\t\tServiceData32.2.........0x%X\n"
+             "\t\t\t\tServiceData32.3.........0x%X\n"
+             "\t\t\t\tServiceData32.4.........0x%X\n"
+             "\t\t\t\tServiceData64.1.........0x%016" PRIx64 "\n"
+             "\t\t\t\tServiceData64.2.........0x%016" PRIx64 "\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 ),
+             buf_service_key,
+             buf_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])
+             );
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+  uint32_t qpn;
+  uint8_t  resp_time_val;
+  ib_inform_info_get_qpn_resp_time(p_ii->g_or_v.generic.qpn_resp_time_val,
+                                   &qpn,&resp_time_val);
+
+  if( osm_log_is_active( p_log, log_level ) )
+  {
+    if (p_ii->is_generic)
+    {
+      osm_log( p_log, log_level,
+               "InformInfo dump:\n"
+               "\t\t\t\tgid.....................0x%016" PRIx64 ",%016" PRIx64 "\n"
+               "\t\t\t\tlid_range_begin.........0x%X\n"
+               "\t\t\t\tlid_range_end...........0x%X\n"
+               "\t\t\t\tis_generic..............0x%X\n"
+               "\t\t\t\tsubscribe...............0x%X\n"
+               "\t\t\t\ttrap_type...............0x%X\n"
+               "\t\t\t\ttrap_num................0x%X\n"
+               "\t\t\t\tqpn.....................0x%06X\n"
+               "\t\t\t\tresp_time_val...........0x%X\n"
+               "\t\t\t\tnode_type...............0x%06X\n"
+               "",
+               cl_ntoh64( p_ii->gid.unicast.prefix ),
+               cl_ntoh64( p_ii->gid.unicast.interface_id ),
+               cl_ntoh16( p_ii->lid_range_begin ),
+               cl_ntoh16( p_ii->lid_range_end ),
+               p_ii->is_generic,
+               p_ii->subscribe,
+               cl_ntoh16( p_ii->trap_type ),
+               cl_ntoh16( p_ii->g_or_v.generic.trap_num ),
+               cl_ntoh32(qpn),
+               resp_time_val,
+               cl_ntoh32(ib_inform_info_get_node_type( p_ii ))
+               );
+    }
+    else
+    {
+      osm_log( p_log, log_level,
+               "InformInfo dump:\n"
+               "\t\t\t\tgid.....................0x%016" PRIx64 ",%016" PRIx64 "\n"
+               "\t\t\t\tlid_range_begin.........0x%X\n"
+               "\t\t\t\tlid_range_end...........0x%X\n"
+               "\t\t\t\tis_generic..............0x%X\n"
+               "\t\t\t\tsubscribe...............0x%X\n"
+               "\t\t\t\ttrap_type...............0x%X\n"
+               "\t\t\t\tdev_id..................0x%X\n"
+               "\t\t\t\tqpn.....................0x%06X\n"
+               "\t\t\t\tresp_time_val...........0x%X\n"
+               "\t\t\t\tvendor_id...............0x%06X\n"
+               "",
+               cl_ntoh64( p_ii->gid.unicast.prefix ),
+               cl_ntoh64( p_ii->gid.unicast.interface_id ),
+               cl_ntoh16( p_ii->lid_range_begin ),
+               cl_ntoh16( p_ii->lid_range_end ),
+               p_ii->is_generic,
+               p_ii->subscribe,
+               cl_ntoh16( p_ii->trap_type ),
+               cl_ntoh16( p_ii->g_or_v.vend.dev_id ),
+               cl_ntoh32(qpn),
+               resp_time_val,
+               cl_ntoh32(ib_inform_info_get_node_type( p_ii ))
+               );
+    }
+  }
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+  if( osm_log_is_active( p_log, log_level ) )
+  {
+    osm_log( p_log, log_level,
+             "LinkRecord dump:\n"
+             "\t\t\t\tfrom_lid................0x%X\n"
+             "\t\t\t\tfrom_port_num...........0x%X\n"
+             "\t\t\t\tto_port_num.............0x%X\n"
+             "\t\t\t\tto_lid..................0x%X\n"
+             "",
+             cl_ntoh16( p_lr->from_lid ),
+             p_lr->from_port_num,
+             p_lr->to_port_num,
+             cl_ntoh16( p_lr->to_lid )
+             );
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+  if( osm_log_is_active( p_log, log_level ) )
+  {
+    osm_log( p_log, OSM_LOG_VERBOSE,
+             "SwitchInfo dump:\n"
+             "\t\t\t\tlin_cap.................0x%X\n"
+             "\t\t\t\trand_cap................0x%X\n"
+             "\t\t\t\tmcast_cap...............0x%X\n"
+             "\t\t\t\tlin_top.................0x%X\n"
+             "\t\t\t\tdef_port................0x%X\n"
+             "\t\t\t\tdef_mcast_pri_port......0x%X\n"
+             "\t\t\t\tdef_mcast_not_port......0x%X\n"
+             "\t\t\t\tlife_state..............0x%X\n"
+             "\t\t\t\tlids_per_port...........0x%X\n"
+             "\t\t\t\tenforce_cap.............0x%X\n"
+             "\t\t\t\tflags...................0x%X\n"
+             "",
+             cl_ntoh16( p_si->lin_cap ),
+             cl_ntoh16( p_si->rand_cap ),
+             cl_ntoh16( p_si->mcast_cap ),
+             cl_ntoh16( p_si->lin_top ),
+             p_si->def_port,
+             p_si->def_mcast_pri_port,
+             p_si->def_mcast_not_port,
+             p_si->life_state,
+             cl_ntoh16( p_si->lids_per_port ),
+             cl_ntoh16( p_si->enforce_cap ),
+             p_si->flags
+             );
+  }
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+  int i;
+  char buf_line[1024];
+
+  if( osm_log_is_active( p_log, log_level ) )
+  {
+    buf_line[0] = '\0';
+    for (i = 0; i<32; i++)
+      sprintf( buf_line,"%s 0x%04x |",
+               buf_line, cl_ntoh16(p_pkey_tbl->pkey_entry[i]));
+
+    osm_log( p_log, log_level,
+             "P_Key table dump:\n"
+             "\t\t\tport_guid...........0x%016" PRIx64 "\n"
+             "\t\t\tblock_num...........0x%X\n"
+             "\t\t\tport_num............0x%X\n\tP_Key Table: %s\n",
+             cl_ntoh64( port_guid ),
+             block_num,
+             port_num,
+             buf_line
+             );
+  }
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+  uint8_t i;
+  char buf_line1[1024];
+  char buf_line2[1024];
+  if( osm_log_is_active( p_log, log_level ) )
+  {
+    buf_line1[0] = '\0';
+    buf_line2[0] = '\0';
+    for (i = 0; i<16; i++) sprintf( buf_line1,"%s %-2u |", buf_line1, i);
+    for (i = 0; i<16; i++) sprintf( buf_line2,"%s0x%01X |",
+                                    buf_line2, ib_slvl_table_get(p_slvl_tbl, i));
+    osm_log( p_log, log_level,
+             "SLtoVL dump:\n"
+             "\t\t\tport_guid............0x%016" PRIx64 "\n"
+             "\t\t\tin_port_num..........0x%X\n"
+             "\t\t\tout_port_num.........0x%X\n\tSL: | %s\n\tVL: | %s\n",
+             cl_ntoh64( port_guid ),
+             in_port_num,
+             out_port_num,
+             buf_line1, buf_line2
+             );
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+  int i;
+  char buf_line1[1024];
+  char buf_line2[1024];
+  if( osm_log_is_active( p_log, log_level ) )
+  {
+    buf_line1[0] = '\0';
+    buf_line2[0] = '\0';
+    for (i = 0; i<32; i++) sprintf( buf_line1,"%s 0x%01X |",
+                                    buf_line1, p_vla_tbl->vl_entry[i].vl);
+    for (i = 0; i<32; i++) sprintf( buf_line2,"%s 0x%01X |",
+                                    buf_line2, p_vla_tbl->vl_entry[i].weight);
+    osm_log( p_log, log_level,
+             "VlArb dump:\n"
+             "\t\t\tport_guid...........0x%016" PRIx64 "\n"
+             "\t\t\tblock_num...........0x%X\n"
+             "\t\t\tport_num............0x%X\n\tVL    : | %s\n\tWEIGHT:| %s\n",
+             cl_ntoh64( port_guid ),
+             block_num,
+             port_num,
+             buf_line1, buf_line2
+             );
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+  if( osm_log_is_active( p_log, log_level ) )
+  {
+    osm_log( p_log, OSM_LOG_DEBUG,
+             "SMInfo dump:\n"
+             "\t\t\t\tguid....................0x%016" PRIx64 "\n"
+             "\t\t\t\tsm_key..................0x%016" PRIx64 "\n"
+             "\t\t\t\tact_count...............%u\n"
+             "\t\t\t\tpriority................%u\n"
+             "\t\t\t\tsm_state................%u\n"
+             "",
+             cl_ntoh64( p_smi->guid ),
+             cl_ntoh64( p_smi->sm_key ),
+             cl_ntoh32( p_smi->act_count ),
+             ib_sminfo_get_priority( p_smi ),
+             ib_sminfo_get_state( p_smi )
+             );
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+  char buff[1024];
+  buff[0] = '\0';
+  if( osm_log_is_active( p_log, log_level ) )
+  {
+    if (ib_notice_is_generic(p_ntci))
+    {
+      /* immediate data based on the trap */
+      switch (cl_ntoh16(p_ntci->g_or_v.generic.trap_num)) {
+      case 64:
+      case 65:
+      case 66:
+      case 67:
+        sprintf(buff,
+                "\t\t\t\tsrc_gid..................0x%016" PRIx64
+                ":0x%016" PRIx64 "\n",
+                cl_ntoh64(p_ntci->data_details.ntc_64_67.gid.unicast.prefix),
+                cl_ntoh64(p_ntci->data_details.ntc_64_67.gid.unicast.interface_id));
+        break;
+      case 128:
+        sprintf(buff,
+                "\t\t\t\tsw_lid...................0x%04X\n",
+                cl_ntoh16(p_ntci->data_details.ntc_128.sw_lid));
+        break;
+      case 129:
+      case 130:
+      case 131:
+        sprintf(buff,
+                "\t\t\t\tlid......................0x%04X\n"
+                "\t\t\t\tport_num.................%u\n",
+                cl_ntoh16(p_ntci->data_details.ntc_129_131.lid),
+                p_ntci->data_details.ntc_129_131.port_num);
+        break;
+      case 144:
+        sprintf(buff,
+                "\t\t\t\tlid......................0x%04x\n"
+                "\t\t\t\tnew_cap_mask.............0x%08x\n",
+                cl_ntoh16(p_ntci->data_details.ntc_144.lid),
+                cl_ntoh32(p_ntci->data_details.ntc_144.new_cap_mask));
+        break;
+      case 145:
+        sprintf(buff,
+                "\t\t\t\tlid......................0x%04X\n"
+                "\t\t\t\tnew_sys_guid.............0x%016" PRIx64 "\n",
+                cl_ntoh16(p_ntci->data_details.ntc_145.lid),
+                cl_ntoh64(p_ntci->data_details.ntc_145.new_sys_guid));
+        break;
+      }
+
+      osm_log( p_log, log_level,
+               "Generic Notice dump:\n"
+               "\t\t\t\ttype....................0x%02X\n"
+               "\t\t\t\tprod_type...............%u\n"
+               "\t\t\t\ttrap_num................%u\n%s"
+               "",
+               ib_notice_get_type(p_ntci),
+               cl_ntoh32(ib_notice_get_prod_type(p_ntci)),
+               cl_ntoh16(p_ntci->g_or_v.generic.trap_num),
+               buff
+               );
+    }
+    else
+    {
+      osm_log( p_log, log_level,
+               "Vendor Notice dump:\n"
+               "\t\t\t\ttype....................0x%04x\n"
+               "\t\t\t\tvendor..................%u\n"
+               "\t\t\t\tdevice_id...............%u\n"
+               "",
+               cl_ntoh16(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)
+               );
+    }
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 log_level )
+{
+  uint32_t i;
+  char buf[BUF_SIZE];
+  char line[BUF_SIZE];
+
+  if( osm_log_is_active( p_log, log_level ) )
+  {
+    sprintf( buf,
+             "SMP dump:\n"
+             "\t\t\t\tbase_ver................0x%X\n"
+             "\t\t\t\tmgmt_class..............0x%X\n"
+             "\t\t\t\tclass_ver...............0x%X\n"
+             "\t\t\t\tmethod..................0x%X (%s)\n",
+             p_smp->base_ver,
+             p_smp->mgmt_class,
+             p_smp->class_ver,
+             p_smp->method, ib_get_sm_method_str(p_smp->method));
+
+    if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR)
+    {
+      sprintf( line,
+               "\t\t\t\tD bit...................0x%X\n"
+               "\t\t\t\tstatus..................0x%X\n",
+               ib_smp_is_d(p_smp),
+               ib_smp_get_status(p_smp));
+    }
+    else
+    {
+      sprintf( line,
+               "\t\t\t\tstatus..................0x%X\n",
+               cl_ntoh16(p_smp->status));
+    }
+    strcat( buf, line );
+
+    sprintf( line,
+             "\t\t\t\thop_ptr.................0x%X\n"
+             "\t\t\t\thop_count...............0x%X\n"
+             "\t\t\t\ttrans_id................0x%" PRIx64 "\n"
+             "\t\t\t\tattr_id.................0x%X (%s)\n"
+             "\t\t\t\tresv....................0x%X\n"
+             "\t\t\t\tattr_mod................0x%X\n"
+             "\t\t\t\tm_key...................0x%016" PRIx64 "\n"
+             "\t\t\t\tdr_slid.................0x%X\n"
+             "\t\t\t\tdr_dlid.................0x%X\n",
+             p_smp->hop_ptr,
+             p_smp->hop_count,
+             cl_ntoh64(p_smp->trans_id),
+             cl_ntoh16(p_smp->attr_id),
+             ib_get_sm_attr_str( p_smp->attr_id ),
+             cl_ntoh16(p_smp->resv),
+             cl_ntoh32(p_smp->attr_mod),
+             cl_ntoh64(p_smp->m_key),
+             cl_ntoh16(p_smp->dr_slid),
+             cl_ntoh16(p_smp->dr_dlid)
+             );
+    strcat( buf, line );
+
+    if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR)
+    {
+      strcat( buf, "\n\t\t\t\tInitial path: " );
+
+      for( i = 0; i <= p_smp->hop_count; i++ )
+      {
+        sprintf( line, "[%X]", p_smp->initial_path[i] );
+        strcat( buf, line );
+      }
+
+      strcat( buf, "\n\t\t\t\tReturn path:  " );
+
+      for( i = 0; i <= p_smp->hop_count; i++ )
+      {
+        sprintf( line, "[%X]", p_smp->return_path[i] );
+        strcat( buf, line );
+      }
+
+      strcat( buf, "\n\t\t\t\tReserved:     " );
+
+      for( i = 0; i < 7; i++ )
+      {
+        sprintf( line, "[%0X]", p_smp->resv1[i] );
+        strcat( buf, line );
+      }
+
+      strcat( buf, "\n" );
+
+      for( i = 0; i < 64; i += 16 )
+      {
+        sprintf( line, "\n\t\t\t\t%02X %02X %02X %02X "
+                 "%02X %02X %02X %02X"
+                 "   %02X %02X %02X %02X %02X %02X %02X %02X\n",
+                 p_smp->data[i],
+                 p_smp->data[i+1],
+                 p_smp->data[i+2],
+                 p_smp->data[i+3],
+                 p_smp->data[i+4],
+                 p_smp->data[i+5],
+                 p_smp->data[i+6],
+                 p_smp->data[i+7],
+                 p_smp->data[i+8],
+                 p_smp->data[i+9],
+                 p_smp->data[i+10],
+                 p_smp->data[i+11],
+                 p_smp->data[i+12],
+                 p_smp->data[i+13],
+                 p_smp->data[i+14],
+                 p_smp->data[i+15] );
+
+        strcat( buf, line );
+      }
+    }
+    else
+    {
+      /* not a Direct Route so provide source and destination lids */
+      strcat(buf, "\t\t\t\tMAD IS LID ROUTED\n");
+    }
+
+    osm_log( p_log, log_level,
+             "%s\n", buf );
+
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_dump_sa_mad(
+  IN osm_log_t* const p_log,
+  IN const ib_sa_mad_t* const p_mad,
+  IN const osm_log_level_t log_level )
+{
+  char buf[BUF_SIZE];
+
+  /* make sure the mad is valid */
+  if (p_mad == NULL)
+  {
+    osm_log( p_log, log_level,
+             "NULL MAD POINTER\n");
+    return;
+  }
+
+  if( osm_log_is_active( p_log, log_level ) )
+  {
+    sprintf( buf,
+             "SA MAD dump:\n"
+             "\t\t\t\tbase_ver................0x%X\n"
+             "\t\t\t\tmgmt_class..............0x%X\n"
+             "\t\t\t\tclass_ver...............0x%X\n"
+             "\t\t\t\tmethod..................0x%X (%s)\n"
+             "\t\t\t\tstatus..................0x%X\n"
+             "\t\t\t\tresv....................0x%X\n"
+             "\t\t\t\ttrans_id................0x%" PRIx64 "\n"
+             "\t\t\t\tattr_id.................0x%X (%s)\n"
+             "\t\t\t\tresv1...................0x%X\n"
+             "\t\t\t\tattr_mod................0x%X\n"
+             "\t\t\t\trmpp_version............0x%X\n"
+             "\t\t\t\trmpp_type...............0x%X\n"
+             "\t\t\t\trmpp_flags..............0x%X\n"
+             "\t\t\t\trmpp_status.............0x%X\n"
+             "\t\t\t\tseg_num.................0x%X\n"
+             "\t\t\t\tpayload_len/new_win.....0x%X\n"
+             "\t\t\t\tsm_key..................0x%016" PRIx64 "\n"
+             "\t\t\t\tattr_offset.............0x%X\n"
+             "\t\t\t\tresv2...................0x%X\n"
+             "\t\t\t\tcomp_mask...............0x%016" PRIx64 "\n",
+             p_mad->base_ver,
+             p_mad->mgmt_class,
+             p_mad->class_ver,
+             p_mad->method, ib_get_sa_method_str(p_mad->method),
+             cl_ntoh16(p_mad->status),
+             cl_ntoh16(p_mad->resv),
+             cl_ntoh64(p_mad->trans_id),
+             cl_ntoh16(p_mad->attr_id),
+             ib_get_sa_attr_str( p_mad->attr_id ),
+             cl_ntoh16(p_mad->resv1),
+             cl_ntoh32(p_mad->attr_mod),
+             p_mad->rmpp_version,
+             p_mad->rmpp_type,
+             p_mad->rmpp_flags,
+             p_mad->rmpp_status,
+             cl_ntoh32(p_mad->seg_num),
+             cl_ntoh32(p_mad->paylen_newwin),
+             cl_ntoh64(p_mad->sm_key),
+             cl_ntoh16(p_mad->attr_offset),
+             cl_ntoh16(p_mad->resv3),
+             cl_ntoh64(p_mad->comp_mask)
+             );
+
+    strcat( buf, "\n" );
+
+    osm_log( p_log, log_level,
+             "%s\n", buf );
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 log_level)
+{
+  uint32_t i;
+  char buf[BUF_SIZE];
+  char line[BUF_SIZE];
+
+  if( osm_log_is_active( p_log, log_level) )
+  {
+    sprintf( buf, "Directed Path Dump of %u hop path:"
+             "\n\t\t\t\tPath = ", p_path->hop_count );
+
+    for( i = 0; i <= p_path->hop_count; i++ )
+    {
+      sprintf( line, "[%X]", p_path->path[i] );
+      strcat( buf, line );
+    }
+    osm_log( p_log, log_level,
+             "%s\n", buf );
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 log_level
+  )
+{
+  uint32_t i;
+  char buf[BUF_SIZE];
+  char line[BUF_SIZE];
+
+  if( osm_log_is_active( p_log, log_level) )
+  {
+    sprintf( buf, "Received a SMP on a %u hop path:"
+             "\n\t\t\t\tInitial path = ", p_smp->hop_count );
+
+    for( i = 0; i <= p_smp->hop_count; i++ )
+    {
+      sprintf( line, "[%X]", p_smp->initial_path[i] );
+      strcat( buf, line );
+    }
+
+    strcat( buf, "\n\t\t\t\tReturn path  = " );
+
+    for( i = 0; i <= p_smp->hop_count; i++ )
+    {
+      sprintf( line, "[%X]", p_smp->return_path[i] );
+      strcat( buf, line );
+    }
+
+    osm_log( p_log, log_level,
+             "%s\n", buf );
+  }
+}
+
+const char* const __osm_sm_state_str[] =
+{
+  "OSM_SM_STATE_NO_STATE",                 /* 0 */
+  "OSM_SM_STATE_INIT",                     /* 1 */
+  "OSM_SM_STATE_IDLE",                     /* 2 */
+  "OSM_SM_STATE_SWEEP_LIGHT",                 /* 3 */
+  "OSM_SM_STATE_SWEEP_LIGHT_WAIT",            /* 4 */
+  "OSM_SM_STATE_SWEEP_HEAVY_SELF",            /* 5 */
+  "OSM_SM_STATE_SWEEP_HEAVY_SUBNET",          /* 6 */
+  "OSM_SM_STATE_SET_SM_UCAST_LID",            /* 7 */
+  "OSM_SM_STATE_SET_SM_UCAST_LID_WAIT",       /* 8 */
+  "OSM_SM_STATE_SET_SM_UCAST_LID_DONE",       /* 9 */
+  "OSM_SM_STATE_SET_SUBNET_UCAST_LIDS",       /* 10 */
+  "OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_WAIT",     /* 11 */
+  "OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_DONE",     /* 12 */
+  "OSM_SM_STATE_SET_UCAST_TABLES",            /* 13 */
+  "OSM_SM_STATE_SET_UCAST_TABLES_WAIT",       /* 14 */
+  "OSM_SM_STATE_SET_UCAST_TABLES_DONE",       /* 15 */
+  "OSM_SM_STATE_SET_MCAST_TABLES",            /* 16 */
+  "OSM_SM_STATE_SET_MCAST_TABLES_WAIT",       /* 17 */
+  "OSM_SM_STATE_SET_MCAST_TABLES_DONE",       /* 18 */
+  "OSM_SM_STATE_SET_LINK_PORTS",                 /* 19 */
+  "OSM_SM_STATE_SET_LINK_PORTS_WAIT",               /* 20 */
+  "OSM_SM_STATE_SET_LINK_PORTS_DONE",               /* 21 */
+  "OSM_SM_STATE_SET_ARMED",                /* 19 */
+  "OSM_SM_STATE_SET_ARMED_WAIT",              /* 20 */
+  "OSM_SM_STATE_SET_ARMED_DONE",              /* 21 */
+  "OSM_SM_STATE_SET_ACTIVE",                  /* 22 */
+  "OSM_SM_STATE_SET_ACTIVE_WAIT",             /* 23 */
+  "OSM_SM_STATE_LOST_NEGOTIATION",            /* 24 */
+  "OSM_SM_STATE_STANDBY",                     /* 25 */
+  "OSM_SM_STATE_SUBNET_UP",                /* 26 */
+  "OSM_SM_STATE_PROCESS_REQUEST",             /* 27 */
+  "OSM_SM_STATE_PROCESS_REQUEST_WAIT",        /* 28 */
+  "OSM_SM_STATE_PROCESS_REQUEST_DONE",        /* 29 */
+  "OSM_SM_STATE_MASTER_OR_HIGHER_SM_DETECTED",  /* 30 */
+  "UNKNOWN STATE!!"                        /* 31 */
+};
+
+const char* const __osm_sm_signal_str[] =
+{
+  "OSM_SIGNAL_NONE",                       /* 0 */
+  "OSM_SIGNAL_SWEEP",                      /* 1 */
+  "OSM_SIGNAL_CHANGE_DETECTED",               /* 2 */
+  "OSM_SIGNAL_NO_PENDING_TRANSACTIONS",       /* 3 */
+  "OSM_SIGNAL_DONE",                       /* 4 */
+  "OSM_SIGNAL_DONE_PENDING",                  /* 5 */
+  "OSM_SIGNAL_LOST_SM_NEGOTIATION",           /* 6 */
+  "OSM_SIGNAL_LIGHT_SWEEP_FAIL",              /* 7 */
+  "OSM_SIGNAL_IDLE_TIME_PROCESS",             /* 8 */
+  "OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST",        /* 9 */
+  "OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED",  /* 10 */
+  "OSM_SIGNAL_EXIT_STBY",                /* 11 */
+  "UNKNOWN SIGNAL!!"                       /* 12 */
+};
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+osm_get_sm_state_str(
+  IN osm_sm_state_t state )
+{
+  if( state > OSM_SM_STATE_MAX )
+    state = OSM_SM_STATE_MAX;
+  return( __osm_sm_state_str[state] );
+}
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+osm_get_sm_signal_str(
+  IN osm_signal_t signal )
+{
+  if( signal > OSM_SIGNAL_MAX )
+    signal = OSM_SIGNAL_MAX;
+  return( __osm_sm_signal_str[signal] );
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static const char* const __osm_disp_msg_str[] =
+{
+  "OSM_MSG_REQ",
+  "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",
+  "UNKNOWN!!"
+};
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+osm_get_disp_msg_str(
+  IN cl_disp_msgid_t msg )
+{
+  if( msg > OSM_MSG_MAX )
+    msg = OSM_MSG_MAX;
+  return( __osm_disp_msg_str[msg] );
+}
+
+static const char* const __osm_port_state_str_fixed_width[] =
+{
+  "NOC",
+  "DWN",
+  "INI",
+  "ARM",
+  "ACT",
+  "???"
+};
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+osm_get_port_state_str_fixed_width(
+  IN uint8_t port_state )
+{
+  if( port_state > IB_LINK_ACTIVE )
+    port_state = IB_LINK_ACTIVE + 1;
+  return( __osm_port_state_str_fixed_width[port_state] );
+}
+
+static const char* const __osm_node_type_str_fixed_width[] =
+{
+  "??",
+  "CA",
+  "SW",
+  "RT",
+};
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+osm_get_node_type_str_fixed_width(
+  IN uint32_t node_type )
+{
+  if( node_type >= IB_NOTICE_NODE_TYPE_ROUTER )
+    node_type = 0;
+  return( __osm_node_type_str_fixed_width[node_type] );
+}
+
+#define OSM_VENDOR_ID_INTEL         0x00D0B7
+#define OSM_VENDOR_ID_MELLANOX      0x0002C9
+#define OSM_VENDOR_ID_REDSWITCH     0x000617
+#define OSM_VENDOR_ID_SILVERSTORM     0x00066A
+#define OSM_VENDOR_ID_TOPSPIN    0x0005AD
+#define OSM_VENDOR_ID_FUJITSU    0x00E000
+#define OSM_VENDOR_ID_FUJITSU2      0x000B5D
+#define OSM_VENDOR_ID_VOLTAIRE   0x0008F1
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+osm_get_manufacturer_str(
+  IN uint64_t              const guid_ho )
+{
+  static const char* intel_str         = "Intel      ";
+  static const char* mellanox_str         = "Mellanox   ";
+  static const char* redswitch_str     = "Redswitch  ";
+  static const char* silverstorm_str     = "SilverStorm  ";
+  static const char* topspin_str       = "Topspin    ";
+  static const char* fujitsu_str       = "Fujitsu    ";
+  static const char* voltaire_str      = "Voltaire   ";
+  static const char* unknown_str       = "Unknown    ";
+
+  switch( (uint32_t)(guid_ho >> (5 * 8)) )
+  {
+  case OSM_VENDOR_ID_INTEL:
+    return( intel_str );
+  case OSM_VENDOR_ID_MELLANOX:
+    return( mellanox_str );
+  case OSM_VENDOR_ID_REDSWITCH:
+    return( redswitch_str );
+  case OSM_VENDOR_ID_SILVERSTORM:
+    return( silverstorm_str );
+  case OSM_VENDOR_ID_TOPSPIN:
+    return( topspin_str );
+  case OSM_VENDOR_ID_FUJITSU:
+  case OSM_VENDOR_ID_FUJITSU2:
+    return( fujitsu_str );
+  case OSM_VENDOR_ID_VOLTAIRE:
+    return( voltaire_str );
+  default:
+    return( unknown_str );
+  }
+}
+
+static const char* const __osm_mtu_str_fixed_width[] =
+{
+  "??? ",
+  "256 ",
+  "512 ",
+  "1024",
+  "2048",
+  "4096"
+};
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+osm_get_mtu_str(
+  IN uint8_t               const mtu )
+{
+  if( mtu > IB_MTU_LEN_4096 )
+    return( __osm_mtu_str_fixed_width[0] );
+  else
+    return( __osm_mtu_str_fixed_width[mtu] );
+}
+
+static const char* const __osm_lwa_str_fixed_width[] =
+{
+  "???",
+  "1x ",
+  "4x ",
+  "???",
+  "???",
+  "???",
+  "???",
+  "???",
+  "12x"
+};
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+osm_get_lwa_str(
+  IN uint8_t               const lwa )
+{
+  if( lwa > 8 )
+    return( __osm_lwa_str_fixed_width[0] );
+  else
+    return( __osm_lwa_str_fixed_width[lwa] );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static const char* const __osm_lsa_str_fixed_width[] =
+{
+  "???",
+  "2.5",
+  "5  ",
+  "???",
+  "10 "
+};
+
+const char*
+osm_get_lsa_str(
+  IN uint8_t               const lsa )
+{
+  if( lsa > 4 )
+    return( __osm_lsa_str_fixed_width[0] );
+  else
+    return( __osm_lsa_str_fixed_width[lsa] );
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+const char* const __osm_sm_mgr_signal_str[] =
+{
+  "OSM_SM_SIGNAL_INIT",                 /* 0 */
+  "OSM_SM_SIGNAL_DISCOVERY_COMPLETED",   /* 2 */
+  "OSM_SM_SIGNAL_POLLING_TIMEOUT",       /* 3 */
+  "OSM_SM_SIGNAL_DISCOVER",              /* 4 */
+  "OSM_SM_SIGNAL_DISABLE",               /* 5 */
+  "OSM_SM_SIGNAL_HANDOVER",              /* 6 */
+  "OSM_SM_SIGNAL_HANDOVER_SENT",         /* 7 */
+  "OSM_SM_SIGNAL_ACKNOWLEDGE",           /* 8 */
+  "OSM_SM_SIGNAL_STANDBY",               /* 9 */
+  "OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED",        /* 10 */
+  "OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED_DONE",    /* 11 */
+  "OSM_SM_SIGNAL_WAIT_FOR_HANDOVER",     /* 12 */
+  "UNKNOWN STATE!!"                      /* 13 */
+
+};
+
+/**********************************************************************
+ **********************************************************************/
+const char*
+osm_get_sm_mgr_signal_str(
+  IN osm_sm_signal_t signal )
+{
+  if( signal > OSM_SM_SIGNAL_MAX )
+    signal = OSM_SM_SIGNAL_MAX;
+  return( __osm_sm_mgr_signal_str[signal] );
+}
+
+const char* const __osm_sm_mgr_state_str[] =
+{
+  "IB_SMINFO_STATE_NOTACTIVE",                /* 0 */
+  "IB_SMINFO_STATE_DISCOVERING",              /* 1 */
+  "IB_SMINFO_STATE_STANDBY",                     /* 2 */
+  "IB_SMINFO_STATE_MASTER",                   /* 3 */
+  "IB_SMINFO_STATE_INIT",                     /* 4 */
+  "UNKNOWN STATE!!"                              /* 5 */
+
+};
+
+const char*
+osm_get_sm_mgr_state_str(
+  IN uint16_t state )
+{
+  if( state > IB_SMINFO_STATE_INIT )
+    state = IB_SMINFO_STATE_INIT + 1;
+  return( __osm_sm_mgr_state_str[state] );
+}
+
diff --git a/trunk/ulp/opensm/user/libopensm/osm_log.c b/trunk/ulp/opensm/user/libopensm/osm_log.c
new file mode 100644 (file)
index 0000000..113d967
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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>
+
+#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"
+};
+#endif /* ndef WIN32 */
+
+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 )
+  {
+    /* this is a call to the syslog */
+    va_start( args, p_str );
+    vsprintf( buffer, p_str, args );
+    va_end(args);
+    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 );
+    }
+
+    /* send it also to the log file */
+#ifdef WIN32
+    GetLocalTime(&st);
+    fprintf( p_log->out_port, "[%02d:%02d:%02d:%03d][%04X] -> %s",
+                     st.wHour, st.wMinute, st.wSecond, st.wMilliseconds,
+                     pid, buffer);
+#else
+    fprintf( p_log->out_port, "%s %02d %02d:%02d:%02d %06d [%04X] -> %s\n",
+             (result.tm_mon < 12 ? month_str[result.tm_mon] : "???"),
+             result.tm_mday, result.tm_hour,
+             result.tm_min, result.tm_sec,
+             usecs, pid, buffer);
+    fflush( p_log->out_port );
+#endif    
+  }
+
+
+  /* SYS messages go to the log anyways */
+  if (p_log->level & verbosity)
+  {
+#ifdef _MEM_DEBUG_MODE_
+    /* If we are running in MEM_DEBUG_MODE then 
+       the cl_mem_check will be called on every run */
+    if (cl_mem_check() == FALSE) 
+    {
+      fprintf( p_log->out_port, "*** MEMORY ERROR!!! ***\n" );
+      CL_ASSERT(0);
+    }
+#endif
+    
+    va_start( args, p_str );
+    vsprintf( buffer, p_str, args );
+    va_end(args);
+    
+    /* regular log to default out_port */
+    cl_spinlock_acquire( &p_log->lock );
+#ifdef WIN32
+    GetLocalTime(&st);
+    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();
+    tim = time(NULL);
+    ret = fprintf( p_log->out_port, "%s %02d %02d:%02d:%02d %06d [%04X] -> %s",
+                   ((result.tm_mon < 12) && (result.tm_mon >= 0) ? 
+                    month_str[result.tm_mon] : "???"),
+                   result.tm_mday, result.tm_hour,
+                   result.tm_min, result.tm_sec,
+                   usecs, pid, buffer);
+
+#endif /*  WIN32 */
+    
+    /*
+      Flush log on errors too.
+    */
+    if( p_log->flush || (verbosity & OSM_LOG_ERROR) )
+      fflush( p_log->out_port );
+    
+    cl_spinlock_release( &p_log->lock );
+    
+    if (ret < 0)
+    {
+      fprintf(stderr, "OSM LOG FAILURE! Probably quota exceeded\n");
+      exit(1);
+    }
+  }
+}
+
+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_ ) */
+}
diff --git a/trunk/ulp/opensm/user/libopensm/osm_mad_pool.c b/trunk/ulp/opensm/user/libopensm/osm_mad_pool.c
new file mode 100644 (file)
index 0000000..a260ade
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <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 );
+
+  cl_memclr( p_pool, 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 );
+
+  /*
+    Frist, 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 );
+
+  /*
+    Frist, 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/trunk/ulp/opensm/user/libvendor/Makefile b/trunk/ulp/opensm/user/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/trunk/ulp/opensm/user/libvendor/SOURCES b/trunk/ulp/opensm/user/libvendor/SOURCES
new file mode 100644 (file)
index 0000000..d128cdf
--- /dev/null
@@ -0,0 +1,61 @@
+!if $(FREEBUILD)
+TARGETNAME=osmv_ibal
+!else
+TARGETNAME=osmv_ibald
+!endif
+TARGETTYPE=LIBRARY
+
+!if !defined(WINIBHOME)
+WINIBHOME=..\..\..\..
+!endif
+
+LIBPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)
+
+!if defined(OSM_TARGET)
+TARGETPATH=$(OSM_TARGET)\bin\user\obj$(BUILD_ALT_DIR)
+!else
+TARGETPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)
+!endif
+
+USE_NTDLL=1
+OVR_DIR=..\addon
+
+
+SOURCES=\
+       osm_vendor_al.c \
+       osm_vendor_mlx_sa.c \
+   winosm_common.c
+
+OSM_HOME=..
+
+TARGETLIBS=\
+!if $(FREEBUILD)
+                       $(LIBPATH)\*\ibal.lib \
+                       $(LIBPATH)\*\complib.lib \
+                       $(CRT_LIB_PATH)\msvcrt.lib
+
+!else
+                       $(LIBPATH)\*\ibald.lib \
+                       $(LIBPATH)\*\complibd.lib \
+                       $(CRT_LIB_PATH)\msvcrt.lib
+!endif
+
+#DO NOT TOUCH the order of search path , until ib_types.h merging process will be done
+INCLUDES= \
+       $(OSM_HOME)\include; \
+       $(OSM_HOME); \
+       $(WINIBHOME)\inc; \
+       $(WINIBHOME)\inc\user;
+
+# Could be any special flag needed for this project 
+USER_C_FLAGS=$(USER_C_FLAGS) /Ze
+#Add preproccessor definitions
+C_DEFINES=$(C_DEFINES) -DWIN32 -D__WIN__ -D__i386__ -Dinline=__inline -DMT_LITTLE_ENDIAN -DOSM_VENDOR_INTF_AL
+!if !$(FREEBUILD)
+#C_DEFINES=$(C_DEFINES) -D_DEBUG -DDEBUG -DDBG
+C_DEFINES=$(C_DEFINES)
+!endif
+
+LINKER_FLAGS= $(LINKER_FLAGS)
+MSC_WARNING_LEVEL= /W3
+#MSC_OPTIMIZATION= /O0
diff --git a/trunk/ulp/opensm/user/libvendor/osm_vendor_al.c b/trunk/ulp/opensm/user/libvendor/osm_vendor_al.c
new file mode 100644 (file)
index 0000000..6ac713f
--- /dev/null
@@ -0,0 +1,1593 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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.8 $
+ */
+
+/*
+  Next available error code: 0x300
+*/
+#ifdef __WIN__
+/* Suppress all warning regarding casting void* to specific pointer object */
+#pragma warning(disable : 4305)
+#endif
+
+#include <vendor/osm_vendor_select.h>
+
+#ifdef OSM_VENDOR_INTF_AL
+
+#include <complib/cl_memory.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_thread.h>
+#include <complib/cl_math.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_mad_pool.h>
+#include <vendor/osm_vendor_api.h>
+
+/****s* OpenSM: Vendor AL/osm_al_bind_info_t
+ * NAME
+ *   osm_al_bind_info_t
+ *
+ * DESCRIPTION
+ *    Structure containing bind information.
+ *
+ * SYNOPSIS
+ */
+typedef struct _osm_al_bind_info
+{
+  osm_vendor_t                *p_vend;
+  void                        *client_context;
+  ib_qp_handle_t                 h_qp;
+  ib_mad_svc_handle_t               h_svc;
+  uint8_t                        port_num;
+  ib_pool_key_t                  pool_key;
+  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;
+  ib_av_handle_t                 h_dr_av;
+
+} osm_al_bind_info_t;
+/*
+ * FIELDS
+ * p_vend
+ *    Pointer to the vendor object.
+ *
+ * client_context
+ *    User's context passed during osm_bind
+ *
+ * h_qp
+ *    Handle the QP for this bind.
+ *
+ * h_qp_svc
+ *    Handle the QP mad service for this bind.
+ *
+ * port_num
+ *    Port number (within the HCA) of the bound port.
+ *
+ * pool_key
+ *    Pool key returned by all for this QP.
+ *
+ * h_dr_av
+ *    Address vector handle used for all directed route SMPs.
+ *
+ * SEE ALSO
+ *********/
+
+/**********************************************************************
+ **********************************************************************/
+inline static ib_api_status_t
+__osm_al_convert_wcs(
+  IN ib_wc_status_t        const wc_status )
+{
+  switch( wc_status )
+  {
+  case IB_WCS_SUCCESS:
+    return( IB_SUCCESS );
+
+  case IB_WCS_TIMEOUT_RETRY_ERR:
+    return( IB_TIMEOUT );
+
+  default:
+    return( IB_ERROR );
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void AL_API
+__osm_set_vend_wrap( IN  osm_al_bind_info_t* const p_bind,
+                     IN  ib_mad_element_t* const   p_elem,
+                     OUT osm_vend_wrap_t* p_vw)
+{
+    p_vw->h_bind = p_bind;
+    p_vw->size = p_elem->size;
+    p_vw->p_elem = p_elem;
+    p_vw->h_av = 0;
+    p_vw->p_resp_madw = NULL;
+
+}
+            
+
+static void AL_API
+__osm_al_ca_err_callback(
+  IN ib_async_event_rec_t *p_async_rec )
+{
+  osm_vendor_t *p_vend = (osm_vendor_t*)p_async_rec->context;
+  OSM_LOG_ENTER( p_vend->p_log, __osm_al_ca_err_callback );
+
+  osm_log( p_vend->p_log, OSM_LOG_ERROR,
+           "__osm_al_ca_err_callback: ERR 3B01: "
+           "Event on channel adapter (%s).\n",
+           ib_get_async_event_str( p_async_rec->code ) );
+
+  OSM_LOG_EXIT( p_vend->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void AL_API
+__osm_al_ca_destroy_callback(
+  IN void *context )
+{
+  osm_al_bind_info_t *p_bind = (osm_al_bind_info_t*)context;
+  osm_vendor_t *p_vend = p_bind->p_vend;
+  OSM_LOG_ENTER( p_vend->p_log, __osm_al_ca_destroy_callback );
+
+  osm_log( p_vend->p_log, OSM_LOG_INFO,
+           "__osm_al_ca_destroy_callback: "
+           "Closing local channel adapter.\n" );
+
+  OSM_LOG_EXIT( p_vend->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+static void AL_API
+__osm_al_err_callback(
+  IN ib_async_event_rec_t *p_async_rec )
+{
+  osm_al_bind_info_t *p_bind = (osm_al_bind_info_t*)p_async_rec->context;
+  osm_vendor_t *p_vend = p_bind->p_vend;
+  OSM_LOG_ENTER( p_vend->p_log, __osm_al_err_callback );
+
+  osm_log( p_vend->p_log, OSM_LOG_ERROR,
+           "__osm_al_err_callback: ERR 3B02: "
+           "Error on QP (%s).\n",
+           ib_get_async_event_str( p_async_rec->code ) );
+
+  OSM_LOG_EXIT( p_vend->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* 
+    Send_cb will handle  the following cases :
+    Element Status  |  Send Response (no reponse expected)      | Send Request (response expeceted)  
+    ================|===========================================|==========================================
+        ERROR       |   Free : AV , madw(send_err_cb)           | Free : AV , madw , resp_madw 
+        SUCCESS     |   Free : AV , madw                        | Free : AV , madw
+
+    Element Status  |  Receive Response (no reponse expected)    
+    ================|===========================================
+        ERROR       |   Free : AV , madw(send_err_cb) 
+        SUCCESS     |   Free : AV , madw, resp_madw (both through rcv_callback)                        
+   
+*/    
+static void AL_API
+__osm_al_send_callback(
+  IN const ib_mad_svc_handle_t h_mad_svc,
+  IN void *mad_svc_context,
+  IN ib_mad_element_t *p_elem )
+{
+  osm_al_bind_info_t* const p_bind = (osm_al_bind_info_t*)mad_svc_context;
+  osm_vendor_t* const p_vend = p_bind->p_vend;
+  osm_madw_t* const p_madw = (osm_madw_t*)p_elem->context1;
+  osm_vend_wrap_t* p_vw = osm_madw_get_vend_ptr( p_madw );
+  ib_mad_t *p_mad = ib_get_mad_buf( p_elem );
+  ib_av_attr_t         av_attr;
+  ib_pd_handle_t               h_pd;
+  ib_api_status_t status_elem,status;
+  osm_madw_t *p_new_madw;
+
+  OSM_LOG_ENTER( p_vend->p_log, __osm_al_send_callback );
+  UNUSED_PARAM(h_mad_svc);
+  CL_ASSERT( p_vw );
+  CL_ASSERT( p_vw->h_av );
+  /* since we use context1 , safely , and its the only place that remove the clean 
+    p_elem,p_madw , h_av no checks are required */
+  status_elem = __osm_al_convert_wcs(p_elem->status);
+  osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+           "__osm_al_send_callback: "
+           "Destroying av handle %p.\n", p_elem->h_av );
+  /* Check first if its a direct route handle , in this case skip */
+  if (p_elem->h_av != p_bind->h_dr_av) 
+  {
+      ib_destroy_av( p_elem->h_av );
+  }
+  /* Since the free order is first resp_madw then madw (PARENT) we should check
+   this case first */
+  if (p_elem->resp_expected)
+  {
+      p_madw->status = status_elem;
+      if ( status_elem != IB_SUCCESS )
+      {
+          /*
+              Return any wrappers to the pool that may have been
+              pre-emptively allocated to handle a receive.
+          */
+          osm_log(p_vend->p_log, OSM_LOG_ERROR,
+                  "__osm_al_send_callback: ERR 3333 "
+                  " Mad Completed with WQE Error : %s.\n",ib_get_wc_status_str(p_elem->status));
+          if( p_vw->p_resp_madw )
+          {
+              osm_mad_pool_put( p_bind->p_osm_pool, p_vw->p_resp_madw );
+              p_vw->p_resp_madw = NULL;
+          }
+
+          p_bind->send_err_callback( p_bind->client_context, p_madw );
+      }
+      else
+      {
+          /* We are in response flow of receive , need to apply the rcv_callback 
+                The rcv_callback will free the resp_madw , req_madw , p_elem of receive
+                and request */
+          osm_log(p_vend->p_log, OSM_LOG_DEBUG,
+                  "__osm_al_send_callback: "
+                  "The Mad is a response , thus handeled in __osm_al_send_callback\n");
+          p_new_madw = p_vw->p_resp_madw;
+          p_bind->rcv_callback( p_new_madw, p_bind->client_context,
+                                p_madw );
+
+      }
+  }
+  else
+  {
+      osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+           "__osm_al_send_callback: "
+           "Returning MAD to pool, TID = 0x%" PRIx64 ".\n",
+           cl_ntoh64( p_mad->trans_id ) );
+      osm_mad_pool_put( p_bind->p_osm_pool, p_madw );
+      if ( status_elem != IB_SUCCESS )
+          osm_log( p_vend->p_log, OSM_LOG_ERROR,
+           "__osm_al_send_callback: ERR 3b0b "
+           "request mad had failed.\n");
+      goto Exit;
+  }
+
+
+
+
+
+ Exit:
+  OSM_LOG_EXIT( p_vend->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+    Receive_cb will be applied in the following cases :
+    Element Status  |  Receive Response (no reponse expected)      | Receive Request (response expeceted)  
+    ================|==============================================|=======================================
+        ERROR       |  NOT APPLIED                                 | NOT_APPLIED
+        SUCCESS     |  Free :  Resp_madw , copy_req_madw           | Allocate new_madw (for response then in send_cb free)
+ */
+ static void AL_API
+__osm_al_rcv_callback(
+  IN const ib_mad_svc_handle_t h_mad_svc,
+  IN void *mad_svc_context,
+  IN ib_mad_element_t *p_elem )
+{
+  osm_al_bind_info_t* const p_bind = (osm_al_bind_info_t*)mad_svc_context;
+  osm_vendor_t* const p_vend = p_bind->p_vend;
+  osm_madw_t *p_old_madw,*p_copy_old_madw;
+  osm_madw_t *p_new_madw;
+  osm_vend_wrap_t* p_old_vw;
+  osm_vend_wrap_t* p_new_vw;
+  ib_mad_t *p_new_mad;
+  osm_mad_addr_t mad_addr;
+
+  OSM_LOG_ENTER( p_vend->p_log, __osm_al_rcv_callback );
+  UNUSED_PARAM(h_mad_svc);
+  CL_ASSERT( p_elem->context1 == NULL );
+  CL_ASSERT( p_elem->context2 == NULL );
+    /*
+  osm_log( p_vend->p_log, OSM_LOG_VERBOSE,
+             "__osm_al_rcv_callback:  "
+             "Handling Transaction : 0x%" PRIx64 " .\n",
+           cl_ntoh64(p_elem->p_mad_buf->trans_id));
+           */
+  p_new_mad = ib_get_mad_buf( p_elem );
+  /*
+    In preperation for initializing the new mad wrapper,
+    Initialize the mad_addr structure for the received wire MAD.
+  */
+  mad_addr.dest_lid = p_elem->remote_lid;
+  mad_addr.path_bits = p_elem->path_bits;
+
+  /* TO DO - figure out which #define to use for the 2.5 Gb rate... */
+  mad_addr.static_rate = 0;
+
+  if( p_new_mad->mgmt_class == IB_MCLASS_SUBN_LID ||
+      p_new_mad->mgmt_class == IB_MCLASS_SUBN_DIR )
+  {
+    mad_addr.addr_type.smi.source_lid = p_elem->remote_lid;
+  }
+  else
+  {
+    mad_addr.addr_type.gsi.remote_qp = p_elem->remote_qp;
+    mad_addr.addr_type.gsi.remote_qkey = p_elem->remote_qkey;
+    mad_addr.addr_type.gsi.pkey = p_elem->pkey_index;
+    mad_addr.addr_type.gsi.service_level = p_elem->remote_sl;
+    mad_addr.addr_type.gsi.global_route = FALSE;
+  }
+
+  /*
+    If this MAD is a response to a previous request,
+    then grab our pre-allocated MAD wrapper.
+    Otherwise, allocate a new MAD wrapper.
+    context1 - contains the request madw
+  */
+  if( ib_mad_is_response( p_new_mad ) )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+               "__osm_al_rcv_callback: "
+               "The Mad is a response , thus handeled in __osm_al_send_callback\n");
+    CL_ASSERT( p_elem->send_context1 != NULL );
+    CL_ASSERT( p_elem->send_context2 == NULL );
+
+    p_old_madw = (osm_madw_t*)p_elem->send_context1;
+    p_old_vw = osm_madw_get_vend_ptr( p_old_madw );
+    p_new_madw = p_old_vw->p_resp_madw;
+
+    CL_ASSERT( p_new_madw );
+    osm_madw_init( p_new_madw, p_bind, p_elem->size,
+                   &mad_addr );
+    osm_madw_set_mad( p_new_madw, p_new_mad );
+    p_new_vw = osm_madw_get_vend_ptr( p_new_madw );
+    __osm_set_vend_wrap(p_bind,p_elem,p_new_vw);
+    goto Exit;
+  }
+  else
+  {
+    osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+                 "__osm_al_rcv_callback: "
+                 "The Mad is a request , thus handeled in __osm_al_rcv_callback\n");
+    CL_ASSERT( p_elem->send_context1 == NULL );
+    CL_ASSERT( p_elem->send_context2 == NULL );
+
+    p_new_madw = osm_mad_pool_get_wrapper( p_bind->p_osm_pool,
+                                           p_bind, p_elem->size, p_new_mad, &mad_addr );
+    CL_ASSERT(p_new_madw);
+    p_new_vw = osm_madw_get_vend_ptr( p_new_madw );
+
+    __osm_set_vend_wrap(p_bind,p_elem,p_new_vw);
+    osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+             "__osm_al_rcv_callback: "
+             "Calling receive callback function %p.\n",
+             p_bind->rcv_callback );
+
+
+    p_bind->rcv_callback( p_new_madw, p_bind->client_context,
+                          ((osm_madw_t*)p_elem->send_context1) );
+  }
+
+
+  Exit:
+  OSM_LOG_EXIT( p_vend->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+  ib_api_status_t status;
+  OSM_LOG_ENTER( p_log, osm_vendor_init );
+
+  p_vend->p_log = p_log;
+
+  /*
+    Open our instance of AL.
+  */
+  status = ib_open_al( &p_vend->h_al );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,
+             "osm_vendor_init: ERR 3B03: "
+             "Error opening AL (%s).\n",
+             ib_get_err_str( status ) );
+
+    goto Exit;
+  }
+
+  p_vend->timeout = timeout;
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_vendor_t*
+osm_vendor_new(
+  IN osm_log_t* const p_log,
+  IN const uint32_t timeout )
+{
+  ib_api_status_t    status;
+  osm_vendor_t    *p_vend;
+
+  OSM_LOG_ENTER( p_log, osm_vendor_new );
+
+  p_vend = cl_zalloc( sizeof(*p_vend) );
+  if( p_vend == NULL )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,
+             "osm_vendor_new: ERR 3B04: "
+             "Unable to allocate vendor object.\n" );
+    goto Exit;
+  }
+
+  status = osm_vendor_init( p_vend, p_log, timeout );
+  if( status != IB_SUCCESS )
+  {
+    cl_free( p_vend );
+    p_vend = NULL;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( p_vend );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vendor_delete(
+  IN osm_vendor_t** const pp_vend )
+{
+  /* TO DO - fill this in */
+  ib_close_al( (*pp_vend)->h_al );
+  cl_free( *pp_vend );
+  *pp_vend = NULL;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_ca_info_init(
+  IN osm_vendor_t*        const p_vend,
+  IN osm_ca_info_t*  const   p_ca_info,
+  IN const ib_net64_t      ca_guid )
+{
+  ib_api_status_t status;
+
+  OSM_LOG_ENTER( p_vend->p_log, __osm_ca_info_init );
+
+  p_ca_info->guid = ca_guid;
+
+  if( osm_log_is_active( p_vend->p_log, OSM_LOG_VERBOSE ) )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_VERBOSE,
+             "__osm_ca_info_init: "
+             "Querying CA 0x%" PRIx64 ".\n",
+             cl_ntoh64( ca_guid ) );
+  }
+/* attr size by verbs definition is required to be (uint32_t *) under opensm is only being set as 1 */
+  status = ib_query_ca_by_guid( p_vend->h_al, ca_guid, NULL,
+                                &p_ca_info->attr_size );
+  if( (status != IB_INSUFFICIENT_MEMORY ) && (status != IB_SUCCESS ) )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,
+             "__osm_ca_info_init: ERR 3B05: "
+             "Unexpected status getting CA attributes (%s).\n",
+             ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  CL_ASSERT( p_ca_info->attr_size );
+
+  p_ca_info->p_attr = cl_malloc( p_ca_info->attr_size );
+  if( p_ca_info->p_attr == NULL )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,
+             "__osm_ca_info_init: ERR 3B06: "
+             "Unable to allocate attribute storage.\n" );
+    goto Exit;
+  }
+
+  status = ib_query_ca_by_guid( p_vend->h_al, ca_guid, p_ca_info->p_attr,
+                                (uint32_t*)&p_ca_info->attr_size );
+
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,
+             "__osm_ca_info_init: ERR 3B07: "
+             "Unexpected status getting CA attributes (%s).\n",
+             ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_vend->p_log );
+  return( status );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ca_info_destroy(
+  IN osm_vendor_t*        const p_vend,
+  IN osm_ca_info_t*     const p_ca_info )
+{
+  OSM_LOG_ENTER( p_vend->p_log, osm_ca_info_destroy );
+
+  if( p_ca_info->p_attr )
+    cl_free( p_ca_info->p_attr );
+
+  cl_free( p_ca_info );
+
+  OSM_LOG_EXIT( p_vend->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_ca_info_t*
+osm_ca_info_new(
+  IN osm_vendor_t*        const p_vend,
+  IN const ib_net64_t      ca_guid )
+{
+  ib_api_status_t status;
+  osm_ca_info_t *p_ca_info;
+
+  OSM_LOG_ENTER( p_vend->p_log, osm_ca_info_new );
+
+  CL_ASSERT( ca_guid );
+
+  p_ca_info = cl_zalloc( sizeof(*p_ca_info) );
+  if( p_ca_info == NULL )
+    goto Exit;
+
+  status = __osm_ca_info_init( p_vend, p_ca_info, ca_guid );
+  if( status != IB_SUCCESS )
+  {
+    osm_ca_info_destroy( p_vend, p_ca_info );
+    p_ca_info = NULL;
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_vend->p_log );
+  return( p_ca_info );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_vendor_get_ca_guids(
+  IN osm_vendor_t*        const p_vend,
+  IN ib_net64_t**       const p_guids,
+  IN size_t*           const p_num_guids )
+{
+  ib_api_status_t status;
+
+  OSM_LOG_ENTER( p_vend->p_log, __osm_vendor_get_ca_guids );
+
+  CL_ASSERT( p_guids );
+  CL_ASSERT( p_num_guids );
+
+  status = ib_get_ca_guids( p_vend->h_al, NULL, p_num_guids );
+  if( (status != IB_INSUFFICIENT_MEMORY ) && (status != IB_SUCCESS ) )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,
+             "__osm_vendor_get_ca_guids: ERR 3B08: "
+             "Unexpected status getting CA GUID array (%s).\n",
+             ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  if( *p_num_guids == 0 )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,
+             "__osm_vendor_get_ca_guids: ERR 3B09: "
+             "No available channel adapters.\n" );
+    status = IB_INSUFFICIENT_RESOURCES;
+    goto Exit;
+  }
+
+  *p_guids = cl_malloc( *p_num_guids * sizeof(**p_guids) );
+  if( *p_guids == NULL )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,
+             "__osm_vendor_get_ca_guids: ERR 3B10: "
+             "Unable to allocate CA GUID array.\n" );
+    goto Exit;
+  }
+
+  status = ib_get_ca_guids( p_vend->h_al, *p_guids, p_num_guids );
+  CL_ASSERT( *p_num_guids );
+
+  if( osm_log_is_active( p_vend->p_log, OSM_LOG_VERBOSE ) )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_VERBOSE,
+             "__osm_vendor_get_ca_guids: "
+             "Detected %u local channel adapters.\n", *p_num_guids );
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_vend->p_log );
+  return( status );
+}
+
+/****f* OpenSM: CA Info/osm_ca_info_get_pi_ptr
+ * NAME
+ * osm_ca_info_get_pi_ptr
+ *
+ * DESCRIPTION
+ * Returns a pointer to the port attribute of the specified port
+ * owned by this CA.
+ *
+ * SYNOPSIS
+ */
+static ib_port_attr_t*
+__osm_ca_info_get_port_attr_ptr(
+  IN const osm_ca_info_t* const p_ca_info,
+  IN const uint8_t index )
+{
+  return( &p_ca_info->p_attr->p_port_attr[index] );
+}
+/*
+ * PARAMETERS
+ * p_ca_info
+ *    [in] Pointer to a CA Info object.
+ *
+ * index
+ *    [in] Port "index" for which to retrieve the port attribute.
+ *    The index is the offset into the ca's internal array
+ *    of port attributes.
+ *
+ * RETURN VALUE
+ * Returns a pointer to the port attribute of the specified port
+ * owned by this CA.
+ * Also allocate p_vend->p_ca_info if not allocated and init it .
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+  ib_api_status_t status;
+
+  uint32_t ca;
+  size_t ca_count;
+  uint32_t port_count = 0;
+  uint8_t port_num;
+  uint32_t total_ports = 0;
+  ib_net64_t *p_ca_guid = NULL;
+  osm_ca_info_t *p_ca_info;
+
+  OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get_all_port_attr );
+
+  CL_ASSERT( p_vend );
+  /*
+    1) Determine the number of CA's
+    2) If not allready allocated - allocate an array big enough to hold the
+         ca info object , the ca info will be overwrite to contain the new ca info
+    3) Call again to retrieve the guids.
+  */
+  status = __osm_vendor_get_ca_guids( p_vend, &p_ca_guid, &ca_count );
+
+  if (p_vend->p_ca_info == NULL) 
+  {
+      p_vend->p_ca_info = cl_zalloc( ca_count * sizeof(*(p_vend->p_ca_info)) );
+      
+      if( p_vend->p_ca_info == NULL )
+      {
+        osm_log( p_vend->p_log, OSM_LOG_ERROR,
+                 "osm_vendor_get_all_port_attr: ERR 3B11: "
+                 "Unable to allocate CA information array.\n" );
+        goto Exit;
+      }
+  }
+
+  p_vend->ca_count = ca_count;
+
+  /*
+    For each CA, retrieve the port info attributes
+  */
+  for( ca = 0; ca < ca_count; ca++ )
+  {
+    p_ca_info = &p_vend->p_ca_info[ca];
+
+    status = __osm_ca_info_init(
+      p_vend,
+      p_ca_info,
+      p_ca_guid[ca] );
+
+    if( status != IB_SUCCESS )
+    {
+      osm_log( p_vend->p_log, OSM_LOG_ERROR,
+               "osm_vendor_get_all_port_attr: ERR 3B12: "
+               "Unable to initialize CA Info object (%s).\n",
+               ib_get_err_str( status ) );
+    }
+
+    total_ports += osm_ca_info_get_num_ports( p_ca_info );
+  }
+
+  /*
+    If the user supplied enough storage, return the port guids,
+    otherwise, return the appropriate error.
+  */
+  if( *p_num_ports >= total_ports )
+  {
+    for( ca = 0; ca < ca_count; ca++ )
+    {
+      uint32_t num_ports;
+
+      p_ca_info = &p_vend->p_ca_info[ca];
+
+      num_ports = osm_ca_info_get_num_ports( p_ca_info );
+
+      for( port_num = 0; port_num < num_ports; port_num++ )
+      {
+        p_attr_array[port_count] = *__osm_ca_info_get_port_attr_ptr(
+          p_ca_info, port_num );
+        port_count++;
+      }
+    }
+  }
+  else
+  {
+    status = IB_INSUFFICIENT_MEMORY;
+  }
+
+
+  *p_num_ports = total_ports;
+
+
+ Exit:
+  if( p_ca_guid )
+    cl_free( p_ca_guid );
+
+  OSM_LOG_EXIT( p_vend->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_net64_t
+osm_vendor_get_ca_guid(
+  IN osm_vendor_t* const p_vend,
+  IN const ib_net64_t port_guid )
+{
+  uint8_t index;
+  uint8_t num_ports;
+  uint32_t num_guids = 0;
+  osm_ca_info_t *p_ca_info;
+  uint32_t ca;
+
+  OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get_ca_guid );
+
+  CL_ASSERT( port_guid );
+  /*
+    First, locate the HCA that owns this port.
+  */
+  if( p_vend->p_ca_info == NULL )
+  {
+    /*
+      Initialize the osm_ca_info_t array which allows
+      us to match port GUID to CA.
+    */
+    osm_vendor_get_all_port_attr( p_vend, NULL, &num_guids );
+  }
+
+  CL_ASSERT( p_vend->p_ca_info );
+  CL_ASSERT( p_vend->ca_count );
+
+  for( ca = 0; ca < p_vend->ca_count; ca++ )
+  {
+    p_ca_info = &p_vend->p_ca_info[ca];
+
+    num_ports = osm_ca_info_get_num_ports( p_ca_info );
+    CL_ASSERT( num_ports );
+
+    for( index = 0; index < num_ports; index++ )
+    {
+      if( port_guid ==
+          osm_ca_info_get_port_guid( p_ca_info, index ) )
+      {
+        OSM_LOG_EXIT( p_vend->p_log );
+        return( osm_ca_info_get_ca_guid( p_ca_info ) );
+      }
+    }
+  }
+
+  /*
+    No local CA owns this guid!
+  */
+  osm_log( p_vend->p_log, OSM_LOG_ERROR,
+           "osm_vendor_get_ca_guid: ERR 3B13: "
+           "Unable to determine CA guid.\n" );
+
+  OSM_LOG_EXIT( p_vend->p_log );
+  return( 0 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+uint8_t
+osm_vendor_get_port_num(
+  IN osm_vendor_t* const p_vend,
+  IN const ib_net64_t port_guid )
+{
+  uint8_t index;
+  uint8_t num_ports;
+  uint32_t num_guids = 0;
+  osm_ca_info_t *p_ca_info;
+  uint32_t ca;
+
+  OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get_port_num );
+
+  CL_ASSERT( port_guid );
+  /*
+    First, locate the HCA that owns this port.
+  */
+  if( p_vend->p_ca_info == NULL )
+  {
+    /*
+      Initialize the osm_ca_info_t array which allows
+      us to match port GUID to CA.
+    */
+    osm_vendor_get_all_port_attr( p_vend, NULL, &num_guids );
+  }
+
+  CL_ASSERT( p_vend->p_ca_info );
+  CL_ASSERT( p_vend->ca_count );
+
+  for( ca = 0; ca < p_vend->ca_count; ca++ )
+  {
+    p_ca_info = &p_vend->p_ca_info[ca];
+
+    num_ports = osm_ca_info_get_num_ports( p_ca_info );
+    CL_ASSERT( num_ports );
+
+    for( index = 0; index < num_ports; index++ )
+    {
+      if( port_guid ==
+          osm_ca_info_get_port_guid( p_ca_info, index ) )
+      {
+        OSM_LOG_EXIT( p_vend->p_log );
+        return( osm_ca_info_get_port_num( p_ca_info, index ) );
+      }
+    }
+  }
+  /*
+    No local CA owns this guid!
+  */
+  osm_log( p_vend->p_log, OSM_LOG_ERROR,
+           "osm_vendor_get_port_num: ERR 3B30: "
+           "Unable to determine CA guid.\n" );
+
+  OSM_LOG_EXIT( p_vend->p_log );
+  return( 0 );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_vendor_open_ca(
+  IN osm_vendor_t* const p_vend,
+  IN const ib_net64_t port_guid )
+{
+  ib_net64_t ca_guid;
+  ib_api_status_t status;
+
+  OSM_LOG_ENTER( p_vend->p_log, __osm_vendor_open_ca );
+
+  ca_guid = osm_vendor_get_ca_guid( p_vend, port_guid );
+  if( ca_guid == 0 )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,
+             "__osm_vendor_open_ca: ERR 3B31: "
+             "Bad port GUID value 0x%" PRIx64 ".\n",
+             cl_ntoh64( port_guid ) );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  osm_log( p_vend->p_log, OSM_LOG_VERBOSE,
+           "__osm_vendor_open_ca: "
+           "Opening HCA 0x%" PRIx64 ".\n",   cl_ntoh64( ca_guid ) );
+
+  status = ib_open_ca( p_vend->h_al,
+                       ca_guid,
+                       __osm_al_ca_err_callback,
+                       p_vend,
+                       &p_vend->h_ca );
+
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,
+             "__osm_vendor_open_ca: ERR 3B15: "
+             "Unable to open CA (%s).\n",
+             ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  CL_ASSERT( p_vend->h_ca );
+
+  status = ib_alloc_pd(
+    p_vend->h_ca,
+    IB_PDT_ALIAS,
+    p_vend,
+    &p_vend->h_pd );
+
+  if( status != IB_SUCCESS )
+  {
+    ib_close_ca( p_vend->h_ca,__osm_al_ca_destroy_callback  );
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,
+             "__osm_vendor_open_ca: ERR 3B16: "
+             "Unable to allocate protection domain (%s).\n",
+             ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  CL_ASSERT( p_vend->h_pd );
+
+ Exit:
+  OSM_LOG_EXIT( p_vend->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_vendor_init_av(
+  IN const osm_al_bind_info_t* p_bind,
+  IN ib_av_attr_t* p_av )
+{
+  cl_memclr( p_av, sizeof(*p_av) );
+  p_av->port_num = p_bind->port_num;
+  p_av->dlid = IB_LID_PERMISSIVE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_bind_handle_t
+osm_vendor_bind(
+  IN osm_vendor_t* const p_vend,
+  IN osm_bind_info_t* const p_user_bind,
+  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 )
+{
+  ib_net64_t port_guid;
+  osm_al_bind_info_t *p_bind = 0;
+  ib_api_status_t status;
+  ib_qp_create_t qp_create;
+  ib_mad_svc_t mad_svc;
+  ib_av_attr_t av;
+  DWORD get_last_error;
+  HANDLE handle;
+  char mutex_name[100];
+
+  OSM_LOG_ENTER( p_vend->p_log, osm_vendor_bind );
+
+  CL_ASSERT( p_user_bind );
+  CL_ASSERT( p_mad_pool );
+  CL_ASSERT( mad_recv_callback );
+  CL_ASSERT( send_err_callback );
+
+  port_guid = p_user_bind->port_guid;
+  osm_log( p_vend->p_log, OSM_LOG_INFO,
+           "osm_vendor_bind: "
+           "Binding to port 0x%" PRIx64 ".\n",
+           cl_ntoh64( port_guid ) );
+
+  if( p_vend->h_ca == 0 )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+             "osm_vendor_bind: "
+             "Opening CA that owns port 0x%" PRIx64 ".\n", cl_ntoh64( port_guid ));
+
+    status = __osm_vendor_open_ca( p_vend, port_guid );
+    if( status != IB_SUCCESS )
+    {
+      osm_log( p_vend->p_log, OSM_LOG_ERROR,
+               "osm_vendor_bind: ERR 3B17: "
+               "Unable to Open CA (%s).\n",
+               ib_get_err_str( status ) );
+      goto Exit;
+    }
+  }
+
+  p_bind = cl_zalloc( sizeof(*p_bind) );
+  if( p_bind == NULL )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,
+             "osm_vendor_bind: ERR 3B18: "
+             "Unable to allocate internal bind object.\n" );
+    goto Exit;
+  }
+
+  p_bind->p_vend = p_vend;
+  p_bind->client_context = context;
+  p_bind->port_num = osm_vendor_get_port_num( p_vend, port_guid );
+  p_bind->rcv_callback = mad_recv_callback;
+  p_bind->send_err_callback = send_err_callback;
+  p_bind->p_osm_pool = p_mad_pool;
+
+  CL_ASSERT( p_bind->port_num );
+
+  /* Patch to handle mutiple instances of vendor calls */
+
+  switch( p_user_bind->mad_class )
+  {
+  case IB_MCLASS_SUBN_LID:
+  case IB_MCLASS_SUBN_DIR:
+    sprintf(mutex_name,"Global\\osm_vendor_sm_%d",p_bind->port_num);
+    break;
+
+  case IB_MCLASS_SUBN_ADM:
+  default:
+    sprintf(mutex_name,"Global\\osm_vendor_sa_%d",p_bind->port_num);
+    break;
+  }
+
+  
+  handle = CreateMutex( NULL, TRUE, mutex_name);
+
+  if(handle == NULL) 
+  {
+      osm_log( p_vend->p_log, OSM_LOG_ERROR,
+               "osm_vendor_bind: ERR 3B32: "
+               "Can't create Mutex\n");
+      cl_free(p_bind);
+      p_bind = NULL;
+      /* Bug in IBAL in exit flow , thus force exit , cleanup is not done , OS responsibility*/
+      exit(1);
+  }
+  get_last_error = GetLastError();
+
+  if (get_last_error == ERROR_ALREADY_EXISTS) 
+  {
+      osm_log( p_vend->p_log, OSM_LOG_ERROR,
+               "osm_vendor_bind: ERR 3B35: "
+               "Current Mutex already exist : %s\n",mutex_name);
+      printf("ERROR : Port %d already binded.\n",p_bind->port_num);
+      cl_free(p_bind);
+      p_bind = NULL;
+      /* Bug in IBAL in exit flow , thus force exit , cleanup is not done , OS responsibility*/
+      exit(1);
+  }
+  /* End Of Patch */
+
+  /*
+    Get the proper QP.
+  */
+  cl_memclr( &qp_create, sizeof(qp_create) );
+
+  switch( p_user_bind->mad_class )
+  {
+  case IB_MCLASS_SUBN_LID:
+  case IB_MCLASS_SUBN_DIR:
+    qp_create.qp_type = IB_QPT_QP0_ALIAS;
+    break;
+
+  case IB_MCLASS_SUBN_ADM:
+  default:
+    qp_create.qp_type = IB_QPT_QP1_ALIAS;
+    break;
+  }
+
+  qp_create.sq_depth = p_user_bind->send_q_size;
+  qp_create.rq_depth = p_user_bind->recv_q_size;
+  qp_create.sq_sge = OSM_AL_SQ_SGE;
+  qp_create.rq_sge = OSM_AL_RQ_SGE;
+  status = ib_get_spl_qp(
+    p_vend->h_pd,
+    port_guid,
+    &qp_create,
+    p_bind,
+    __osm_al_err_callback,
+    &p_bind->pool_key,
+    &p_bind->h_qp );
+
+  if( status != IB_SUCCESS )
+  {
+    cl_free( p_bind );
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,
+             "osm_vendor_bind: ERR 3B19: "
+             "Unable to get QP handle (%s).\n",
+             ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  CL_ASSERT( p_bind->h_qp );
+  CL_ASSERT( p_bind->pool_key );
+
+  cl_memclr( &mad_svc, sizeof(mad_svc) );
+
+  mad_svc.mad_svc_context = p_bind;
+  mad_svc.pfn_mad_send_cb = __osm_al_send_callback; 
+  mad_svc.pfn_mad_recv_cb = __osm_al_rcv_callback;
+  mad_svc.mgmt_class = p_user_bind->mad_class;
+  mad_svc.mgmt_version = p_user_bind->class_version;
+  mad_svc.support_unsol = p_user_bind->is_responder;
+  mad_svc.method_array[IB_MAD_METHOD_GET] = TRUE;
+  mad_svc.method_array[IB_MAD_METHOD_SET] = TRUE;
+  mad_svc.method_array[IB_MAD_METHOD_DELETE] = TRUE;
+  mad_svc.method_array[IB_MAD_METHOD_TRAP] = TRUE;
+  mad_svc.method_array[IB_MAD_METHOD_GETTABLE] = TRUE;
+
+
+  status = ib_reg_mad_svc(
+    p_bind->h_qp,
+    &mad_svc,
+    &p_bind->h_svc );
+
+  if( status != IB_SUCCESS )
+  {
+    cl_free( p_bind );
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,
+             "osm_vendor_bind: ERR 3B21: "
+             "Unable to register QP0 MAD service (%s).\n",
+             ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  __osm_vendor_init_av( p_bind, &av );
+
+  status = ib_create_av( p_vend->h_pd, &av, &(p_bind->h_dr_av) );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,
+             "osm_vendor_bind: ERR 3B22: "
+             "Unable to create address vector (%s).\n",
+             ib_get_err_str( status ) );
+
+    goto Exit;
+  }
+
+  if( osm_log_is_active( p_vend->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+             "osm_vendor_bind: "
+             "Allocating av handle %p.\n", p_bind->h_dr_av );
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_vend->p_log );
+  return( (osm_bind_handle_t)p_bind );
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* osm_vendor_unbind is added due to OSM-1.8.0 gen2 merging
+    The functionality will be added when the Gen2 osm_vendor_unbind
+    will be implemented.
+*/    
+void
+osm_vendor_unbind(
+  IN osm_bind_handle_t h_bind)
+{
+       osm_al_bind_info_t *p_bind = ( osm_al_bind_info_t * ) h_bind;
+       osm_vendor_t *p_vend = p_bind->p_vend;
+
+
+       OSM_LOG_ENTER( p_vend->p_log, osm_vendor_unbind );
+
+       OSM_LOG_EXIT( p_vend->p_log);
+}
+
+/**********************************************************************
+ **********************************************************************/
+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_vw )
+{
+  ib_mad_t *p_mad;
+  osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;
+  osm_vendor_t *p_vend = p_bind->p_vend;
+  ib_api_status_t status;
+
+  OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get );
+
+  CL_ASSERT( p_vw );
+
+  p_vw->size = mad_size;
+  p_vw->h_bind = h_bind;
+
+  /*
+    Retrieve a MAD element from the pool and give the user direct
+    access to its buffer.
+  */
+  status = ib_get_mad( p_bind->pool_key, mad_size, &p_vw->p_elem );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,
+             "osm_vendor_get: ERR 3B25: "
+             "Unable to acquire MAD (%s).\n",
+             ib_get_err_str( status ) );
+
+    p_mad = NULL;
+    goto Exit;
+  }
+
+  CL_ASSERT( p_vw->p_elem );
+  p_mad = ib_get_mad_buf( p_vw->p_elem );
+
+  if( osm_log_get_level( p_vend->p_log ) >= OSM_LOG_DEBUG )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+             "osm_vendor_get: "
+             "Acquired MAD %p, size = %u.\n", p_mad, mad_size );
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_vend->p_log );
+  return( p_mad );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vendor_put(
+  IN osm_bind_handle_t h_bind,
+  IN osm_vend_wrap_t* const p_vw )
+{
+  osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;
+  osm_vendor_t *p_vend = p_bind->p_vend;
+  ib_api_status_t status;
+
+  OSM_LOG_ENTER( p_vend->p_log, osm_vendor_put );
+
+  CL_ASSERT( p_vw );
+  CL_ASSERT( p_vw->p_elem );
+  CL_ASSERT( p_vw->h_bind == h_bind );
+
+  if( osm_log_get_level( p_vend->p_log ) >= OSM_LOG_DEBUG )
+  {
+       
+    osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+             "osm_vendor_put: "
+             "Retiring MAD %p.\n", ib_get_mad_buf( p_vw->p_elem ) );
+  //            "Retiring MAD %p.\n", p_mad);
+  }
+
+  status = ib_put_mad( p_vw->p_elem );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,
+             "osm_vendor_put: ERR 3B26: "
+             "Unable to retire MAD (%s).\n",
+             ib_get_err_str( status ) );
+  }
+
+  OSM_LOG_EXIT( p_vend->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+  osm_al_bind_info_t* const p_bind = h_bind;
+  osm_vendor_t* const p_vend = p_bind->p_vend;
+  osm_vend_wrap_t* const p_vw = osm_madw_get_vend_ptr( p_madw );
+  osm_mad_addr_t* const p_mad_addr = osm_madw_get_mad_addr_ptr( p_madw );
+  ib_mad_t* const p_mad = osm_madw_get_mad_ptr( p_madw );
+  ib_api_status_t status;
+  ib_mad_element_t *p_elem;
+  ib_av_attr_t av;
+
+  OSM_LOG_ENTER( p_vend->p_log, osm_vendor_send );
+
+  CL_ASSERT( p_vw->h_bind == h_bind );
+  CL_ASSERT( p_vw->p_elem );
+
+  p_elem = p_vw->p_elem;
+
+  /*
+    If a response is expected to this MAD, then preallocate
+    a mad wrapper to contain the wire MAD received in the
+    response.  Allocating a wrapper here allows for easier
+    failure paths than after we already received the wire mad.
+    In order to seperate the receive callback and the send callback
+    dependency , we copy the request madw and send it as context2
+    Which in time in the receive callback will replace the req_madw 
+    to allow avoid races with send callback
+  */
+  if( resp_expected )
+  {
+    p_vw->p_resp_madw = osm_mad_pool_get_wrapper_raw(
+      p_bind->p_osm_pool );
+    if( p_vw->p_resp_madw == NULL  )
+    {
+      osm_log( p_vend->p_log, OSM_LOG_ERROR,
+               "osm_vendor_send: ERR 3B27: "
+               "Unable to allocate MAD wrapper.\n" );
+      status = IB_INSUFFICIENT_RESOURCES;
+      goto Exit;
+    }
+    
+  }
+  else
+    p_vw->p_resp_madw = NULL;
+
+  /*
+    For all sends other than directed route SM MADs,
+    acquire an address vector for the destination.
+  */
+  if( p_mad->mgmt_class != IB_MCLASS_SUBN_DIR )
+  {
+    cl_memclr( &av, sizeof(av) );
+    av.port_num = p_bind->port_num;
+    av.dlid = p_mad_addr->dest_lid;
+    av.static_rate = p_mad_addr->static_rate;
+    av.path_bits = p_mad_addr->path_bits;
+
+    if( (p_mad->mgmt_class != IB_MCLASS_SUBN_LID) &&
+        (p_mad->mgmt_class != IB_MCLASS_SUBN_DIR) )
+    {
+      av.sl = p_mad_addr->addr_type.gsi.service_level;
+
+
+      if(p_mad_addr->addr_type.gsi.global_route)
+      {
+        av.grh_valid = TRUE;
+        /* ANIL */
+        /* av.grh = p_mad_addr->addr_type.gsi.grh_info; */
+      }
+    }
+
+    if( osm_log_is_active( p_vend->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+               "osm_vendor_send: "
+               "av.port_num 0x%X, "
+               "av.dlid 0x%X, "
+               "av.static_rate   %d, "
+               "av.path_bits %d.\n",
+               av.port_num, cl_ntoh16(av.dlid),
+               av.static_rate, av.path_bits);
+    }
+
+    status = ib_create_av( p_vend->h_pd, &av, &(p_vw->h_av) );
+    if( status != IB_SUCCESS )
+    {
+      osm_log( p_vend->p_log, OSM_LOG_ERROR,
+               "osm_vendor_send: ERR 3B28: "
+               "Unable to create address vector (%s).\n",
+               ib_get_err_str( status ) );
+
+      if( p_vw->p_resp_madw )
+        osm_mad_pool_put( p_bind->p_osm_pool, p_vw->p_resp_madw );
+      /* Since we in immediate error the vendor layer is expected to handle the rollback , i.e free of madw */
+      if (p_madw) 
+        osm_mad_pool_put( p_bind->p_osm_pool, p_madw );
+      goto Exit;
+    }
+
+    if( osm_log_is_active( p_vend->p_log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+               "osm_vendor_send: "
+               "Allocating av handle %p.\n", p_vw->h_av );
+    }
+  }
+  else
+  {
+    p_vw->h_av = p_bind->h_dr_av;
+  }
+
+  p_elem->h_av = p_vw->h_av;
+
+  p_elem->context1 = p_madw;
+  p_elem->context2 = NULL;
+
+  p_elem->immediate_data = 0;
+  p_elem->p_grh = NULL;
+  p_elem->resp_expected = resp_expected;
+  p_elem->retry_cnt = OSM_DEFAULT_RETRY_COUNT;
+
+  p_elem->send_opt = IB_SEND_OPT_SIGNALED;
+  p_elem->timeout_ms = p_vend->timeout;
+
+  /* Completion information. */
+  p_elem->status = 0; /* Not trusting AL */
+
+
+  if( (p_mad->mgmt_class == IB_MCLASS_SUBN_LID) ||
+      (p_mad->mgmt_class == IB_MCLASS_SUBN_DIR) )
+  {
+    p_elem->remote_qp = 0;
+    p_elem->remote_qkey = 0;
+  }
+  else
+  {
+    p_elem->remote_qp = p_mad_addr->addr_type.gsi.remote_qp;
+    p_elem->remote_qkey = p_mad_addr->addr_type.gsi.remote_qkey;
+       osm_log(p_vend->p_log, OSM_LOG_DEBUG,
+            "osm_vendor_send: "
+            "remote qp = 0x%X, remote qkey = 0x%X.\n",
+            cl_ntoh32(p_elem->remote_qp),
+            cl_ntoh32(p_elem->remote_qkey) );
+  }
+
+  status = ib_send_mad( p_bind->h_svc, p_elem, NULL );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,
+             "osm_vendor_send: ERR 3B29: "
+             "Send failed , cleaning up (%s).\n",
+             ib_get_err_str( status ) );
+    /* When we destroy the av - we should take the pointer from local allocation since
+        we do not "trust" IBAL to keep track in p_elem */
+
+    if (p_vw->h_av && (p_vw->h_av != p_bind->h_dr_av) )
+    {
+        osm_log( p_vend->p_log, OSM_LOG_DEBUG,
+                   "__osm_al_send_callback: "
+                   "Destroying av handle %p.\n", p_vw->h_av );
+        ib_destroy_av( p_vw->h_av );
+    }
+    if( p_vw->p_resp_madw )
+      osm_mad_pool_put( p_bind->p_osm_pool, p_vw->p_resp_madw );
+    /* Since we in immediate error the vendor layer is expected to handle the rollback , i.e free of madw */
+    if (p_madw) 
+      osm_mad_pool_put( p_bind->p_osm_pool, p_madw );
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_vend->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_vendor_local_lid_change(
+  IN osm_bind_handle_t h_bind )
+{
+  osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;
+  osm_vendor_t *p_vend = p_bind->p_vend;
+  ib_av_attr_t av;
+  ib_api_status_t status;
+
+  OSM_LOG_ENTER( p_vend->p_log, osm_vendor_local_lid_change );
+
+  /*
+    The only thing we need to do is refresh the directed
+    route address vector.
+  */
+  __osm_vendor_init_av( p_bind, &av );
+
+  status = ib_destroy_av( p_bind->h_dr_av );
+  p_bind->h_dr_av = NULL;
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,
+             "osm_vendor_local_lid_change: ERR 3B32: "
+             "Unable to destroy address vector (%s).\n",
+             ib_get_err_str( status ) );
+
+    goto Exit;
+  }
+
+  status = ib_create_av( p_vend->h_pd, &av, &p_bind->h_dr_av );
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,
+             "osm_vendor_local_lid_change: ERR 3B33: "
+             "Unable to create address vector (%s).\n",
+             ib_get_err_str( status ) );
+
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_vend->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vendor_set_sm(
+  IN osm_bind_handle_t h_bind,
+  IN boolean_t         is_sm_val )
+{
+  osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;
+  osm_vendor_t *p_vend = p_bind->p_vend;
+  ib_api_status_t status;
+  ib_port_attr_mod_t attr_mod;
+
+  OSM_LOG_ENTER( p_vend->p_log, osm_vendor_set_sm );
+
+  cl_memclr( &attr_mod, sizeof(attr_mod) );
+
+  attr_mod.cap.sm = is_sm_val;
+
+  status = ib_modify_ca( p_vend->h_ca, p_bind->port_num,
+                         IB_CA_MOD_IS_SM, &attr_mod );
+
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_vend->p_log, OSM_LOG_ERROR,
+             "osm_vendor_set_sm: ERR 3B34: "
+             "Unable set 'IS_SM' bit to:%u in port attributes (%s).\n",
+             is_sm_val, ib_get_err_str( status ) );
+  }
+
+  OSM_LOG_EXIT( p_vend->p_log );
+}
+
+#endif   /* OSM_VENDOR_INTF_AL */
diff --git a/trunk/ulp/opensm/user/libvendor/osm_vendor_mlx_sa.c b/trunk/ulp/opensm/user/libvendor/osm_vendor_mlx_sa.c
new file mode 100644 (file)
index 0000000..f53685d
--- /dev/null
@@ -0,0 +1,854 @@
+/*
+ * 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$
+ */
+
+
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_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 mathods... */
+    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) cl_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.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) cl_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 *)cl_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)
+             );
+    cl_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);
+    }
+  }
+
+  cl_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 *)cl_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)
+  {
+    cl_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)
+  {
+    cl_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)
+             );
+    cl_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_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 defiend by RMPP
+ *
+ *  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 */
+  cl_memclr(p_sa_mad, 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 */
+    0                                  /* 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 )
+  {
+    cl_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 = cl_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);
+  }
+
+ 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;
+
+  /* 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.comp_mask = p_user_query->comp_mask;
+    sa_mad_data.p_attr = p_user_query->p_attr;
+    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;
+    cl_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" );
+    cl_memclr(&path_rec, 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" );
+    cl_memclr(&path_rec, 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;
+    cl_memcpy( &path_rec.dgid,
+               &( ( osmv_gid_pair_t * ) ( p_query_req->p_query_input ) )->
+               dest_gid, sizeof( ib_gid_t ) );
+    cl_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" );
+    cl_memclr(&path_rec, 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/trunk/ulp/opensm/user/libvendor/winosm_common.c b/trunk/ulp/opensm/user/libvendor/winosm_common.c
new file mode 100644 (file)
index 0000000..9523bea
--- /dev/null
@@ -0,0 +1,206 @@
+#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*
+GetOsmPath(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;
+}
+/****************************************************************************/
+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 */             
+                *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/trunk/ulp/opensm/user/opensm/Makefile b/trunk/ulp/opensm/user/opensm/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/trunk/ulp/opensm/user/opensm/SOURCES b/trunk/ulp/opensm/user/opensm/SOURCES
new file mode 100644 (file)
index 0000000..66a0bed
--- /dev/null
@@ -0,0 +1,153 @@
+!if $(FREEBUILD)
+TARGETNAME=opensm
+!else
+TARGETNAME=opensmd
+!endif
+
+
+!if !defined(WINIBHOME)
+WINIBHOME=..\..\..\..
+!endif
+
+LIBPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)
+
+!if defined(OSM_TARGET)
+TARGETPATH=$(OSM_TARGET)\bin\user\obj$(BUILD_ALT_DIR)
+!else
+TARGETPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)
+!endif
+
+TARGETTYPE=PROGRAM
+UMTYPE=console
+USE_CRTDLL=1
+
+SOURCES=\
+        opensm.rc \
+        osm_db_files.c \
+        osm_db_pack.c \
+        osm_drop_mgr.c \
+        osm_fwd_tbl.c \
+        osm_inform.c \
+        osm_lid_mgr.c \
+        osm_lin_fwd_rcv.c \
+        osm_lin_fwd_rcv_ctrl.c \
+        osm_lin_fwd_tbl.c \
+        osm_link_mgr.c \
+        osm_matrix.c \
+        osm_mcast_fwd_rcv.c \
+        osm_mcast_fwd_rcv_ctrl.c \
+        osm_mcast_mgr.c \
+        osm_mcast_tbl.c \
+        osm_mcm_info.c \
+        osm_mcm_port.c \
+        osm_mtree.c \
+        osm_multicast.c \
+        osm_node.c \
+        osm_node_desc_rcv.c \
+        osm_node_desc_rcv_ctrl.c \
+        osm_node_info_rcv.c \
+        osm_node_info_rcv_ctrl.c \
+        osm_opensm.c \
+        osm_pkey.c \
+        osm_pkey_rcv.c \
+        osm_pkey_rcv_ctrl.c \
+        osm_port.c \
+        osm_port_info_rcv.c \
+        osm_port_info_rcv_ctrl.c \
+        osm_remote_sm.c \
+        osm_req.c \
+        osm_req_ctrl.c \
+        osm_resp.c \
+        osm_sa.c \
+        osm_sa_class_port_info.c \
+        osm_sa_class_port_info_ctrl.c \
+        osm_sa_informinfo.c \
+        osm_sa_informinfo_ctrl.c \
+        osm_sa_lft_record.c \
+        osm_sa_lft_record_ctrl.c \
+        osm_sa_link_record.c \
+        osm_sa_link_record_ctrl.c \
+        osm_sa_mad_ctrl.c \
+        osm_sa_mcmember_record.c \
+        osm_sa_mcmember_record_ctrl.c \
+        osm_sa_node_record.c \
+        osm_sa_node_record_ctrl.c \
+        osm_sa_path_record.c \
+        osm_sa_path_record_ctrl.c \
+        osm_sa_pkey_record.c \
+        osm_sa_pkey_record_ctrl.c \
+        osm_sa_portinfo_record.c \
+        osm_sa_portinfo_record_ctrl.c \
+        osm_sa_response.c \
+        osm_sa_service_record.c \
+        osm_sa_service_record_ctrl.c \
+        osm_sa_slvl_record.c \
+        osm_sa_slvl_record_ctrl.c \
+        osm_sa_sminfo_record.c \
+        osm_sa_sminfo_record_ctrl.c \
+        osm_sa_vlarb_record.c \
+        osm_sa_vlarb_record_ctrl.c \
+        osm_service.c \
+        osm_slvl_map_rcv.c \
+        osm_slvl_map_rcv_ctrl.c \
+        osm_sm.c \
+        osm_sminfo_rcv.c \
+        osm_sminfo_rcv_ctrl.c \
+        osm_sm_mad_ctrl.c \
+        osm_sm_state_mgr.c \
+        osm_state_mgr.c \
+        osm_state_mgr_ctrl.c \
+        osm_subnet.c \
+        osm_sweep_fail_ctrl.c \
+        osm_sw_info_rcv.c \
+        osm_sw_info_rcv_ctrl.c \
+        osm_switch.c \
+        osm_trap_rcv.c \
+        osm_trap_rcv_ctrl.c \
+        osm_ucast_mgr.c \
+        osm_ucast_updn.c \
+        osm_vl15intf.c \
+        osm_vl_arb_rcv.c \
+        osm_vl_arb_rcv_ctrl.c \
+        st.c \
+        main.c \
+        cl_event_wheel.c \
+        cl_dispatcher.c
+
+OSM_HOME=..
+
+TARGETLIBS=\
+!if $(FREEBUILD)
+                       $(LIBPATH)\*\ibal.lib \
+                       $(LIBPATH)\*\complib.lib \
+                       $(TARGETPATH)\*\osmv_ibal.lib \
+                       $(TARGETPATH)\*\opensm_ibal.lib \
+                       $(CRT_LIB_PATH)\msvcrt.lib
+
+!else
+                       $(LIBPATH)\*\ibald.lib \
+                       $(LIBPATH)\*\complibd.lib \
+                       $(TARGETPATH)\*\osmv_ibald.lib \
+                       $(TARGETPATH)\*\opensm_ibald.lib \
+                       $(CRT_LIB_PATH)\msvcrt.lib
+!endif
+
+#DO NOT TOUCH the order of search path , until ib_types.h merging process will be done
+INCLUDES= \
+       $(OSM_HOME)\include; \
+       $(OSM_HOME); \
+       $(WINIBHOME)\inc; \
+       $(WINIBHOME)\inc\user;
+
+# Could be any special flag needed for this project 
+USER_C_FLAGS=$(USER_C_FLAGS) /MD
+#Add preproccessor definitions
+C_DEFINES=$(C_DEFINES) -DWIN32 -D__WIN__ -D__i386__ -Dinline=__inline -DMT_LITTLE_ENDIAN -DOSM_VENDOR_INTF_AL
+!if !$(FREEBUILD)
+#C_DEFINES=$(C_DEFINES) -D_DEBUG -DDEBUG -DDBG
+C_DEFINES=$(C_DEFINES) 
+!endif
+
+LINKER_FLAGS= $(LINKER_FLAGS)
+MSC_WARNING_LEVEL= /W3
+#MSC_OPTIMIZATION= /O0
diff --git a/trunk/ulp/opensm/user/opensm/cl_dispatcher.c b/trunk/ulp/opensm/user/opensm/cl_dispatcher.c
new file mode 100644 (file)
index 0000000..2e3242d
--- /dev/null
@@ -0,0 +1,409 @@
+/*
+ * 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$
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of Dispatcher abstraction.
+ *
+ * Environment:
+ *    All
+ *
+ * $Revision: 1.5 $
+ */
+
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/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 ) )
+    cl_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*)cl_zalloc( sizeof(cl_disp_reg_info_t) );
+  if( !p_reg )
+  {
+    cl_spinlock_release( &p_disp->lock );
+    return( NULL );
+  }
+
+  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 )
+    {
+      cl_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 */
+  cl_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/trunk/ulp/opensm/user/opensm/cl_event_wheel.c b/trunk/ulp/opensm/user/opensm/cl_event_wheel.c
new file mode 100644 (file)
index 0000000..e23d51c
--- /dev/null
@@ -0,0 +1,660 @@
+/*
+ * 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$
+ */
+
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <math.h>
+#include <complib/cl_debug.h>
+#include <opensm/cl_event_wheel.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 */
+      cl_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 : ERROR 1000: "
+               "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 : ERROR 1000: "
+             "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 : ERROR 1000: "
+             "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);
+    cl_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;
+  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 *)
+      cl_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. */
+    if ( timeout > (uint32_t)timeout )
+    {
+      osm_log (p_event_wheel->p_log, OSM_LOG_INFO,
+               "cl_event_wheel_reg: "
+               "timeout requested is too large. Using timeout: %u \n",
+               (uint32_t)timeout );
+    }
+
+    /* start the timer to the timeout [msec] */
+    cl_status = cl_timer_start(&p_event_wheel->timer, (uint32_t)timeout);
+
+    if (cl_status != CL_SUCCESS)
+    {
+      osm_log (p_event_wheel->p_log, OSM_LOG_ERROR,
+               "cl_event_wheel_reg : ERROR 1000: "
+               "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 */
+    cl_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( &log, TRUE, 0xff, NULL);
+  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/trunk/ulp/opensm/user/opensm/main.c b/trunk/ulp/opensm/user/opensm/main.c
new file mode 100644 (file)
index 0000000..a5b4651
--- /dev/null
@@ -0,0 +1,788 @@
+/*
+ * 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 3445 2005-09-15 08:35:44Z yael $
+ */
+
+
+/*
+ * 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_opensm.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_ucast_updn.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 subents by
+  instantiating more than one opensm object.
+*/
+osm_opensm_t osm;
+volatile int osm_exit_flag = 0;
+
+#define GUID_ARRAY_SIZE 64
+#define INVALID_GUID (0xFFFFFFFFFFFFFFFFULL)
+
+/**********************************************************************
+ **********************************************************************/
+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 trys 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" );
+  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( "-u\n"
+          "--updn\n"
+          "          This option activate UPDN algorithm instead of Min Hop\n"
+          "          algorithm (default).\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 at 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" );
+  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"
+          "          100 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"
+          "          one outstanding SMP.\n\n" );
+  printf( "-i <equalize-ignore-guids-file>\n"
+          "-ignore-guids <equalize-ignore-guids-file>\n"
+          "          This option provides means to define a set of ports\n"
+          "          (by guids) that will be ignored by the link load \n"
+          "          equalization algorithm.\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 /var/log/osm.log.\n"
+          "          For the log to go to standard output use -f stdout.\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 -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( "-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"
+          "          -d4  - Put OpenSM in memory tracking mode.\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 = 1;
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+  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_opensm_init (%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 */
+
+  /* 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" ,
+               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" ,
+               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 XXX: "
+               "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_pro_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 __cdecl
+main(
+  int                   argc,
+  char*                 argv[] )
+{
+  osm_subn_opt_t        opt;
+  ib_net64_t            guid = 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:d:g:l:s:t:vVhorc";
+
+  /*
+    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[] =
+    {
+      {  "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'},
+      {  "maxsmps",       1, NULL, 'n'},
+      {  "V",             0, NULL, 'V'},
+      {  "help",          0, NULL, 'h'},
+      {  "once",          0, NULL, 'o'},
+      {  "reassign_lids", 0, NULL, 'r'},
+      {  "priority",      1, NULL, 'p'},
+      {  "updn",          0, NULL, 'u'},
+      {  "add_guid_file", 1, NULL, 'a'},
+      {  "cache-options", 0, NULL, 'c'},
+      {  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 '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.
+      */
+      guid = cl_hton64( strtoull( optarg, NULL, 16 ));
+      if (! guid)
+      {
+        /* If guid is 0 - need to display the guid list */
+        guid = INVALID_GUID;
+      }
+      else
+        printf(" Guid <0x%"PRIx64">\n", cl_hton64( 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 '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: Force Signale 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;
+      }
+      else if(dbg_lvl == 4)
+      {
+        mem_track = TRUE;
+      }
+      else if(dbg_lvl >= 10)
+      {
+        /* Please look at 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 '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 'u':
+      opt.updn_activate = TRUE;
+      printf(" Activate UPDN algorithm\n");
+      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 'h':
+    case '?':
+    case ':':
+      show_usage();
+      break;
+
+    case -1:
+      break; /* done with option */
+    default: /* something wrong */
+      abort();
+    }
+  }
+  while(next_option != -1);
+
+  if (osm_exit_flag) {
+    return( 0 );
+  }
+  if (opt.log_file != NULL )
+    printf(" Log File: %s\n", opt.log_file );
+  /* Done with options description */
+  printf("-------------------------------------------------\n");
+
+  if (mem_track) __cl_mem_track(TRUE);
+
+  opt.log_flags = (uint8_t)log_flags;
+
+  if ( cache_options == TRUE )
+    osm_subn_write_conf_file( &opt );
+
+  status = osm_opensm_init( &osm, &opt );
+  if( status != IB_SUCCESS )
+  {
+    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);
+    /* We will just exit, and not go to Exit, since we don't
+       want the destroy to be called. */
+    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( guid == 0 || cl_hton64(guid) == cl_hton64(INVALID_GUID))
+    guid = get_port_guid( &osm, guid );
+
+  if ( guid == 0 )
+  {
+    printf( "Error: Could not get port guid \n" );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  status = osm_opensm_bind( &osm, 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 );
+  /* since osm_opensm_init get opt as RO we'll set the opt value with UI pfn here */
+  /* Now do the registration */
+  if (opt.updn_activate)
+    if (osm_updn_reg_calc_min_hop_table(osm.p_updn_ucast_routing, &(osm.subn.opt))) {
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  if( run_once_flag == TRUE )
+  {
+    status = osm_opensm_wait_for_subnet_up(
+      &osm, EVENT_NO_TIMEOUT, TRUE );
+    osm_exit_flag = 1;
+  }
+  else
+  {
+    /*
+      Sit here forever
+      In the future, some sort of console interactivity could
+      be implemented in this loop.
+    */
+    while( !osm_exit_flag )
+      cl_thread_suspend( 10000 );
+  }
+
+  /* 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:
+  osm_opensm_destroy( &osm );
+
+  if (mem_track) cl_mem_display();
+
+  exit( 0 );
+}
diff --git a/trunk/ulp/opensm/user/opensm/opensm.rc b/trunk/ulp/opensm/user/opensm/opensm.rc
new file mode 100644 (file)
index 0000000..588b227
--- /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$\r
+ */\r
+\r
+\r
+#include <ics_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 Application"\r
+#define VER_INTERNALNAME_STR        "opensm.exe"\r
+#define VER_ORIGINALFILENAME_STR    "opensm.exe"\r
+#else\r
+#define VER_FILEDESCRIPTION_STR     "OpenSM Subnet Manager Application"\r
+#define VER_INTERNALNAME_STR        "opensm.exe"\r
+#define VER_ORIGINALFILENAME_STR    "opensm.exe"\r
+#endif\r
+#include <common.ver>\r
diff --git a/trunk/ulp/opensm/user/opensm/osm_db_files.c b/trunk/ulp/opensm/user/opensm/osm_db_files.c
new file mode 100644 (file)
index 0000000..2d96469
--- /dev/null
@@ -0,0 +1,769 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/st.h>
+#include <opensm/osm_db.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdlib.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
+/**********/
+
+/****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 )
+{
+  cl_memclr(p_db, 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 );
+  cl_free( p_domain_imp->file_name );
+  cl_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 );
+    cl_free( p_domain );
+  }
+  cl_list_destroy( &p_db->domains );
+  cl_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 *)cl_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 == NULL )
+    p_db_imp->db_dir_name = OSM_DEFAULT_CACHE_DIR;
+
+  /* create the directory if it doesn't exist */
+  /* There is difference between creating in windows and in 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, also if it is a link */
+  if (lstat(p_db_imp->db_dir_name, &dstat))
+  {
+    if (mkdir(p_db_imp->db_dir_name, 777))
+    {
+      osm_log( p_log, OSM_LOG_ERROR,
+               "osm_db_init: ERR 6901: "
+               " Fail 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 *)cl_malloc(sizeof(osm_db_domain_t));
+  CL_ASSERT( p_domain != NULL );
+
+  p_domain_imp =
+    (osm_db_domain_imp_t *)cl_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 *)cl_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 6902: "
+             " Fail to open the db file:%s\n",
+             p_domain_imp->file_name);
+    cl_free(p_domain_imp);
+    cl_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 6903: "
+             " Fail 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 6904: "
+                   " Fail to get key from line:%u : %s\n",
+                   line_num, sLine);
+          status = 1;
+          goto EndParsing;
+        }
+
+        p_key = (char *)cl_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*)cl_malloc(sizeof(char)*(strlen(p_rest_of_line) + 1));
+          strcpy(p_accum_val, p_rest_of_line);
+        }
+        else
+        {
+          p_accum_val = (char*)cl_malloc(2);
+          strcpy(p_accum_val, "\0");
+        }
+      }
+      else if (sLine[0] != '\n')
+      {
+        osm_log( p_log, OSM_LOG_ERROR,
+                 "osm_db_restore: ERR 6905: "
+                 " How did we get here? line:%u : %s\n",
+                 line_num, sLine);
+        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 6906: "
+                   " 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 *)cl_malloc(strlen(p_prev_val) + strlen(sLine) + 1);
+        strcpy(p_accum_val, p_prev_val);
+        cl_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 );
+  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 *)cl_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 6907: "
+             " Fail 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 6909: "
+             " Fail 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 6908: "
+             " Fail to rename the db file to:%s (err:%u)\n",
+             p_domain_imp->file_name, status);
+  }
+ Exit:
+  cl_spinlock_release( &p_domain_imp->lock );
+  cl_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)
+{
+  cl_free((char*)key);
+  cl_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 = cl_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 = cl_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) cl_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
+    {
+      cl_free(p_key);
+      cl_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( &log, TRUE, 0xff, "/tmp/test_osm_db.log");
+
+  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/trunk/ulp/opensm/user/opensm/osm_db_pack.c b/trunk/ulp/opensm/user/opensm/osm_db_pack.c
new file mode 100644 (file)
index 0000000..9d6df77
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * 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$
+ */
+
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.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*)cl_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/trunk/ulp/opensm/user/opensm/osm_drop_mgr.c b/trunk/ulp/opensm/user/opensm/osm_drop_mgr.c
new file mode 100644 (file)
index 0000000..1e75ef5
--- /dev/null
@@ -0,0 +1,722 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <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_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_memclr( p_mgr, sizeof(*p_mgr) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_drop_mgr_destroy(
+  IN osm_drop_mgr_t* const p_mgr )
+{
+  OSM_LOG_ENTER( p_mgr->p_log, osm_drop_mgr_destroy );
+
+  CL_ASSERT( p_mgr );
+  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 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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;
+  char* p_node_desc;
+
+  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_lid_tbl = &p_mgr->p_subn->port_lid_tbl;
+  p_sm_guid_tbl = &p_mgr->p_subn->sm_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 = (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" );
+    
+    cl_free(p_sm);
+  }
+
+  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 );
+
+  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 loose 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 ther remote node is a ca - 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_CA )
+        {
+          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:%u.\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 %u.\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_desc */
+  p_node_desc = p_port->p_node ? (char*)(p_port->p_node->node_desc.description) : "UNKNOWN"; 
+  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(&notice, CL_HTON32(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;
+  cl_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;
+  }
+  osm_log( p_mgr->p_log, OSM_LOG_INFO, 
+           "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 );
+  
+ Exit:
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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
+  {
+    osm_switch_delete( &p_sw );
+  }
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_drop_mgr_remove_router(
+  IN const osm_drop_mgr_t* const p_mgr,
+  IN osm_node_t* p_node )
+{
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_drop_mgr_remove_router );
+
+  UNUSED_PARAM( p_mgr );
+  UNUSED_PARAM( p_node );
+
+  osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+           "__osm_drop_mgr_remove_router: ERR 0106: "
+           "Routers are not supported.\n" );
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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_node_guid_tbl = &p_mgr->p_subn->node_guid_tbl;
+  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;
+
+  switch( osm_node_get_type( p_node ) )
+  {
+  case IB_NODE_TYPE_CA:
+    break;
+
+  case IB_NODE_TYPE_SWITCH:
+    __osm_drop_mgr_remove_switch( p_mgr, p_node );
+    break;
+
+  case IB_NODE_TYPE_ROUTER:
+    __osm_drop_mgr_remove_router( p_mgr, p_node );
+    break;
+
+  default:
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "__osm_drop_mgr_process_node: ERR 0104: "
+             "Node 0x%016" PRIx64 " unknown node type: %u.\n",
+             cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+             osm_node_get_type( p_node ) );
+    break;
+  }
+
+  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 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_drop_mgr_check_node(
+  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_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_VERBOSE,
+             "__osm_drop_mgr_check_node: ERR 0107: "
+             "Node 0x%016" PRIx64 " is not a switch node\n",
+             cl_ntoh64( node_guid ) );
+    goto Exit;
+  }
+
+  p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+  /* Make sure we have a switch object for this node */
+  p_sw = (osm_switch_t*)cl_qmap_get( p_sw_guid_tbl, node_guid );
+  if (p_sw == (osm_switch_t*)cl_qmap_end( p_sw_guid_tbl ) )
+  {
+    /* 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 " 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;
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_drop_mgr_process );
+
+  CL_ASSERT( p_mgr );
+
+  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 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/trunk/ulp/opensm/user/opensm/osm_fwd_tbl.c b/trunk/ulp/opensm/user/opensm/osm_fwd_tbl.c
new file mode 100644 (file)
index 0000000..6edfad6
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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_memory.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/trunk/ulp/opensm/user/opensm/osm_inform.c b/trunk/ulp/opensm/user/opensm/osm_inform.c
new file mode 100644 (file)
index 0000000..655e969
--- /dev/null
@@ -0,0 +1,718 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <complib/cl_memory.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 )
+{
+  cl_memclr( p_infr, sizeof(osm_infr_t) );
+}
+/**********************************************************************
+ **********************************************************************/
+
+void
+osm_infr_destroy(
+  IN osm_infr_t* const p_infr )
+{
+  cl_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 */
+  cl_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*)cl_malloc( sizeof(osm_infr_t) );
+  if( p_infr )
+  {
+    osm_infr_construct( p_infr );
+    osm_infr_init( p_infr, p_infr_rec );
+  }
+
+  return( p_infr );
+}
+
+/**********************************************************************
+ * Match an infr by the RID of the stored inform_info_record
+ **********************************************************************/
+static
+cl_status_t
+__match_rid_of_inf_rec(
+  IN  const cl_list_item_t* const p_list_item,
+  IN  void*                       context )
+{
+  ib_inform_info_record_t* p_infr_rec = (ib_inform_info_record_t  *)context;
+  osm_infr_t* p_infr = (osm_infr_t*)p_list_item;
+  int32_t count;
+
+
+  count = cl_memcmp(
+    &p_infr->inform_record,
+    p_infr_rec,
+    sizeof(p_infr_rec->subscriber_gid) +
+    sizeof(p_infr_rec->subscriber_enum) );
+
+  if(count == 0)
+    return CL_SUCCESS;
+  else
+    return CL_NOT_FOUND;
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+osm_infr_t*
+osm_infr_get_by_rid(
+  IN osm_subn_t   const *p_subn,
+  IN osm_log_t *p_log,
+  IN ib_inform_info_record_t* const p_infr_rec )
+{
+  cl_list_item_t* p_list_item;
+  OSM_LOG_ENTER( p_log, osm_infr_get_by_rid );
+
+  p_list_item = cl_qlist_find_from_head(
+    &p_subn->sa_infr_list,
+    __match_rid_of_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
+__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 );
+
+   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  );
+   }
+   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;
+  int32_t count1, count2;
+
+  OSM_LOG_ENTER( p_log, __match_inf_rec);
+  count1 = cl_memcmp(&p_infr->report_addr, &p_infr_rec->report_addr,
+                    sizeof(p_infr_rec->report_addr));
+  if (count1) 
+    osm_log(p_log, OSM_LOG_DEBUG,
+           "__match_inf_rec : "
+           "Differ by Address\n");
+  count2 = cl_memcmp(
+    &p_infr->inform_record.inform_info,
+    &p_infr_rec->inform_record.inform_info,
+    sizeof(p_infr->inform_record.inform_info));
+  if (count2) 
+    osm_log(p_log, OSM_LOG_DEBUG,
+           "__match_inf_rec : "
+           "Differ by InformInfo\n" ); 
+  if ((count1 == 0) && (count2 == 0))
+    status = CL_SUCCESS;
+  else
+    status = CL_NOT_FOUND;
+
+  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 is : %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 a new InformInfo Record:\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);
+
+ /* osm_dump_inform_info(p_log, 
+    &(p_infr->inform_record.inform_info), OSM_LOG_DEBUG); */
+
+  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 - of SubnAdmClass
+ *
+ **********************************************************************/
+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 );
+
+  /* HACK: I'm not sure if we can simply use the SA MAD format for
+     notices. However, this is what is implied by the spec */
+  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 route comapre a given Notice and a ListItem of InformInfo type.
+ *
+ * PRE REQUISITES:
+ * 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  )
+  {
+    /* macth by GID */
+    if (cl_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 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
+ **********************************************************************/
+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/trunk/ulp/opensm/user/opensm/osm_lid_mgr.c b/trunk/ulp/opensm/user/opensm/osm_lid_mgr.c
new file mode 100644 (file)
index 0000000..f4c25f7
--- /dev/null
@@ -0,0 +1,1316 @@
+/*
+ * 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$
+ */
+
+/*
+ * 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 persistant 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 $
+ */
+
+/*
+  Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.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_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 )
+{
+  cl_memclr( p_mgr, 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 ) )
+  {
+    cl_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.
+**********************************************************************/
+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 range 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 acording 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 assigend */
+        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 persistant 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 re-assign */
+  if (!p_mgr->p_subn->opt.reassign_lids)
+  {
+    if (osm_db_restore(p_mgr->p_g2l))
+    {
+      osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+               "osm_lid_mgr_init: ERR 0317: " 
+               "Error restoring Guid-to-Lid persistant database.\n");
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+    /* 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 );
+}
+
+/**********************************************************************
+ 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
+**********************************************************************/
+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, l;
+  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);
+  
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_init_sweep );
+
+  /* if we came out of standby we need to discard any previous guid 2 lid
+     info we might had */
+  if ( p_mgr->p_subn->coming_out_of_standby == TRUE )
+  {
+    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_mgr->used_lids, lid, NULL);
+  }
+
+  /* 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 ) )
+  {
+    cl_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 on the first sweep and in re-assign lids mode 
+     we should ignore all the available info and simply define one 
+     hufe 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 *)cl_malloc(sizeof(osm_lid_mgr_range_t));
+    p_range->min_lid = 1;
+    goto AfterScanningLids;
+  }
+
+  /* go over all discvered 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);
+    for (lid = disc_min_lid; lid <= disc_max_lid; lid++)
+      cl_ptr_vector_set(p_discovered_vec, lid, p_port );
+  }
+
+  /* 
+     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;
+    }
+
+    /* check the discovered port if there is one */
+    if ((lid < max_discovered_lid) &&
+        (p_port = (osm_port_t *)cl_ptr_vector_get(p_discovered_vec, lid)))
+    {
+      /* get the lid range of that port  - but we know how many lids we 
+         are about to assign to it */
+      osm_port_get_lid_range_ho(p_port, &disc_min_lid, &disc_max_lid);
+      if ( osm_node_get_type( osm_port_get_parent_node( p_port ) ) !=
+           IB_NODE_TYPE_SWITCH)
+        disc_max_lid = disc_min_lid + lmc_num_lids - 1;
+
+      /* 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))
+      {
+        /* ok there is an asignment - is it the same ? */
+        if ((disc_min_lid == db_min_lid) && (disc_max_lid == db_max_lid))
+        {
+          osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+                   "__osm_lid_mgr_init_sweep: "
+                   "[0x%04x,0x%04x] is not free as it was discovered "
+                   " and mapped by the persistent db.\n",
+                   disc_min_lid, disc_max_lid);
+          is_free = FALSE;
+        }
+        else
+        {
+          osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+                   "__osm_lid_mgr_init_sweep: "
+                   "[0x%04x,0x%04x] is free as it was discovered"
+                   " but mapped to range: [0x%x:0x%x] by the persistent db.\n",
+                   disc_min_lid, disc_max_lid, db_min_lid, db_max_lid);
+          for (l = disc_min_lid; l <= disc_max_lid; l++)
+            cl_ptr_vector_set(p_discovered_vec, l, NULL);
+        }
+      }
+      else
+      {
+        osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+                 "__osm_lid_mgr_init_sweep: "
+                 "0x%04x is not free as it was discovered"
+                 " and there is no persistent db entry for it.\n",
+                 lid);
+        is_free = FALSE;
+      }
+
+      /* if there is more then one lid on that port - and the discovered port
+         is going to retain its lids advance to the max lid */
+      if (is_free == FALSE)
+      {
+        lid = disc_max_lid;
+      }
+    }
+
+    if (is_free)
+    {
+      if (p_range)
+      {
+        p_range->max_lid = lid;
+      }
+      else
+      {
+        p_range =
+          (osm_lid_mgr_range_t *)cl_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 *)cl_malloc(sizeof(osm_lid_mgr_range_t));
+    p_range->min_lid = 1;
+  }
+  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 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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);
+  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.
+**********************************************************************/
+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 switch then we only need one lid */
+  if( osm_node_get_type( osm_port_get_parent_node( p_port ) ) ==
+      IB_NODE_TYPE_SWITCH )
+    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 matches 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
+     re-assign 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;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+__osm_lid_mgr_set_physp_pi(
+  IN osm_lid_mgr_t *       const p_mgr,
+  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;
+
+  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) )
+  {
+    /*
+      Switches ports that are not 0 - should not be set with the
+      following attributes 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.
+  */
+
+  cl_memclr( payload, IB_SMP_DATA_SIZE );
+
+  /* Correction by FUJITSU */
+  if( port_num != 0 )
+  {
+    cl_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
+  */
+  /* 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 (cl_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 (cl_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 (cl_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 (cl_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 (cl_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 (cl_memcmp( &p_pi->link_width_enabled, &p_old_pi->link_width_enabled,
+                   sizeof(p_pi->link_width_enabled) ))
+      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 (cl_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 (cl_memcmp( &p_pi->error_threshold, &p_old_pi->error_threshold,
+                   sizeof(p_pi->error_threshold) ))
+      send_set = TRUE;
+
+    /*
+      TO DO -
+      If the subnet is being reconfigured, should we force the link
+      to the INIT state?
+
+      To reset the port state machine we can send PortInfo.State = DOWN.
+      (see: 7.2.7 p161 lines:10-19.)
+    */
+    if ( (mtu != ib_port_info_get_mtu_cap( 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_mtu_cap( p_old_pi ),
+                 op_vls, ib_port_info_get_op_vls(p_old_pi)
+                 );
+      }
+      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 sw. port 0 to:%u\n",
+             ib_port_info_get_neighbor_mtu( p_pi ) );
+  }
+
+  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;
+
+  /*
+    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
+  */
+  if ( ( p_mgr->p_subn->first_time_master_sweep == TRUE ) &&
+       ( (p_old_pi->capability_mask & IB_PORT_CAP_HAS_CLIENT_REREG) != 0 ) )
+    ib_port_info_set_client_rereg( p_pi, 1 );
+
+  /* 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. 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.
+     3. got_set_resp on the physical port is FALSE. This means we haven't seen
+     this port before - 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,
+                          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_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
+     persistant 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;
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_lid_mgr_process_subnet );
+
+  CL_ASSERT( p_mgr );
+
+  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_physp, cl_hton16( min_lid_ho )))
+        p_mgr->send_set_reqs = TRUE;
+        
+    }
+  } /* all ports */
+
+  /* store the guid to lid table in persistant 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/trunk/ulp/opensm/user/opensm/osm_lin_fwd_rcv.c b/trunk/ulp/opensm/user/opensm/osm_lin_fwd_rcv.c
new file mode 100644 (file)
index 0000000..b725b2b
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lft_rcv_destroy(
+  IN osm_lft_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_lft_rcv_destroy );
+
+  CL_ASSERT( p_rcv );
+  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 )
+{
+  cl_qmap_t *p_sw_tbl;
+  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;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_lft_rcv_process );
+
+  CL_ASSERT( p_rcv );
+  CL_ASSERT( p_madw );
+
+  p_sw_tbl = &p_rcv->p_subn->sw_guid_tbl;
+  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_switch_t*)cl_qmap_get( p_sw_tbl, node_guid );
+
+  if( p_sw == (osm_switch_t*)cl_qmap_end( p_sw_tbl ) )
+  {
+    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/trunk/ulp/opensm/user/opensm/osm_lin_fwd_rcv_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_lin_fwd_rcv_ctrl.c
new file mode 100644 (file)
index 0000000..ea3322b
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <complib/cl_memory.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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_lin_fwd_tbl.c b/trunk/ulp/opensm/user/opensm/osm_lin_fwd_tbl.c
new file mode 100644 (file)
index 0000000..75e94d2
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <complib/cl_memory.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*)cl_malloc(
+    __osm_lin_tbl_compute_obj_size( size ) );
+
+  /*
+    Initialize the table to OSM_NO_PATH, which means "invalid port"
+  */
+  cl_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 )
+{
+  cl_free( *pp_tbl );
+  *pp_tbl = NULL;
+}
diff --git a/trunk/ulp/opensm/user/opensm/osm_link_mgr.c b/trunk/ulp/opensm/user/opensm/osm_link_mgr.c
new file mode 100644 (file)
index 0000000..469c591
--- /dev/null
@@ -0,0 +1,476 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <iba/ib_types.h>
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_mgr, 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 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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                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 )
+  {
+    osm_switch_t *p_switch;
+    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. (p734, table132)
+    */
+    p_switch = osm_get_switch_by_guid( p_mgr->p_subn, p_node->node_info.node_guid );
+    if (! p_switch )
+    {
+      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_switch );
+    if (ib_switch_info_is_enhanced_port_0( 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;
+    }
+  }
+
+  /*
+    PAST THIS POINT WE ARE HANDLING EITHER A NON PORT 0 OR ENHANCED PORT 0
+  */
+
+  p_node = osm_physp_get_node_ptr( p_physp );
+  p_old_pi = osm_physp_get_port_info_ptr( p_physp );
+
+  cl_memclr( payload, IB_SMP_DATA_SIZE );
+
+  /* Correction by FUJITSU */
+  cl_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 (cl_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 (cl_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 (cl_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 (cl_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 (cl_memcmp( &p_pi->m_key_lease_period, &p_old_pi->m_key_lease_period, 
+                     sizeof(p_pi->m_key_lease_period) ))
+        send_set = TRUE;
+
+      p_pi->mkey_lmc = p_mgr->p_subn->opt.lmc;
+      if (cl_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 (p_remote_physp && 
+        osm_physp_is_valid(p_remote_physp) &&
+        (osm_node_get_type( osm_physp_get_node_ptr(p_remote_physp) ) != 
+         IB_NODE_TYPE_SWITCH))
+    {
+      /* we drive an HCA port so we need to set stall-count to 1 and
+         use leaf hoq value */
+      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, OSM_DEFAULT_LEAF_VL_STALL_COUNT);
+    }
+    else
+    {
+      ib_port_info_set_hoq_lifetime(
+        p_pi, p_mgr->p_subn->opt.head_of_queue_lifetime);
+    }
+    if ( ib_port_info_get_hoq_lifetime(p_pi) !=
+         ib_port_info_get_hoq_lifetime(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 (cl_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 (cl_memcmp( &p_pi->link_width_enabled, &p_old_pi->link_width_enabled, 
+                    sizeof(p_pi->link_width_enabled) ))
+      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 becaused 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;
+
+  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,
+                          IB_MAD_ATTR_PORT_INFO,
+                          cl_hton32(port_num),
+                          CL_DISP_MSGID_NONE,
+                          &context );
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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/trunk/ulp/opensm/user/opensm/osm_matrix.c b/trunk/ulp/opensm/user/opensm/osm_matrix.c
new file mode 100644 (file)
index 0000000..3c3dc48
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <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;
+  cl_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 );
+  cl_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/trunk/ulp/opensm/user/opensm/osm_mcast_fwd_rcv.c b/trunk/ulp/opensm/user/opensm/osm_mcast_fwd_rcv.c
new file mode 100644 (file)
index 0000000..6c0a519
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <iba/ib_types.h>
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mft_rcv_destroy(
+  IN osm_mft_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_mft_rcv_destroy );
+
+  CL_ASSERT( p_rcv );
+  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 )
+{
+  cl_qmap_t *p_sw_tbl;
+  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;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_mft_rcv_process );
+
+  CL_ASSERT( p_rcv );
+  CL_ASSERT( p_madw );
+
+  p_sw_tbl = &p_rcv->p_subn->sw_guid_tbl;
+  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_switch_t*)cl_qmap_get( p_sw_tbl, node_guid );
+
+  if( p_sw == (osm_switch_t*)cl_qmap_end( p_sw_tbl ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_mft_rcv_process: ERR 0801: "
+             "LFT 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 forwarding table block failed (%s)"
+               "\n\t\t\t\tSwitch 0x%016" PRIx64
+               ", block_num = %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/trunk/ulp/opensm/user/opensm/osm_mcast_fwd_rcv_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_mcast_fwd_rcv_ctrl.c
new file mode 100644 (file)
index 0000000..078c16d
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <complib/cl_memory.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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_mcast_mgr.c b/trunk/ulp/opensm/user/opensm/osm_mcast_mgr.c
new file mode 100644 (file)
index 0000000..b152fc3
--- /dev/null
@@ -0,0 +1,1707 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <iba/ib_types.h>
+#include <complib/cl_memory.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 = cl_zalloc( sizeof( *p_obj ) );
+  if( 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 )
+{
+  cl_free( p_wobj );
+}
+
+/**********************************************************************
+   Recursively remove nodes from the tree
+**********************************************************************/
+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;
+
+  }
+
+  cl_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 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+uint32_t
+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 )
+{
+  uint32_t 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 = 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
+ **********************************************************************/
+uint32_t
+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 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 );
+    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( 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;
+  uint32_t                 hops = 0;
+  uint32_t                 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 )
+{
+  cl_memclr( p_mgr, sizeof(*p_mgr) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcast_mgr_destroy(
+  IN osm_mcast_mgr_t* const p_mgr )
+{
+  OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_destroy );
+
+  CL_ASSERT( p_mgr );
+  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;
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_set_tbl );
+
+  CL_ASSERT( p_mgr );
+  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,
+                          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 linear 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 to not 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 eminate 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;
+  cl_qmap_t*               p_sw_guid_tbl;
+  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;
+  }
+
+  p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+  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 = cl_zalloc( 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;
+  }
+
+  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;
+    osm_switch_t        *p_remote_sw;
+
+    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 %u 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.
+      */
+      p_remote_sw = (osm_switch_t*)cl_qmap_get(
+        p_sw_guid_tbl, osm_node_get_node_guid( p_remote_node ) );
+      CL_ASSERT( p_remote_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_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 );
+    }
+  }
+
+  cl_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_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_tbl = &p_mgr->p_subn->sw_guid_tbl;
+  p_sw = (osm_switch_t*)cl_qmap_head( p_tbl );
+  while( p_sw != (osm_switch_t*)cl_qmap_end( p_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;
+  cl_qmap_t*               p_sw_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;
+  p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl;
+  mlid_ho = cl_ntoh16( mlid );
+
+  if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+  {
+    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 = (osm_switch_t*)cl_qmap_get( p_sw_tbl, sw_guid );
+  if( p_sw == (osm_switch_t*)cl_qmap_end( p_sw_tbl ) )
+  {
+    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_VERBOSE ) )
+        {
+          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_VERBOSE ) )
+    {
+      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
+**********************************************************************/
+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;
+  cl_qmap_t*               p_tbl;
+  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 );
+  p_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+  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 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcast_mgr_dump_mcast_routes(
+  IN const osm_mcast_mgr_t*   const p_mgr,
+  IN const osm_switch_t*      const p_sw )
+{
+  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;
+  char                  line[OSM_REPORT_LINE_SIZE];
+  boolean_t             print_lid;
+  const osm_node_t*     p_node;
+  FILE  *               p_mcfdbFile;
+  uint16_t              i, j;
+  uint16_t              mask_entry;
+  char                 *file_name = NULL;
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_dump_mcast_routes );
+  
+  if( !osm_log_is_active( p_mgr->p_log, OSM_LOG_ROUTING ) )
+    goto Exit;
+
+  file_name = 
+    (char*)cl_malloc(strlen(p_mgr->p_subn->opt.dump_files_dir) + 12);
+  
+  CL_ASSERT(file_name);
+  
+  strcpy(file_name, p_mgr->p_subn->opt.dump_files_dir);
+  strcat(file_name,"/osm.mcfdbs");
+  
+  /* Open the file or error */
+  p_mcfdbFile = fopen(file_name, "a");
+  if (! p_mcfdbFile)
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "osm_mcast_mgr_dump_mcast_routes: ERR 0A23: "
+             "Fail to open mcfdb file (%s).\n",
+             file_name );
+    goto Exit;
+  }
+
+  p_node = osm_switch_get_node_ptr( p_sw );
+
+  p_tbl = osm_switch_get_mcast_tbl_ptr( p_sw );
+
+  fprintf( p_mcfdbFile, "\nSwitch 0x%016" PRIx64 "\n"
+           "LID    : Out Port(s) \n",
+           cl_ntoh64( osm_node_get_node_guid( p_node ) ) );  
+  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;
+      print_lid = FALSE;
+      sprintf( line, "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;
+        }
+        print_lid = TRUE;
+        for (j = 0 ; j < 16 ; j++)
+        {
+          if ( (1 << j) & mask_entry )
+            sprintf( line, "%s 0x%03X ", line, j+(position*16) );
+        }
+        position++;
+      }
+      if (print_lid)
+      {
+        fprintf( p_mcfdbFile, "%s\n", line );
+      }
+    }
+    block_num++;
+  }
+
+  fclose(p_mcfdbFile);
+
+ Exit:
+  if (file_name)
+    cl_free(file_name);
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ Process the entire group.
+
+ NOTE : The lock should be held externally!
+ **********************************************************************/
+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_tbl;
+  boolean_t             pending_transactions = FALSE;
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_process_mgrp );
+
+  p_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;
+  }
+
+  /* initialize the mc fdb dump file: */
+  if( osm_log_is_active( p_mgr->p_log, OSM_LOG_ROUTING ) )
+    unlink("/tmp/osm.mcfdbs");
+
+  /*
+    Walk the switches and download the tables for each.
+  */
+  p_sw = (osm_switch_t*)cl_qmap_head( p_tbl );
+  while( p_sw != (osm_switch_t*)cl_qmap_end( p_tbl ) )
+  {
+    signal = __osm_mcast_mgr_set_tbl( p_mgr, p_sw );
+    if( signal == OSM_SIGNAL_DONE_PENDING )
+      pending_transactions = TRUE;
+
+    osm_mcast_mgr_dump_mcast_routes( p_mgr, p_sw );
+
+    p_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item );
+  }
+
+ 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_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_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 );
+  }
+
+  /* initialize the mc fdb dump file: */
+  if( osm_log_is_active( p_mgr->p_log, OSM_LOG_ROUTING ) )
+    unlink("/tmp/osm.mcfdbs");
+
+  /*
+    Walk the switches and download the tables for each.
+  */
+  p_sw = (osm_switch_t*)cl_qmap_head( p_tbl );
+  while( p_sw != (osm_switch_t*)cl_qmap_end( p_tbl ) )
+  {
+    signal = __osm_mcast_mgr_set_tbl( p_mgr, p_sw );
+    if( signal == OSM_SIGNAL_DONE_PENDING )
+      pending_transactions = TRUE;
+
+    osm_mcast_mgr_dump_mcast_routes( p_mgr, p_sw );
+
+    p_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item );
+  }
+
+  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_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 */
+  cl_memcpy(&mlid, &p_ctxt->mlid, sizeof(mlid));
+
+  /* we can destroy the context now */
+  cl_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)
+    {
+      signal = OSM_SIGNAL_DONE;
+      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;
+    }
+    CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+    /* 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 registerd for
+         Trap 67 : MCGroup delete */
+      osm_mgrp_send_delete_notice( p_mgr->p_subn, p_mgr->p_log, p_mgrp );
+
+      CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
+      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 );
+    }
+    /* no need for CL_PLOCK_RELEASE( p_mgr->p_lock ) - internally done */
+    OSM_LOG_EXIT( p_mgr->p_log );
+    return signal;
+  }
+  else
+  {
+    CL_PLOCK_RELEASE( p_mgr->p_lock );
+    OSM_LOG_EXIT( p_mgr->p_log );
+    return OSM_SIGNAL_DONE;
+  }
+
+}
diff --git a/trunk/ulp/opensm/user/opensm/osm_mcast_tbl.c b/trunk/ulp/opensm/user/opensm/osm_mcast_tbl.c
new file mode 100644 (file)
index 0000000..fe38871
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <complib/cl_memory.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 );
+
+  cl_memclr( p_tbl, 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 = cl_zalloc( 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 );
+
+  return( IB_SUCCESS );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcast_tbl_destroy(
+  IN osm_mcast_tbl_t* const p_tbl )
+{
+  cl_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...
+    */
+    cl_memclr( p_block, 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/trunk/ulp/opensm/user/opensm/osm_mcm_info.c b/trunk/ulp/opensm/user/opensm/osm_mcm_info.c
new file mode 100644 (file)
index 0000000..aff3831
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <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*)cl_zalloc( sizeof(*p_mcm) );
+  if( 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 );
+  cl_free( p_mcm );
+}
+
diff --git a/trunk/ulp/opensm/user/opensm/osm_mcm_port.c b/trunk/ulp/opensm/user/opensm/osm_mcm_port.c
new file mode 100644 (file)
index 0000000..edbf1c8
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/osm_mcm_port.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcm_port_construct(
+  IN osm_mcm_port_t* const p_mcm )
+{
+  cl_memclr( p_mcm, 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 = cl_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 );
+  cl_free( p_mcm );
+}
diff --git a/trunk/ulp/opensm/user/opensm/osm_mtree.c b/trunk/ulp/opensm/user/opensm/osm_mtree.c
new file mode 100644 (file)
index 0000000..cdfa46d
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <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 = cl_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]);
+  
+  cl_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:%d\n", 
+         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/trunk/ulp/opensm/user/opensm/osm_multicast.c b/trunk/ulp/opensm/user/opensm/osm_multicast.c
new file mode 100644 (file)
index 0000000..d07046f
--- /dev/null
@@ -0,0 +1,402 @@
+/*
+ * 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$
+ */
+
+
+
+/*
+ * Abstract:
+ *    Implementation of multicast functions.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_mgrp, 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);
+
+  cl_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*)cl_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 portshould 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(&notice, CL_NTOH32(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 */
+  cl_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(&notice, CL_HTON32(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 */
+  cl_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/trunk/ulp/opensm/user/opensm/osm_node.c b/trunk/ulp/opensm/user/opensm/osm_node.c
new file mode 100644 (file)
index 0000000..250aac4
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <complib/cl_memory.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            port_num;
+  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 );
+  port_num = ib_node_info_get_local_port_num( p_ni );
+
+  /*
+    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 = cl_zalloc( sizeof(*p_node) + sizeof(osm_physp_t) * size );
+  if( p_node != NULL )
+  {
+    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 );
+  cl_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 );
+
+  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/trunk/ulp/opensm/user/opensm/osm_node_desc_rcv.c b/trunk/ulp/opensm/user/opensm/osm_node_desc_rcv.c
new file mode 100644 (file)
index 0000000..e502222
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.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 ) )
+  {
+    cl_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 );
+  }
+
+  cl_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 )
+{
+  cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nd_rcv_destroy(
+  IN osm_nd_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_nd_rcv_destroy );
+
+  CL_ASSERT( p_rcv );
+  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;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_nd_rcv_process );
+
+  CL_ASSERT( p_rcv );
+  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/trunk/ulp/opensm/user/opensm/osm_node_desc_rcv_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_node_desc_rcv_ctrl.c
new file mode 100644 (file)
index 0000000..e52b0d8
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x601
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_node_info_rcv.c b/trunk/ulp/opensm/user/opensm/osm_node_info_rcv.c
new file mode 100755 (executable)
index 0000000..afe72a4
--- /dev/null
@@ -0,0 +1,1044 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.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_mad_pool.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+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 ) )
+          {
+            /*
+              Uh oh...
+            */
+            p_old_neighbor_node = osm_node_get_remote_node(
+              p_node, port_num, &old_neighbor_port_num );
+
+            osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                     "__osm_ni_rcv_set_links: ERR 0D01: "
+                     "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.\n"
+                     "\t\t\t\tnew node 0x%" PRIx64 ", "
+                     "port number 0x%X.\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 ,
+                     cl_ntoh64( p_ni_context->node_guid ),
+                     p_ni_context->port_num
+                     );
+
+            if (osm_log_is_active(p_rcv->p_log, OSM_LOG_ERROR))
+            {
+              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);
+             
+              p_old_physp = osm_node_get_physp_ptr(
+                p_old_neighbor_node,
+                old_neighbor_port_num);
+              if (p_old_physp)
+                osm_dump_dr_path(p_rcv->p_log,
+                                 osm_physp_get_dr_path_ptr( p_old_physp ),
+                                 OSM_LOG_ERROR);
+            }
+          }
+
+          /* 
+             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);
+          }
+          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.
+**********************************************************************/
+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 );
+
+  CL_ASSERT( p_node );
+
+  /*
+    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;
+
+  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.
+**********************************************************************/
+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.
+**********************************************************************/
+void
+__osm_ni_rcv_process_new_ca(
+  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 );
+
+  __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.
+**********************************************************************/
+void
+__osm_ni_rcv_process_ca_port(
+  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_ca_port );
+
+  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_ca_port: "
+             "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_ca_port: 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_ca_port: 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_ca_port: 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_ca_port: "
+                 "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 );
+    CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+    /*
+      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_ca_port: ERR 0D13: "
+             "Failure initiating PortInfo request (%s).\n",
+             ib_get_err_str(status));
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+void
+__osm_ni_rcv_process_existing_ca(
+  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_ca );
+
+  __osm_ni_rcv_process_ca_port( p_rcv, p_node, p_madw );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+void
+__osm_ni_rcv_process_new_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_router );
+
+  __osm_ni_rcv_process_new_node( p_rcv, p_node, p_madw );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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.
+**********************************************************************/
+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 )
+{
+  cl_qmap_t *p_sw_guid_tbl;
+  ib_net64_t node_guid;
+  osm_switch_t *p_sw;
+
+  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 */
+    p_sw_guid_tbl = &p_rcv->p_subn->sw_guid_tbl;
+    node_guid = osm_node_get_node_guid( p_node );
+    p_sw = (osm_switch_t*)cl_qmap_get( p_sw_guid_tbl,
+                                       node_guid );
+    if( p_sw == (osm_switch_t*)cl_qmap_end( p_sw_guid_tbl ) ||
+        osm_switch_discovery_count_get( p_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(node_guid) );
+      __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.
+**********************************************************************/
+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.
+**********************************************************************/
+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;
+  cl_qmap_t *p_node_guid_tbl;
+  cl_qmap_t *p_port_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;
+  }
+
+  p_node_guid_tbl = &p_rcv->p_subn->node_guid_tbl;
+  p_port_guid_tbl = &p_rcv->p_subn->port_guid_tbl;
+
+  /*
+    Add the new port object to the database.
+  */
+  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);
+
+    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 list.\n",
+               CL_STATUS_MSG(status ) );
+      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 )) );
+    }
+  }
+
+  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:
+    __osm_ni_rcv_process_new_ca( 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;
+  case IB_NODE_TYPE_ROUTER:
+    __osm_ni_rcv_process_new_router( 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.
+**********************************************************************/
+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_ROUTER:
+    /* Not supported yet. */
+    break;
+
+  case IB_NODE_TYPE_CA:
+    __osm_ni_rcv_process_existing_ca( 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 )
+{
+  cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ni_rcv_destroy(
+  IN osm_ni_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_ni_rcv_destroy );
+
+  CL_ASSERT( p_rcv );
+  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;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_ni_rcv_process );
+
+  CL_ASSERT( p_rcv );
+  CL_ASSERT( p_madw );
+
+  p_guid_tbl = &p_rcv->p_subn->node_guid_tbl;
+  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;
+  }
+  /*
+    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/trunk/ulp/opensm/user/opensm/osm_node_info_rcv_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_node_info_rcv_ctrl.c
new file mode 100644 (file)
index 0000000..eeecc47
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_opensm.c b/trunk/ulp/opensm/user/opensm/osm_opensm.c
new file mode 100644 (file)
index 0000000..2e800d1
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <complib/cl_memory.h>
+#include <complib/cl_signal_osd.h>
+#include <opensm/cl_dispatcher.h>
+#include <complib/cl_passivelock.h>
+#include <vendor/osm_vendor_api.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>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_opensm_construct(
+   IN osm_opensm_t * const p_osm )
+{
+   cl_memclr( p_osm, 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 Q1 Messages and 
+    */
+   osm_sa_shutdown( &p_osm->sa );
+
+   /* shut down the SM 
+    * - make sure the SM sweeper thread exited
+    * - unbind from Q0 Messages and 
+    */
+   osm_sm_shutdown( &p_osm->sm );
+
+   /* shut down the dispatcher - so no new messages cross */
+   cl_disp_shutdown( &p_osm->disp );
+
+   /* cleanup all messages on VL15 fifo that were not sent yet */
+   osm_vl15_shutdown( &p_osm->vl15, &p_osm->mad_pool );
+
+   /* lock the whole thing so we do not get any requests etc */
+   cl_plock_excl_acquire( &p_osm->lock );
+
+   /* do the destruction in reverse init order */
+   updn_destroy( p_osm->p_updn_ucast_routing );
+   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_release( &p_osm->lock );
+   cl_plock_destroy( &p_osm->lock );
+
+   cl_mem_display(  );
+
+   osm_log_destroy( &p_osm->log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+osm_opensm_create_mcgroups(
+   IN osm_opensm_t * const p_osm,
+   IN const osm_subn_opt_t * const p_opt )
+{
+   OSM_LOG_ENTER( &p_osm->log, osm_opensm_create_mcgroups );
+   osm_sa_create_template_record_ipoib( &p_osm->sa, p_opt );
+   OSM_LOG_EXIT( &p_osm->log );
+}
+
+/**********************************************************************
+ * SHUT DOWN IS CONTROLLED BY A GLOBAL EXIT FLAG
+ **********************************************************************/
+#ifndef __WIN__
+static osm_opensm_t *__p_osm_to_signal;
+
+void
+__sig_handler(
+   int signum )
+{
+   static int got_signal = 0;
+
+   if( signum != SIGHUP )
+   {
+      if( !got_signal )
+      {
+         got_signal++;
+         printf( "OpenSM: Got signal %d - exiting...\n", signum );
+         osm_exit_flag = 1;
+      }
+   }
+   else
+   {
+      /* a HUP signal should only start a new heavy sweep */
+      __p_osm_to_signal->subn.force_immediate_heavy_sweep = TRUE;
+      osm_state_mgr_process( &__p_osm_to_signal->sm.state_mgr,
+                             OSM_SIGNAL_SWEEP );
+   }
+}
+
+void
+osm_reg_sig_handler(
+   IN osm_opensm_t * const p_osm )
+{
+   __p_osm_to_signal = p_osm;
+   cl_reg_sig_hdl( SIGINT, __sig_handler );
+   cl_reg_sig_hdl( SIGTERM, __sig_handler );
+   cl_reg_sig_hdl( SIGHUP, __sig_handler );
+   osm_exit_flag = 0;
+
+   return;
+}
+#endif
+
+/**********************************************************************
+ **********************************************************************/
+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( &p_osm->log, p_opt->force_log_flush,
+                          p_opt->log_flags, p_opt->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_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 );
+   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;
+
+   osm_opensm_create_mcgroups( p_osm, p_opt );
+
+   /* HACK - the UpDown manager should have been a part of the osm_sm_t */
+   /* Init updn struct */
+   p_osm->p_updn_ucast_routing = updn_construct(  );
+   status = updn_init( p_osm->p_updn_ucast_routing );
+   if( status != IB_SUCCESS )
+      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/trunk/ulp/opensm/user/opensm/osm_pkey.c b/trunk/ulp/opensm/user/opensm/osm_pkey.c
new file mode 100644 (file)
index 0000000..c1dc8aa
--- /dev/null
@@ -0,0 +1,397 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <complib/cl_memory.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_map_construct( &p_pkey_tbl->keys );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_pkey_tbl_destroy( 
+  IN osm_pkey_tbl_t *p_pkey_tbl)
+{
+  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++)
+    cl_free(cl_ptr_vector_get( &p_pkey_tbl->blocks, i ));
+  cl_ptr_vector_destroy( &p_pkey_tbl->blocks );
+
+  cl_map_remove_all( &p_pkey_tbl->keys );
+  cl_map_destroy( &p_pkey_tbl->keys );
+}
+
+/**********************************************************************
+ **********************************************************************/
+int osm_pkey_tbl_init( 
+  IN osm_pkey_tbl_t *p_pkey_tbl)
+{
+  ib_pkey_table_t *p_pkey_block;
+  /* 
+     we always need one block to be pre-allocated for the sake of
+     empty table test
+  */
+  cl_ptr_vector_init( &p_pkey_tbl->blocks, 1, 1);
+  p_pkey_block = (ib_pkey_table_t *)cl_zalloc(sizeof(ib_pkey_table_t));
+  if (! p_pkey_block)
+  {
+    return(IB_ERROR);
+  }
+
+  cl_ptr_vector_set(&p_pkey_tbl->blocks, 0, p_pkey_block);
+
+  /* deal with the map */
+  cl_map_init( &p_pkey_tbl->keys, 1 );
+  return(IB_SUCCESS);
+}
+
+/**********************************************************************
+ **********************************************************************/
+int 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 *)cl_zalloc(sizeof(ib_pkey_table_t));
+    cl_ptr_vector_set( &p_pkey_tbl->blocks, block, p_pkey_block );
+  }
+
+  /* sets the block values */
+  cl_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 partial 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);
+}
+
+/**********************************************************************
+ **********************************************************************/
+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_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 ) {
+
+  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;
+
+  OSM_LOG_ENTER( p_log, osm_physp_share_pkey );
+
+  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 would 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))
+  {
+    OSM_LOG_EXIT( p_log );
+    return(TRUE);
+  }
+  
+  /* we rely on the fact the map are sorted by pkey */
+  map_iter1 = cl_map_head( &pkey_tbl1->keys );
+  map_iter2 = cl_map_head( &pkey_tbl2->keys );
+
+  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))
+    {
+
+      osm_log( p_log, OSM_LOG_DEBUG,
+               "osm_physp_share_pkey: "
+               "Matched pkeys: 0x%04x 0x%04x\n",
+               cl_ntoh16(*pkey1), cl_ntoh16(*pkey2));
+      OSM_LOG_EXIT( p_log );      
+      return(TRUE);
+    }
+    
+    /* advance the lower value if they are no 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 );
+  }
+    
+  osm_log( p_log, OSM_LOG_DEBUG,
+           "osm_physp_share_pkey: "
+           "Ports do not share a pkey\n");
+
+  OSM_LOG_EXIT( p_log );
+  return(FALSE);
+}
+
+/**********************************************************************
+ **********************************************************************/
+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%X\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/trunk/ulp/opensm/user/opensm/osm_pkey_rcv.c b/trunk/ulp/opensm/user/opensm/osm_pkey_rcv.c
new file mode 100644 (file)
index 0000000..2cea818
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * 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$
+ */
+
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rcv_destroy(
+  IN osm_pkey_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_pkey_rcv_destroy );
+
+  CL_ASSERT( p_rcv );
+  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 A 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;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_pkey_rcv_process );
+
+  CL_ASSERT( p_rcv );
+  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) )
+  {
+    cl_plock_release( p_rcv->p_lock );
+    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 ) )
+  {
+    if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_pkey_rcv_process: "
+               "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/trunk/ulp/opensm/user/opensm/osm_pkey_rcv_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_pkey_rcv_ctrl.c
new file mode 100644 (file)
index 0000000..233d527
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * 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$
+ */
+
+
+/*
+  Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_pkey_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_port.c b/trunk/ulp/opensm/user/opensm/osm_port.c
new file mode 100644 (file)
index 0000000..98154c2
--- /dev/null
@@ -0,0 +1,895 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <complib/cl_memory.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 )
+{
+  cl_memclr( p_physp, 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++)
+      cl_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 );
+    
+    cl_memclr( p_physp, 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 *)cl_zalloc(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 = cl_zalloc( sizeof(*p_port) + sizeof(void *) * size );
+  if( p_port != NULL )
+    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 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 256.\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;
+  cl_memcpy(&k, p, sizeof(void *));
+  return k;
+}
+
+inline 
+void *
+__osm_key_to_ptr(uint64_t k) {
+  void *p = 0;
+  cl_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: "
+             "Fail 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) );
+  }
+  
+  cl_memclr( path_array, 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*)cl_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*)cl_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 three of the following occure:
+           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 );
+    cl_free(p_currPortsList);
+  }
+
+  /* cleanup */
+ Exit:
+  cl_list_destroy( p_nextPortsList );
+  cl_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;
+  osm_switch_t* p_switch;
+
+  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 (osm_node_get_type( p_physp->p_node ) != IB_NODE_TYPE_SWITCH ||
+      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.
+    */
+    p_switch = 
+      osm_get_switch_by_guid(p_subn, p_physp->p_node->node_info.node_guid);
+    if (! p_switch)
+    {
+      osm_log( p_log, OSM_LOG_ERROR,
+               "osm_physp_set_pkey_tbl: ERR 4107: "
+               "Cannot find switch by guid: %" PRIx64 "\n",
+               cl_ntoh64(p_physp->p_node->node_info.node_guid) );
+      return;
+    }
+    
+    max_blocks = 
+      (cl_ntoh16(p_switch->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:%u\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/trunk/ulp/opensm/user/opensm/osm_port_info_rcv.c b/trunk/ulp/opensm/user/opensm/osm_port_info_rcv.c
new file mode 100644 (file)
index 0000000..f11a3a7
--- /dev/null
@@ -0,0 +1,812 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <iba/ib_types.h>
+#include <complib/cl_memory.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 should we track extended port 0 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 defiend 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.
+        */
+        cl_memclr( &context, 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;
+  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 managment 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",
+               osm_physp_get_port_state( p_physp ),
+               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 a management port 0 */
+               __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 )
+{
+  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 );
+
+  __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 )
+{
+  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 );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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;
+  osm_switch_t* p_switch;
+
+  OSM_LOG_ENTER( p_log, osm_physp_has_pkey );
+
+  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 (osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH ||
+      port_num == 0 )
+  {
+    /* The maximum blocks is defined on the node info partition cap for CA, routers 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
+       on the switch info partition enforcement cap. */
+    p_switch = osm_get_switch_by_guid(p_subn, p_node->node_info.node_guid);
+
+    if (! p_switch)
+    {
+      osm_log( p_log, OSM_LOG_ERROR,
+               "osm_physp_has_pkey: ERR 4A02: "
+               "Cannot find switch by guid: %" PRIx64 "\n",
+               cl_ntoh64(p_node->node_info.node_guid) );
+      goto Exit;
+    }
+    max_blocks = (cl_ntoh16(p_switch->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++)
+  {
+    status = osm_req_get( p_req,
+                          &path,
+                          IB_MAD_ATTR_P_KEY_TABLE,
+                          cl_hton32(block_num | (port_num << 16) ),
+                          CL_DISP_MSGID_NONE,
+                          &context );
+
+    if( status != IB_SUCCESS )
+    {
+      osm_log( p_log, OSM_LOG_ERROR,
+               "osm_physp_has_pkey: ERR 4A03: "
+               "Failure initiating PkeyTable request (%s).\n",
+               ib_get_err_str(status));
+      goto Exit;
+    }
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+  cl_memclr( p_rcv, 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_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))
+  {
+    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,
+      OSM_LOG_ERROR);
+  }
+
+  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 = %u"
+             "\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 );
+  port_num = (uint8_t)cl_ntoh32( p_smp->attr_mod );
+
+  port_guid = p_context->port_guid;
+  node_guid = p_context->node_guid;
+
+  CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_PORT_INFO );
+
+  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 = %u, 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 subent.
+    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 %u 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 );
+    }
+
+    osm_dump_port_info( p_rcv->p_log,
+                        node_guid, port_guid, port_num, p_pi,
+                        OSM_LOG_DEBUG );
+
+    /*
+      Check if the update_sm_base_lid in the context is on 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/trunk/ulp/opensm/user/opensm/osm_port_info_rcv_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_port_info_rcv_ctrl.c
new file mode 100644 (file)
index 0000000..5aaba07
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_remote_sm.c b/trunk/ulp/opensm/user/opensm/osm_remote_sm.c
new file mode 100644 (file)
index 0000000..534b439
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <opensm/osm_remote_sm.h>
+#include <complib/cl_memory.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_remote_sm_construct(
+  IN osm_remote_sm_t* const p_sm )
+{
+  cl_memclr( p_sm, sizeof(*p_sm) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_remote_sm_destroy(
+  IN osm_remote_sm_t* const p_sm )
+{
+  cl_memclr( p_sm, sizeof(*p_sm) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+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( IB_SUCCESS );
+}
diff --git a/trunk/ulp/opensm/user/opensm/osm_req.c b/trunk/ulp/opensm/user/opensm/osm_req.c
new file mode 100644 (file)
index 0000000..908bb9f
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x300
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.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_memclr( p_req, 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;
+
+  OSM_LOG_ENTER( p_req->p_log, osm_req_get );
+
+  CL_ASSERT( p_req );
+  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 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;
+
+  OSM_LOG_ENTER( p_req->p_log, osm_req_set );
+
+  CL_ASSERT( p_req );
+  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;
+
+  cl_memcpy( osm_madw_get_smp_ptr( p_madw )->data,
+             p_payload, IB_SMP_DATA_SIZE );
+
+  osm_vl15_post( p_req->p_vl15, p_madw );
+
+ Exit:
+  OSM_LOG_EXIT( p_req->p_log );
+  return( status );
+}
+
+
+
+
+
diff --git a/trunk/ulp/opensm/user/opensm/osm_req_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_req_ctrl.c
new file mode 100644 (file)
index 0000000..c570882
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x102
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_resp.c b/trunk/ulp/opensm/user/opensm/osm_resp.c
new file mode 100644 (file)
index 0000000..2f50055
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <iba/ib_types.h>
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_resp, 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 = (ib_net16_t)(status | IB_SMP_DIRECTION);
+  } 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;
+  }
+
+  p_dest_smp->dr_dlid = p_dest_smp->dr_slid;
+  p_dest_smp->dr_slid = p_dest_smp->dr_dlid;
+  cl_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 requester 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/trunk/ulp/opensm/user/opensm/osm_sa.c b/trunk/ulp/opensm/user/opensm/osm_sa.c
new file mode 100644 (file)
index 0000000..3c62aa3
--- /dev/null
@@ -0,0 +1,589 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_sa_t.
+ * This object represents the Subnet Administrator object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.14 $
+ */
+
+/*
+  Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.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>
+
+#define  OSM_SA_INITIAL_TID_VALUE 0xabc
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_construct(
+  IN osm_sa_t* const p_sa )
+{
+  cl_memclr( p_sa, 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_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 );
+
+  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 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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_lr_rcv_ctrl_destroy( &p_sa->lr_rcv_ctrl );
+  osm_pr_rcv_ctrl_destroy( &p_sa->pr_rcv_ctrl );
+  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_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_lr_rcv_destroy( &p_sa->lr_rcv );
+  osm_pr_rcv_destroy( &p_sa->pr_rcv );
+  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_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_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;
+
+  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;
+
+ 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 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_gid_t osm_ipoib_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 */
+  },
+};
+
+/*
+ * HACK: Until TS resolves their un-compliant join compmask
+ * we have to pre-define the MGID
+ */
+ib_gid_t osm_ts_ipoib_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 */
+  },
+};
+
+void
+osm_sa_create_template_record_ipoib(
+  IN osm_sa_t* const p_sa,
+  IN const osm_subn_opt_t* const p_opt )
+{
+  ib_member_rec_t mc_rec;
+
+  osm_log( p_sa->p_log, OSM_LOG_FUNCS,
+           "osm_sa_create_template_record_ipoib: [\n" );
+
+  UNUSED_PARAM( p_opt );
+  cl_memclr(&mc_rec, sizeof(mc_rec));
+
+  /*
+   *  Fill in the default MC Member record
+   */
+  mc_rec.mgid = osm_ipoib_mgid;
+  mc_rec.mtu = 4; /*  2048 Bytes */
+  mc_rec.qkey = CL_HTON32(0x0b1b); /* This value is pushed into the mad, and thus needs
+                                      to be in network order */
+  mc_rec.pkey = IB_DEFAULT_PKEY;
+  mc_rec.rate = 0x3; /* 10Gb/sec */
+  mc_rec.pkt_life = OSM_DEFAULT_SUBNET_TIMEOUT;
+  mc_rec.sl_flow_hop = OSM_DEFAULT_SL << 28;
+  /* Note: scope needs to be consistent with MGID */
+  mc_rec.scope_state = 0x21;
+
+  osm_sa_add_well_known_mc_record(&p_sa->mcmr_rcv, &mc_rec);
+
+  /*
+   * HACK: Until TS resolves their noncompliant join compmask
+   * we have to pre-define the MGID
+   */
+
+  mc_rec.mgid = osm_ts_ipoib_mgid;
+  osm_sa_add_well_known_mc_record(&p_sa->mcmr_rcv, &mc_rec);
+  
+  osm_log( p_sa->p_log, OSM_LOG_FUNCS,
+           "osm_sa_create_template_record_ipoib: ]\n" );
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+void
+osm_sa_add_well_known_mc_record(
+  osm_mcmr_recv_t* const p_mcmr,
+  const ib_member_rec_t * const p_well_know_mc_rec)
+{
+
+  osm_mgrp_t * p_mgrp = NULL;
+  ib_api_status_t status;
+  ib_net64_t comp_mask;
+
+  comp_mask = IB_MCR_COMPMASK_MTU | IB_MCR_COMPMASK_RATE;
+  status = osm_mcmr_rcv_create_new_mgrp(
+    p_mcmr,
+    comp_mask,
+    p_well_know_mc_rec,
+    &p_mgrp);
+  if(p_mgrp)
+  {
+    p_mgrp->well_known = TRUE;
+  }
+  else
+  {
+    osm_log( p_mcmr->p_log, OSM_LOG_DEBUG,
+             "osm_sa_add_well_known_mc_record:"
+             "failed to create a well known group\n");
+
+  }
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+
diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_class_port_info.c b/trunk/ulp/opensm/user/opensm/osm_sa_class_port_info.c
new file mode 100644 (file)
index 0000000..4454afa
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.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>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_cpi_rcv_construct(
+  IN osm_cpi_rcv_t* const p_rcv )
+{
+  cl_memclr( p_rcv, 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;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_cpi_rcv_respond );
+
+  cl_memclr(&zero_gid,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 );
+
+  cl_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 151 p 782) */
+  p_resp_sa_mad->sm_key = 0;
+  p_resp_sa_mad->paylen_newwin = 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;
+  p_resp_cpi->resp_time_val = p_rcv->p_subn->opt.transaction_timeout;
+  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 optionals:
+     OSM_CAP_IS_SUBN_OPT_RECS_SUP :
+     SwitchInfoRecord,
+     LinearForwardingTableRecord, (we do support it - under the table)
+     RandomForwardingTableRecord,
+     MulticastForwardingTableRecord,
+     SMInfoRecord, (we do support it - under the table)
+     InformInfoRecord,
+     LinkRecord, (we do support it - under the table)
+     GuidInfoRecord
+     ServiceAssociationRecord
+
+     OSM_CAP_IS_SUBN_OPT_MULTI_PATH_SUP:
+     MultiPathRecord,
+     TraceRecord
+
+     OSM_CAP_IS_SUBN_OPT_REINIT_SUP:
+     For re-initialization functionality.
+
+     So not sending traps, but supporting Get(Notice) and Set(Notice):
+  */
+  p_resp_cpi->cap_mask = 0x2; /* Note host notation replaced later */
+  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 supports 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/trunk/ulp/opensm/user/opensm/osm_sa_class_port_info_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_class_port_info_ctrl.c
new file mode 100644 (file)
index 0000000..126cd3c
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_sa_informinfo.c b/trunk/ulp/opensm/user/opensm/osm_sa_informinfo.c
new file mode 100644 (file)
index 0000000..246c21a
--- /dev/null
@@ -0,0 +1,567 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <iba/ib_types.h>
+#include <complib/cl_memory.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>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_rcv_construct(
+  IN osm_infr_rcv_t* const p_rcv )
+{
+  cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_rcv_destroy(
+  IN osm_infr_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_infr_rcv_destroy );
+  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 = IB_SUCCESS;
+  /* Exit: */
+  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 acess 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_requestor_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 requestor physp from the request address */
+  p_requestor_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+                                                p_rcv->p_subn,
+                                                &p_infr_rec->report_addr );
+
+  cl_memclr( &zero_gid, sizeof(zero_gid) );
+  if ( cl_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 \n",
+               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 requestor and destination port can access each other 
+       according to the current partitioning. */
+    if (! osm_physp_share_pkey( p_rcv->p_log, p_physp, p_requestor_physp))
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+               "__validate_ports_access_rights: "
+               "port and requestor 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 
+       requestor 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 (%u) is out of range:%u. \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 requestor and destination port can access each other 
+         according to the current partitioning. */
+      if (! osm_physp_share_pkey( p_rcv->p_log, p_physp, p_requestor_physp))
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+                 "__validate_ports_access_rights: "
+                 "port and requestor 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;
+    goto Exit;
+  }
+
+ Exit:
+  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, but with InformInfo:Subscribe set to 1.
+**********************************************************************/
+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 */
+  cl_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 151 p 782) */
+  p_resp_sa_mad->sm_key = 0;
+  p_resp_sa_mad->paylen_newwin =
+    cl_hton32( sizeof(ib_inform_info_record_t) );
+
+  p_resp_infr = (ib_inform_info_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+  /* confirm success */
+  p_resp_infr->subscribe = 1;
+
+  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 );
+}
+
+/**********************************************************************
+Recived an 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;
+  uint8_t subscribe;
+  ib_net32_t qpn;
+  uint8_t     resp_time_val;
+
+  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 );
+
+  /* the dump routine is not defined yet
+     if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+     {
+     osm_dump_inform_info_record( p_rcv->p_log,
+     p_recvd_service_rec,
+     OSM_LOG_DEBUG );
+     }
+  */
+
+  /* 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 107 : 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;
+
+  /* HACK: enum is always 0 */
+  inform_info_rec.inform_record.subscriber_enum = 0;
+
+  /* update the subscriber GID according to mad address */
+  inform_info_rec.inform_record.subscriber_gid =
+    osm_get_gid_by_mad_addr( p_rcv->p_log, p_rcv->p_subn, &p_madw->mad_addr );
+
+  /*
+   * MODIFICATIONS DONE ON INCOMING REQUEST:
+   *
+   * QPN:
+   * internally we keep the QPN field of the InformInfo updated
+   * so we can compare simply the entire record - when finding such.
+   * The Spec only require to fill the QPN field when an un-subscribe
+   * Set(InformInfo) is done. See table 106 p 654 QPN field
+   *
+   * SUBSCRIBE:
+   * For similar reasons we change the subscribe to 0 on the
+   * inserted/searched data
+   */
+
+  subscribe = p_recvd_inform_info->subscribe;
+  if (subscribe)
+  {
+    inform_info_rec.inform_record.inform_info.subscribe = 0;
+    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: "
+             "Got 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: "
+             "Got UnSubscribe Request with QPN: 0x%06X.\n",
+             cl_ntoh32(qpn)
+             );
+  }
+
+  /* If Record exist 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 = 1 */
+  if (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: "
+               "Fail 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: "
+                 "Fail 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 Un-Subscribe 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: "
+               "Fail to Un-Subscribe to non exiting 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 );
+  return;
+}
+
+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;
+  ib_net16_t sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+
+  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 );
+
+  switch (p_sa_mad->method)
+  {
+  case IB_MAD_METHOD_SET:
+    osm_infr_rcv_process_set_method(p_rcv, p_madw);
+    break;
+  default:
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "osm_infr_rcv_process: "
+             "Bad Method (%s)\n", ib_get_sa_method_str( p_sa_mad->method ));
+    osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status);
+    break;
+  }
+
+  /* Exit: */
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return;
+}
+
+
diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_informinfo_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_informinfo_ctrl.c
new file mode 100644 (file)
index 0000000..b2cc818
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_sa_informinfo_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+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 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_rcv_ctrl_construct(
+  IN osm_infr_rcv_ctrl_t* const p_ctrl )
+{
+  cl_memclr( p_ctrl, sizeof(*p_ctrl) );
+  p_ctrl->h_disp = 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_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;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_log );
+  return( status );
+}
+
diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_lft_record.c b/trunk/ulp/opensm/user/opensm/osm_sa_lft_record.c
new file mode 100644 (file)
index 0000000..ed3894e
--- /dev/null
@@ -0,0 +1,516 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_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 )
+{
+  cl_memclr( p_rcv, 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 )
+             );
+  }
+
+  cl_memclr( &p_rec_item->rec, 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);
+    CL_PLOCK_RELEASE(p_rcv->p_lock);
+    return 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;
+  uint16_t                  sw_max_lid_ho, lids_per_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: "
+             "Fail to find Port by Node Guid:0x%016" PRIx64
+             ".\n",
+             cl_ntoh64( p_sw->p_node->node_info.node_guid )
+             );
+    return;
+  }
+
+  /* get the port 0 of the switch */
+  osm_port_get_lid_range_ho( p_port, &min_lid_ho, &max_lid_ho );
+
+  /* check that the requestor 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: "
+             "Fail 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;
+
+  /* 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 possible */
+    min_block = 0;
+    sw_max_lid_ho = osm_switch_get_max_lid_ho( p_sw );
+    lids_per_block = osm_fwd_tbl_get_lids_per_block( osm_switch_get_fwd_tbl_ptr( p_sw ) );
+    max_block = (max_lid_ho + lids_per_block - 1)/lids_per_block;
+  }
+
+  /* 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;
+  osm_physp_t*              p_req_physp;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_lftr_rcv_process );
+
+  CL_ASSERT( p_rcv );
+  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 );
+
+  /* update the requestor 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 requestor physical port. \n" );
+    goto Exit;
+  }
+
+  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_SA_MAD_STATUS_REQ_INVALID);
+    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 SubAdmGet 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_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.
+  */
+
+  cl_memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method = (uint8_t)(p_resp_sa_mad->method | 0x80);
+  /* C15-0.1.5 - always return SM_Key = 0 (table 151 p 782) */
+  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/trunk/ulp/opensm/user/opensm/osm_sa_lft_record_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_lft_record_ctrl.c
new file mode 100644 (file)
index 0000000..e60dd05
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_sa_link_record.c b/trunk/ulp/opensm/user/opensm/osm_sa_link_record.c
new file mode 100644 (file)
index 0000000..8c6827b
--- /dev/null
@@ -0,0 +1,813 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_rcv, 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%\n"
+             "\t\t\t\tTo port   0x%\n"
+             "\t\t\t\tFrom lid  0x%\n"
+             "\t\t\t\tTo lid    0x%\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_lid_range(
+  IN const osm_physp_t*    p_physp,
+  OUT uint16_t *p_base_lid,
+  OUT uint16_t *p_max_lid)
+{
+  uint8_t lmc;
+
+  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))
+        );
+    *p_max_lid = *p_base_lid;
+  }
+  else
+  {
+    *p_base_lid =
+      cl_ntoh16(osm_physp_get_base_lid(p_physp));
+    lmc = osm_physp_get_lmc( p_physp );
+    *p_max_lid = (uint16_t)(*p_base_lid + (1<<lmc) - 1);
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+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               from_max_lid_ho;
+  ib_net16_t               to_max_lid_ho;
+  ib_net16_t               to_base_lid_ho;
+  uint16_t                 i, j;
+
+  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_src_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 Requestor 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: "
+             "Requestor 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 );
+  }
+
+  if( comp_mask & IB_LR_COMPMASK_FROM_LID )
+  {
+    from_max_lid_ho = from_base_lid_ho =
+      cl_ntoh16(p_lr->from_lid);
+  }else
+  {
+    __get_lid_range(p_src_physp, &from_base_lid_ho,
+                    &from_max_lid_ho);
+  }
+
+  if( comp_mask & IB_LR_COMPMASK_TO_LID )
+  {
+    to_max_lid_ho = to_base_lid_ho =
+      cl_ntoh16(p_lr->to_lid);
+  }else
+  {
+    __get_lid_range(p_dest_physp, &to_base_lid_ho,
+                    &to_max_lid_ho);
+  }
+
+  for(i=from_base_lid_ho; i<= from_max_lid_ho; i++)
+  {
+    for(j=to_base_lid_ho; j<= to_max_lid_ho; j++)
+      __osm_lr_rcv_build_physp_link(p_rcv, cl_ntoh16(i), cl_ntoh16(j),
+                                    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 );
+          __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 );
+          __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 );
+          __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 );
+          __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 );
+          __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 = cl_ptr_vector_at( &p_rcv->p_subn->port_lid_tbl,
+                               cl_ntoh16(p_lr->from_lid),
+                               (void**)pp_src_port );
+
+    if( ( (status != CL_SUCCESS) || (*pp_src_port == NULL) ) &&
+          (p_sa_mad->method == IB_MAD_METHOD_GET) )
+    {
+      /*
+        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 = cl_ptr_vector_at( &p_rcv->p_subn->port_lid_tbl,
+                               cl_ntoh16(p_lr->to_lid),
+                               (void**)pp_dest_port );
+
+    if( ( (status != CL_SUCCESS) || (*pp_dest_port == NULL) ) &&
+          (p_sa_mad->method == IB_MAD_METHOD_GET) )
+    {
+      /*
+        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 SubAdmGet 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: "
+             "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_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 %u 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 */
+  cl_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 151 p 782) */
+  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;
+    cl_memclr( p_resp_lr, 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 = NULL;
+  const osm_port_t*        p_dest_port = NULL;
+  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 );
+
+  /* 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_SA_MAD_STATUS_REQ_INVALID);
+    goto Exit;
+  }
+
+  CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_LINK_RECORD );
+
+  /* update the requestor 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 requestor 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 )
+  {
+    cl_plock_release( p_rcv->p_lock );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+    goto Exit;
+  }
+
+  __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/trunk/ulp/opensm/user/opensm/osm_sa_link_record_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_link_record_ctrl.c
new file mode 100644 (file)
index 0000000..05706a6
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <complib/cl_memory.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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_sa_mad_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_mad_ctrl.c
new file mode 100644 (file)
index 0000000..278e5ce
--- /dev/null
@@ -0,0 +1,627 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <complib/cl_memory.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_get
+ * NAME
+ * __osm_sa_mad_ctrl_process_get
+ *
+ * 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 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:%u[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;
+
+  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).\n",
+               CL_STATUS_MSG( status ) );
+
+      osm_mad_pool_put( p_ctrl->p_mad_pool, p_madw );
+      goto Exit;
+    }
+  }
+  else
+  {
+    /*
+      There is a known 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 is 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 151: SA Header - p782
+   * 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:
+  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: "
+             "Not yet implemented Method=<0x%X> Attribute=<0x%X>",
+             p_sa_mad->method,p_sa_mad->attr_id);
+    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 );
+  CL_ASSERT( p_madw->resp_expected == TRUE);
+
+  /*
+    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 );
+  cl_memclr( p_ctrl, 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.  Call unbind first. " );
+    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. Call bind first.\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/trunk/ulp/opensm/user/opensm/osm_sa_mcmember_record.c b/trunk/ulp/opensm/user/opensm/osm_sa_mcmember_record.c
new file mode 100644 (file)
index 0000000..5d72941
--- /dev/null
@@ -0,0 +1,2251 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.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;
+} osm_sa_mcmr_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcmr_rcv_construct(
+  IN osm_mcmr_recv_t* const p_rcv )
+{
+  cl_memclr( p_rcv, sizeof(*p_rcv) );
+  cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcmr_rcv_destroy(
+  IN osm_mcmr_recv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_mcmr_rcv_destroy );
+
+  CL_ASSERT( p_rcv );
+  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: "
+             "Error Init of qlock pool (%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 (cl_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 MCGROUP 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)
+{
+  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 empty MCGroups table - at 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 *)cl_zalloc(sizeof(uint8_t)*max_num_mlids);
+  /* 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;
+  }
+  cl_free(used_mlids_array);
+ Exit:
+  OSM_LOG_EXIT(p_rcv->p_log);
+  return cl_hton16(mlid);
+}
+
+/*********************************************************************
+This procedure is only invoked to cleanup 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
+requestor 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 requestor_gid;
+
+  /* set the proxy_join if the requestor gid is not identical to the
+     joined gid */
+  requestor_gid = osm_get_gid_by_mad_addr( p_rcv->p_log,
+                                           p_rcv->p_subn,
+                                           p_mad_addr );
+
+  if (! cl_memcmp(&p_recvd_mcmember_rec->port_gid, &requestor_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 requestor 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 */
+  cl_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 = (uint8_t)(p_resp_sa_mad->method | 0x80);
+  }
+  else
+  {
+    CL_ASSERT( p_resp_sa_mad->method == 0);
+  }
+
+  /* C15-0.1.5 - always return SM_Key = 0 (table 151 p 782) */
+  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 |= 2<<6; /* exactly */
+  p_resp_mcmember_rec->rate |=  2<<6; /* exactly */
+  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: \n"
+             "for TID = <0x%"PRIx64">\n", 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;
+}
+
+/**********************************************************************
+ * 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;
+
+  portguid = p_recvd_mcmember_rec->port_gid.unicast.interface_id;
+
+  *pp_mcm_port = NULL;
+
+  /* o15-0.2.1 : If this is a new port adding - 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 mgroup\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 requestor GID == PortGID */
+    request_gid = osm_get_gid_by_mad_addr(p_rcv->p_log,
+                                          p_rcv->p_subn,
+                                          p_mad_addr );
+
+    if (cl_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
+       requestor 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 mgroup\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 JoinState\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 o16.0.1.6:
+ * 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 133:
+ *
+ * 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 */
+  cl_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) == 0x02) ) {
+    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;
+  }
+
+  /*
+   * 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 mgroup 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)
+{
+  uint8_t mtu_sel;
+  uint8_t mtu_required;
+  uint8_t rate_sel;
+  uint8_t rate_required;
+  osm_log_t *p_log = p_rcv->p_log;
+
+  OSM_LOG_ENTER( p_rcv->p_log,  __mgrp_request_is_realizable);
+
+  /*
+   * End of o15-0.1.6 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.
+   */
+  if (! (comp_mask & IB_MCR_COMPMASK_MTU))
+  {
+    p_mcm_rec->mtu = p_rcv->p_subn->min_ca_mtu;
+  }
+  else
+  {
+    /* we need to select an MTU based on the requested MTU and selector */
+    if ( comp_mask & IB_MCR_COMPMASK_MTU_SEL)
+    {
+      mtu_sel = (uint8_t)(p_mcm_rec->mtu >> 6);
+    } 
+    else 
+    {
+      /* by default we assume an exact mtu is requested */
+      mtu_sel = 2; 
+    }
+    
+    /* Clearing last 2 bits */
+    mtu_required = (uint8_t)(p_mcm_rec->mtu & 0x3F);
+
+    switch (mtu_sel)
+    {
+    case 0: /* Greater than MTU specified */
+      /* we provide the largest MTU possible if we can */
+      if (mtu_required < p_rcv->p_subn->min_ca_mtu)
+      {
+        p_mcm_rec->mtu = p_rcv->p_subn->min_ca_mtu;
+      } 
+      else
+      {
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__mgrp_request_is_realizable: "
+                 "Requested MTU %x >= the maximal possible:%x \n",
+                 mtu_required, p_rcv->p_subn->min_ca_mtu);
+        return FALSE;
+      }
+      break;
+    case 1: /* Less than MTU specified */
+      /* if the requested MTU is not already the minimal we just
+         use one lower */
+      if ( mtu_required > 1 )
+      {
+        p_mcm_rec->mtu--;
+      }
+      else
+      {
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__mgrp_request_is_realizable: "
+                 "Can not obtain a lower MTU then the given one:%x\n",
+                 mtu_required);
+        return FALSE;
+      }
+      break;
+    case 2: /* Exactly MTU specified */
+      /* make sure it is in the range */
+      if ((1 > mtu_required) || (mtu_required > p_rcv->p_subn->min_ca_mtu))
+      {
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__mgrp_request_is_realizable: "
+                 "Requested MTU %x out of range: 1 .. %x \n",
+                 mtu_required, p_rcv->p_subn->min_ca_mtu);
+        return FALSE;
+      }
+      break;
+    default:
+      break;
+    }
+  }
+
+  if (! (comp_mask & IB_MCR_COMPMASK_RATE))
+  {
+    p_mcm_rec->rate = p_rcv->p_subn->min_ca_rate;
+  }
+  else
+  {
+    /* we need to select an RATE based on the requested RATE and selector */
+    if ( comp_mask & IB_MCR_COMPMASK_RATE_SEL)
+    {
+      rate_sel = (uint8_t)(p_mcm_rec->rate >> 6);
+    } 
+    else 
+    {
+      /* by default we assume an exact rate is requested */
+      rate_sel = 2; 
+    }
+    
+    /* Clearing last 2 bits */
+    rate_required = (uint8_t)(p_mcm_rec->rate & 0x3F);
+
+    switch (rate_sel)
+    {
+    case 0: /* Greater than RATE specified */
+      /* we provide the largest RATE possible if we can */
+      if (rate_required < p_rcv->p_subn->min_ca_rate)
+      {
+        p_mcm_rec->rate = p_rcv->p_subn->min_ca_rate;
+      } 
+      else
+      {
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__mgrp_request_is_realizable: "
+                 "Requested RATE %x >= the maximal possible:%x \n",
+                 rate_required, p_rcv->p_subn->min_ca_rate);
+        return FALSE;
+      }
+      break;
+    case 1: /* Less than RATE specified */
+      /* if the requested RATE is not already the minimal we just
+         use one lower */
+      if ( rate_required > 2 )
+      {
+        p_mcm_rec->rate--;
+      }
+      else
+      {
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__mgrp_request_is_realizable: "
+                 "Can not obtain a lower RATE then the given one:%x\n",
+                 rate_required);
+        return FALSE;
+      }
+      break;
+    case 2: /* Exactly RATE specified */
+      /* make sure it is in the range */
+      if ((2 > rate_required) || (rate_required > p_rcv->p_subn->min_ca_rate))
+      {
+        osm_log( p_log, OSM_LOG_DEBUG,
+                 "__mgrp_request_is_realizable: "
+                 "Requested RATE %x out of range: 2 .. %x \n",
+                 rate_required, p_rcv->p_subn->min_ca_rate);
+        return FALSE;
+      }
+      break;
+    default:
+      break;
+    }
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return TRUE;
+}
+  
+/**********************************************************************
+ 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,
+  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;
+
+  /*  copy for modifications */
+  ib_member_rec_t mcm_rec = *p_recvd_mcmember_rec;
+
+  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);
+  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: "
+           "Getting 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 = 0x02; /*  link-local scope */
+    }
+
+    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: I will be using the SA port gid for making it globally unique */
+    cl_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 */
+    cl_memcpy(&p_mgid->raw[10], &mlid, sizeof(uint16_t));
+    cl_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) == 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;
+  }
+
+  /* the mcmember_record should have mtu_sel, rate_sel and pkt_lifetime_sel = 2 */
+  (*pp_mgrp)->mcmember_rec.mtu |= 2<<6; /* exactly */
+  (*pp_mgrp)->mcmember_rec.rate |= 2<<6; /* exactly */
+  (*pp_mgrp)->mcmember_rec.pkt_life |= 2<<6; /* exactly */
+
+  /* Initialize the mgrp */
+  (*pp_mgrp)->mcmember_rec = mcm_rec;
+  (*pp_mgrp)->mcmember_rec.mlid = mlid;
+
+  /* Insert the new group in the data base */
+  
+  /* since we might have an old group by that mlid
+     one that its 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_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)
+      {
+        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
+                 );
+        /* 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;
+      }
+      else
+      {
+        /* we need to return the stored scope state */
+        mcmember_rec.scope_state = p_mcm_port->scope_state;
+
+        /* OK we can leave */
+        CL_PLOCK_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");
+
+        }
+
+        CL_PLOCK_EXCL_ACQUIRE(p_rcv->p_lock);
+        /* Note: The deletion of the mgrp itself will be done in the callback
+           for the multicast tree updating (osm_mcast_mgr_process_mgrp_cb) */
+      }
+    }
+    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 on "
+               "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: "
+             "Multicast group not present failed.\n");
+    sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+    osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status);
+    goto Exit;
+  }
+
+  CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+  /* 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: "
+             "Invalid portguid =< 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 requestor 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 requestor 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_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
+    {
+      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 "\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_PLOCK_RELEASE( p_rcv->p_lock );
+      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 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) && (join_state != 0);
+  if(!valid)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_mcmr_rcv_join_mgrp: ERR 1B12: "
+             "__validate_more_comp_fields or JoinState = 0 failed, "
+             "sending IB_SA_MAD_STATUS_REQ_INVALID.\n");
+
+    /* since we might have created the new group we need to cleanup */
+    __cleanup_mgrp(p_rcv, mlid);
+
+    CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+    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)
+    {
+      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");
+
+      CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+      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 );
+    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;
+  }
+
+  cl_memclr( &p_rec_item->rec, sizeof( p_rec_item->rec ) );
+
+  /* HACK: Not trusted requestors 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;
+
+  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) &&
+      cl_memcmp(&p_rcvd_rec->mgid, &p_mgrp->mcmember_rec.mgid, sizeof(ib_gid_t))) {
+    goto Exit;
+  }
+
+  if ((IB_MCR_COMPMASK_MLID & comp_mask) &&
+      cl_memcmp(&p_rcvd_rec->mlid, &p_mgrp->mcmember_rec.mlid, sizeof(uint16_t))) {
+    goto Exit;
+  }
+
+  /* if the requestor 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;
+
+  /*
+   * o15-0.1.16: If SA supports UD multicast, then if it receives a
+   * SubnAdmGetTable() of MCMemberRecord with the MCMemberRecord:PortGID
+   * wildcarded, then SA shall return a single MCMemberRecord for each
+   * multicast group that matches the query operation.
+   */
+
+  /* so did we got 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;
+    }
+    else
+    {
+      /* port not in group */
+      goto Exit;
+    }
+  }
+  else
+  {
+    /* point to the group information */
+    scope_state = p_mgrp->mcmember_rec.scope_state;
+  }
+
+  /* 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_SCOPE & comp_mask)
+    scope_state_mask = 0xF0;
+
+  if (IB_MCR_COMPMASK_JOIN_STATE & comp_mask)
+    scope_state_mask = scope_state_mask | 0x0F;
+
+  if ((scope_state_mask & p_rcvd_rec->scope_state) !=
+      (scope_state_mask & scope_state)) goto Exit;
+
+  if ((IB_MCR_COMPMASK_PROXY & comp_mask) &&
+      (p_rcvd_rec->proxy_join != p_mgrp->mcmember_rec.proxy_join)) goto Exit;
+
+  /* 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;
+
+  /* add to the list */
+  match_rec = p_mgrp->mcmember_rec;
+  match_rec.scope_state = scope_state;
+
+  __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
+**********************************************************************/
+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 = TRUE;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_mcmr_query_mgrp );
+
+  CL_ASSERT( p_rcv );
+  CL_ASSERT( p_madw );
+
+  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;
+
+  CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_MCMEMBER_RECORD );
+
+  /* update the requestor 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 requestor 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;
+
+  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 SubAdmGet 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.
+  */
+
+  cl_memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method = (uint8_t)(p_resp_sa_mad->method | 0x80);
+  /* C15-0.1.5 - always return SM_Key = 0 (table 151 p 782) */
+  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 );
+
+  /*
+    p819 - 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.
+  */
+  if (p_resp_sa_mad->sm_key == 0)
+    trusted_req = FALSE;
+
+  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)
+      {
+        cl_memclr(&p_resp_rec->port_gid, 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;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_mcmr_rcv_process );
+
+  CL_ASSERT( p_rcv );
+  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 );
+
+  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, sa_status);
+    break;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return;
+
+}
diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_mcmember_record_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_mcmember_record_ctrl.c
new file mode 100644 (file)
index 0000000..7102a8b
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <complib/cl_memory.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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_sa_node_record.c b/trunk/ulp/opensm/user/opensm/osm_sa_node_record.c
new file mode 100644 (file)
index 0000000..e8a21ed
--- /dev/null
@@ -0,0 +1,618 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <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 )
+{
+  cl_memclr( p_rcv, 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_ERROR,
+             "__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 )
+             );
+  }
+
+  cl_memclr( &p_rec_item->rec, 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;
+  cl_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;
+  uint16_t              lid_ho;
+  ib_net16_t               base_lid_ho;
+  ib_net16_t               max_lid_ho;
+  uint8_t                  lmc;
+  ib_net64_t               port_guid;
+  ib_api_status_t          status;
+
+  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_ERROR,
+             "__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 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 requestor 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_ho = cl_ntoh16( osm_physp_get_base_lid( p_physp ) );
+    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_ERROR,
+                 "__osm_nr_rcv_create_nr: "
+                 "Comparing LID: 0x%X <= 0x%X <= 0x%X\n",
+                 cl_ntoh16( base_lid_ho ),
+                 cl_ntoh16( match_lid_ho ),
+                 cl_ntoh16( max_lid_ho )
+                 );
+      }
+
+      if( (match_lid_ho <= max_lid_ho) && (match_lid_ho >= base_lid_ho) )
+      {
+        /*
+          Ignore return code for now.
+        */
+        __osm_nr_rcv_new_nr( p_rcv, p_node, p_list,
+                             port_guid, match_lid );
+      }
+    }
+    else
+    {
+      /*
+        For every lid value create a Node Record.
+      */
+      for( lid_ho = base_lid_ho; lid_ho <= max_lid_ho; lid_ho++ )
+      {
+        status = __osm_nr_rcv_new_nr( p_rcv, p_node, p_list,
+                                      port_guid, cl_hton16( lid_ho ) );
+        if( status != IB_SUCCESS )
+          break;
+      }
+    }
+  }
+
+  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_ERROR,
+               "__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;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_nr_rcv_process );
+
+  CL_ASSERT( p_rcv );
+  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 );
+
+  /* update the requestor 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 requestor physical port. \n" );
+    goto Exit;
+  }
+
+  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_SA_MAD_STATUS_REQ_INVALID);
+    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 );
+
+  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 SubAdmGet 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: "
+             "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.
+  */
+
+  cl_memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method = (uint8_t)(p_resp_sa_mad->method | 0x80);
+  /* C15-0.1.5 - always return SM_Key = 0 (table 151 p 782) */
+  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/trunk/ulp/opensm/user/opensm/osm_sa_node_record_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_node_record_ctrl.c
new file mode 100644 (file)
index 0000000..a70e6b5
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <complib/cl_memory.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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_sa_path_record.c b/trunk/ulp/opensm/user/opensm/osm_sa_path_record.c
new file mode 100644 (file)
index 0000000..d75c1f9
--- /dev/null
@@ -0,0 +1,1765 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_pr_rcv_t.
+ * This object represents the PathRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.10 $
+ */
+
+/*
+  Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.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_path_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_pkey.h>
+#include <opensm/osm_multicast.h>
+
+#define OSM_PR_RCV_POOL_MIN_SIZE    64
+#define OSM_PR_RCV_POOL_GROW_SIZE      64
+
+typedef  struct   _osm_pr_item
+{
+  cl_pool_item_t     pool_item;
+  ib_path_rec_t      path_rec;
+
+} osm_pr_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;
+} osm_path_parms_t;
+
+typedef  struct   osm_sa_pr_mcmr_search_ctxt {
+  ib_gid_t        *p_mgid;
+  osm_mgrp_t      *p_mgrp;
+  osm_pr_rcv_t    *p_rcv;
+} osm_sa_pr_mcmr_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pr_rcv_construct(
+  IN osm_pr_rcv_t* const p_rcv )
+{
+  cl_memclr( p_rcv, sizeof(*p_rcv) );
+  cl_qlock_pool_construct( &p_rcv->pr_pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pr_rcv_destroy(
+  IN osm_pr_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_pr_rcv_destroy );
+  cl_qlock_pool_destroy( &p_rcv->pr_pool );
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+  ib_api_status_t status;
+
+  OSM_LOG_ENTER( p_log, osm_pr_rcv_init );
+
+  osm_pr_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_PR_RCV_POOL_MIN_SIZE,
+                               0,
+                               OSM_PR_RCV_POOL_GROW_SIZE,
+                               sizeof(osm_pr_item_t),
+                               NULL, NULL, NULL );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_pr_rcv_get_path_parms(
+  IN osm_pr_rcv_t*         const p_rcv,
+  IN const ib_path_rec_t*     const p_pr,
+  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 )
+{
+  ib_net64_t               node_guid;
+  const osm_node_t*        p_node;
+  const osm_physp_t*       p_physp;
+  const osm_physp_t*       p_dest_physp;
+  const osm_switch_t*         p_sw;
+  const ib_port_info_t*    p_pi;
+  const cl_qmap_t*         p_sw_tbl;
+
+  ib_api_status_t          status = IB_SUCCESS;
+  uint8_t                  mtu;
+  uint8_t                  rate;
+  uint8_t                  required_mtu;
+  uint8_t                  required_rate;
+  ib_net16_t               dest_lid;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_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 );
+  p_sw_tbl = &p_rcv->p_subn->sw_guid_tbl;
+
+  mtu = ib_port_info_get_mtu_cap( p_pi );
+  rate = ib_port_info_compute_rate( p_pi );
+
+  /*
+    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( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH )
+  {
+    p_sw = (osm_switch_t *)cl_qmap_get( p_sw_tbl,
+                                        osm_node_get_node_guid( p_node ) );
+
+    if( p_sw == (osm_switch_t *)cl_qmap_end( p_sw_tbl ) )
+    {
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+    /*
+     * 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_sw, cl_ntoh16(dest_lid_ho) );
+    if ( p_physp == 0 )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_pr_rcv_get_path_parms: ERR 1F02: "
+               "Cannot 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( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH )
+  {
+    p_sw = (osm_switch_t *)cl_qmap_get( p_sw_tbl,
+                                        osm_node_get_node_guid(p_node));
+
+    if( p_sw == (osm_switch_t *)cl_qmap_end( p_sw_tbl ) )
+    {
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+    p_dest_physp = osm_switch_get_route_by_lid( p_sw,
+                                                cl_ntoh16(dest_lid_ho) );
+
+    if ( p_dest_physp == 0 )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_pr_rcv_get_path_parms: ERR 1F03: "
+               "Cannot 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_pr_rcv_get_path_parms: ERR 1F05: "
+               "Cannot 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;
+    }
+
+    /*
+      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( osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH )
+    {
+      /*
+        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_pr_rcv_get_path_parms: ERR 1F06: "
+               "Internal error, bad path.\n" );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+    node_guid = osm_node_get_node_guid( p_node );
+    p_sw = (osm_switch_t*)cl_qmap_get( p_sw_tbl, node_guid );
+
+    if( p_sw == (osm_switch_t*)cl_qmap_end( p_sw_tbl ) )
+    {
+      /*
+        There is some sort of problem in the subnet object!
+      */
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_pr_rcv_get_path_parms: ERR 1F04: "
+               "Internal error, no switch for guid 0x%016" PRIx64 ".\n",
+               cl_ntoh64( node_guid ) );
+      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_pr_rcv_get_path_parms: "
+                 "New smallest MTU = %u at intervening port 0x%016" PRIx64 ".\n",
+                 mtu,
+                 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_pr_rcv_get_path_parms: "
+                 "New smallest rate = %u at intervening port 0x%016" PRIx64 ".\n",
+                 rate,
+                 osm_physp_get_port_guid( p_physp ) );
+      }
+    }
+
+    /*
+      Continue with the egress port on this switch.
+    */
+    p_physp = osm_switch_get_route_by_lid( p_sw, dest_lid );
+
+    if ( p_physp == 0 )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_pr_rcv_get_path_parms: ERR 1F07: "
+               "Dead end on path to lid:0x%X from switch for guid 0x%016" PRIx64 ".\n",
+               dest_lid_ho,
+               cl_ntoh64( node_guid ) );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+    CL_ASSERT( p_physp );
+    CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+    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_pr_rcv_get_path_parms: "
+                 "New smallest MTU = %u at intervening port 0x%016" PRIx64 ".\n",
+                 mtu,
+                 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_pr_rcv_get_path_parms: "
+                 "New smallest rate = %u at intervening port 0x%016" PRIx64 ".\n",
+                 rate,
+                 osm_physp_get_port_guid( 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_pr_rcv_get_path_parms: "
+               "New smallest MTU = %u at destination port 0x%016" PRIx64 ".\n",
+               mtu,
+               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_pr_rcv_get_path_parms: "
+               "New smallest rate = %u at destination port 0x%016"   PRIx64 ".\n",
+               rate,
+               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_pr_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_PR_COMPMASK_MTUSELEC) &&
+      (comp_mask & IB_PR_COMPMASK_MTU))
+  {
+    required_mtu = ib_path_rec_mtu( p_pr );
+    switch( ib_path_rec_mtu_sel( p_pr ) )
+    {
+    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 )
+        status = IB_NOT_FOUND;
+      break;
+
+    case 2:    /* exact match */
+      if( mtu != required_mtu )
+        status = IB_NOT_FOUND;
+      break;
+
+    case 3:    /* largest available */
+      /* can't be disqualified by this one */
+      break;
+
+    default:
+      /* if we're here, there's a bug in ib_path_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_PR_COMPMASK_RATESELEC) &&
+      (comp_mask & IB_PR_COMPMASK_RATE))
+  {
+    required_rate = ib_path_rec_rate( p_pr );
+    switch( ib_path_rec_rate_sel( p_pr ) )
+    {
+    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 )
+        status = IB_NOT_FOUND;
+      break;
+
+    case 2:    /* exact match */
+      if( rate != required_rate )
+        status = IB_NOT_FOUND;
+      break;
+
+    case 3:    /* largest available */
+      /* can't be disqualified by this one */
+      break;
+
+    default:
+      /* if we're here, there's a bug in ib_path_rec_mtu_sel() */
+      CL_ASSERT( FALSE );
+      status = IB_ERROR;
+      break;
+    }
+  }
+
+  p_parms->mtu = mtu;
+  p_parms->rate = rate;
+  p_parms->pkey = IB_DEFAULT_PKEY;
+  p_parms->pkt_life = OSM_DEFAULT_SUBNET_TIMEOUT;
+  p_parms->sl = OSM_DEFAULT_SL;
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pr_rcv_build_pr(
+  IN osm_pr_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_pr_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->pkey = p_parms->pkey;
+  p_pr->sl = p_parms->sl;
+  p_pr->mtu = (uint8_t)(p_parms->mtu | 0x80);
+  p_pr->rate = (uint8_t)(p_parms->rate | 0x80);
+
+  /* According to spec definition Table 171 PacketLifeTime description,
+     for loopback paths, packetLifeTime shall be zero. */
+  if ( p_src_port == p_dest_port )
+    /* This is loopback */
+    p_pr->pkt_life = 0x80;
+  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 */
+  if (p_parms->reversible) p_pr->num_path = 0x80;
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
+
+/**********************************************************************
+ **********************************************************************/
+static osm_pr_item_t*
+__osm_pr_rcv_get_lid_pair_path(
+  IN osm_pr_rcv_t*         const p_rcv,
+  IN const ib_path_rec_t*  const p_pr,
+  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_pr_item_t            *p_pr_item;
+  ib_api_status_t       status, rev_path_status;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_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_pr_rcv_get_lid_pair_path: "
+             "Src LID 0x%X, Dest LID 0x%X.\n",
+             src_lid_ho, dest_lid_ho );
+  }
+
+  p_pr_item = (osm_pr_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_pr_rcv_get_lid_pair_path: ERR 1F01: "
+             "Unable to allocate path record.\n" );
+    goto Exit;
+  }
+
+  status = __osm_pr_rcv_get_path_parms( p_rcv, p_pr, 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_pr_rcv_get_path_parms(
+      p_rcv, p_pr, 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_PR_COMPMASK_REVERSIBLE)
+    if ( (! path_parms.reversible && (p_pr->num_path & 0x80)))
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+               "__osm_pr_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;
+    };
+
+  __osm_pr_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 void
+__osm_pr_rcv_get_port_pair_paths(
+  IN osm_pr_rcv_t*         const p_rcv,
+  IN const ib_path_rec_t*     const p_pr,
+  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 ib_net64_t         comp_mask,
+  IN cl_qlist_t*           const p_list )
+{
+  osm_pr_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;
+  uint8_t                  preference;
+  uintn_t                  iterations;
+  uintn_t                  src_offset;
+  uintn_t                  dest_offset;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_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_pr_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 don't share a pkey - the path is disqualified.
+       Exit */
+    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 redundent 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 dispurse 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.
+  */
+
+  /*
+    Refine our search if the client specified end-point LIDs
+  */
+  if( comp_mask & IB_PR_COMPMASK_DLID )
+  {
+    dest_lid_min_ho = cl_ntoh16( p_pr->dlid );
+    dest_lid_max_ho = cl_ntoh16( p_pr->dlid );
+  }
+  else
+  {
+    osm_port_get_lid_range_ho( p_dest_port, &dest_lid_min_ho,
+                               &dest_lid_max_ho );
+  }
+
+  if( comp_mask & IB_PR_COMPMASK_SLID )
+  {
+    src_lid_min_ho = cl_ntoh16( p_pr->slid );
+    src_lid_max_ho = cl_ntoh16( p_pr->slid );
+  }
+  else
+  {
+    osm_port_get_lid_range_ho( p_src_port, &src_lid_min_ho,
+                               &src_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_pr_rcv_get_port_pair_paths: "
+             "Src LIDs [0x%X,0x%X], "
+             "Dest LIDs [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;
+  path_num = 0;
+
+  if( comp_mask & IB_PR_COMPMASK_NUMBPATH )
+    iterations = p_pr->num_path & 0x7F;
+  else
+    iterations = (uintn_t)(-1);
+
+  while( path_num < iterations )
+  {
+    /*
+      These paths are "fully redundant"
+    */
+
+    p_pr_item = __osm_pr_rcv_get_lid_pair_path( p_rcv, p_pr,
+                                                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 user cares to see.
+  */
+  if( path_num == iterations )
+    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 < iterations )
+  {
+    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_pr_rcv_get_lid_pair_path( p_rcv, p_pr,
+                                                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 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_net16_t
+__osm_pr_rcv_get_end_points(
+  IN osm_pr_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_path_rec_t*     p_pr;
+  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_pr_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_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+  comp_mask = p_sa_mad->comp_mask;
+
+  /*
+    Check a few easy disqualifying cases up front before getting
+    into the endpoints.
+  */
+
+  if( comp_mask & IB_PR_COMPMASK_PKEY )
+  {
+    if( p_pr->pkey != IB_DEFAULT_PKEY )
+    {
+      if ( p_sa_mad->method == IB_MAD_METHOD_GET )
+        sa_status = IB_SA_MAD_STATUS_NO_RECORDS;
+      *pp_src_port = 0;
+      *pp_dest_port = 0;
+      goto Exit;
+    }
+  }
+
+  if( comp_mask & IB_PR_COMPMASK_SL )
+  {
+    if( p_pr->sl != OSM_DEFAULT_SL )
+    {
+      if ( p_sa_mad->method == IB_MAD_METHOD_GET )
+        sa_status = IB_SA_MAD_STATUS_NO_RECORDS;
+      *pp_src_port = 0;
+      *pp_dest_port = 0;
+      goto Exit;
+    }
+  }
+
+  if( p_sa_mad->comp_mask & IB_PR_COMPMASK_SGID )
+  {
+    *pp_src_port = (osm_port_t*)cl_qmap_get(
+      &p_rcv->p_subn->port_guid_tbl,
+      p_pr->sgid.unicast.interface_id );
+
+    if( *pp_src_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_VERBOSE,
+               "__osm_pr_rcv_get_end_points: "
+               "No source port with GUID = 0x%016" PRIx64 ".\n",
+               cl_ntoh64( p_pr->sgid.unicast.interface_id) );
+
+      sa_status = IB_SA_MAD_STATUS_INVALID_GID;
+      goto Exit;
+    }
+  }
+  else
+  {
+    *pp_src_port = 0;
+    if( p_sa_mad->comp_mask & IB_PR_COMPMASK_SLID )
+    {
+      status = cl_ptr_vector_at( &p_rcv->p_subn->port_lid_tbl,
+                                 cl_ntoh16(p_pr->slid), (void**)pp_src_port );
+
+      if( ( (status != CL_SUCCESS) || (*pp_src_port == NULL) ) &&
+          (p_sa_mad->method == IB_MAD_METHOD_GET) )
+      {
+        /*
+          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_pr_rcv_get_end_points: "
+                 "No source port with LID = 0x%X.\n",
+                 cl_ntoh16( p_pr->slid) );
+
+        sa_status = IB_SA_MAD_STATUS_NO_RECORDS;
+        goto Exit;
+      }
+    }
+  }
+
+  if( p_sa_mad->comp_mask & IB_PR_COMPMASK_DGID )
+  {
+    *pp_dest_port = (osm_port_t*)cl_qmap_get(
+      &p_rcv->p_subn->port_guid_tbl,
+      p_pr->dgid.unicast.interface_id );
+
+    if( *pp_dest_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_VERBOSE,
+               "__osm_pr_rcv_get_end_points: "
+               "No dest port with GUID = 0x%016" PRIx64 ".\n",
+               cl_ntoh64( p_pr->dgid.unicast.interface_id) );
+
+      sa_status = IB_SA_MAD_STATUS_INVALID_GID;
+      goto Exit;
+    }
+  }
+  else
+  {
+    *pp_dest_port = 0;
+    if( p_sa_mad->comp_mask & IB_PR_COMPMASK_DLID )
+    {
+      status = cl_ptr_vector_at( &p_rcv->p_subn->port_lid_tbl,
+                                 cl_ntoh16(p_pr->dlid),  (void**)pp_dest_port );
+
+      if( ( (status != CL_SUCCESS) || (*pp_dest_port == NULL) ) &&
+          (p_sa_mad->method == IB_MAD_METHOD_GET) )
+      {
+        /*
+          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_pr_rcv_get_end_points: "
+                 "No dest port with LID = 0x%X.\n",
+                 cl_ntoh16( p_pr->dlid) );
+
+        sa_status = IB_SA_MAD_STATUS_NO_RECORDS;
+        goto Exit;
+      }
+    }
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( sa_status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pr_rcv_process_world(
+  IN osm_pr_rcv_t*         const p_rcv,
+  IN const ib_path_rec_t*     const p_pr,
+  IN const osm_port_t*     const requestor_port,
+  IN const ib_net64_t         comp_mask,
+  IN cl_qlist_t*           const p_list )
+{
+  const cl_qmap_t*         p_tbl;
+  const osm_port_t*        p_dest_port;
+  const osm_port_t*        p_src_port;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_process_world );
+
+  /*
+    Iterate the entire port space over itself.
+    A path record from a port to itself is legit, so no
+    need for a special case there.
+
+    We compute both A -> B and B -> A, since we don't have
+    any check to determine the reversability of the paths.
+  */
+  p_tbl = &p_rcv->p_subn->port_guid_tbl;
+
+  p_dest_port = (osm_port_t*)cl_qmap_head( p_tbl );
+  while( p_dest_port != (osm_port_t*)cl_qmap_end( p_tbl ) )
+  {
+    p_src_port = (osm_port_t*)cl_qmap_head( p_tbl );
+    while( p_src_port != (osm_port_t*)cl_qmap_end( p_tbl ) )
+    {
+      __osm_pr_rcv_get_port_pair_paths( p_rcv, p_pr, requestor_port, p_src_port,
+                                        p_dest_port, comp_mask, p_list );
+
+      p_src_port = (osm_port_t*)cl_qmap_next( &p_src_port->map_item );
+    }
+
+    p_dest_port = (osm_port_t*)cl_qmap_next( &p_dest_port->map_item );
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pr_rcv_process_half(
+  IN osm_pr_rcv_t*         const p_rcv,
+  IN const ib_path_rec_t*     const p_pr,
+  IN const osm_port_t*     const requestor_port,
+  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,
+  IN cl_qlist_t*           const p_list )
+{
+  const cl_qmap_t*         p_tbl;
+  const osm_port_t*        p_port;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_process_half );
+
+  /*
+    Iterate over every port, looking for matches...
+    A path record from a port to itself is legit, so no
+    need to special case that one.
+  */
+  p_tbl = &p_rcv->p_subn->port_guid_tbl;
+
+  if( p_src_port )
+  {
+    /*
+      The src port if fixed, so iterate over destination ports.
+    */
+    p_port = (osm_port_t*)cl_qmap_head( p_tbl );
+    while( p_port != (osm_port_t*)cl_qmap_end( p_tbl ) )
+    {
+      __osm_pr_rcv_get_port_pair_paths( p_rcv, p_pr, requestor_port, p_src_port,
+                                        p_port, comp_mask, p_list );
+      p_port = (osm_port_t*)cl_qmap_next( &p_port->map_item );
+    }
+  }
+  else
+  {
+    /*
+      The dest port if fixed, so iterate over source ports.
+    */
+    p_port = (osm_port_t*)cl_qmap_head( p_tbl );
+    while( p_port != (osm_port_t*)cl_qmap_end( p_tbl ) )
+    {
+      __osm_pr_rcv_get_port_pair_paths( p_rcv, p_pr, requestor_port, p_port,
+                                        p_dest_port, comp_mask, p_list );
+      p_port = (osm_port_t*)cl_qmap_next( &p_port->map_item );
+    }
+  }
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pr_rcv_process_pair(
+  IN osm_pr_rcv_t*         const p_rcv,
+  IN const ib_path_rec_t*     const p_pr,
+  IN const osm_port_t*     const requestor_port,
+  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,
+  IN cl_qlist_t*           const p_list )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_process_pair );
+
+  __osm_pr_rcv_get_port_pair_paths( p_rcv, p_pr, requestor_port, p_src_port,
+                                    p_dest_port, comp_mask, p_list );
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ *********************************************************************/
+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_pr_mcmr_search_ctxt_t *p_ctxt = (osm_sa_pr_mcmr_search_ctxt_t *) context;
+  const ib_gid_t        *p_recvd_mgid;
+  osm_pr_rcv_t *p_rcv;
+  /*  uint32_t  i; */
+
+  p_recvd_mgid = p_ctxt->p_mgid;
+  p_rcv = p_ctxt->p_rcv;
+
+  /* Why not compare the entire MGID ???? */
+  /* different scope can sneak in for the same MGID ? */
+  /* EZ: I changed it to full compare ! */
+  if (cl_memcmp(&p_mgrp->mcmember_rec.mgid,
+                p_recvd_mgid,
+                sizeof(ib_gid_t)))
+    return;
+
+#if 0
+  for ( i = 0 ; i < sizeof(p_mgrp->mcmember_rec.mgid.multicast.raw_group_id); i++)
+  {
+    if (p_mgrp->mcmember_rec.mgid.multicast.raw_group_id[i] !=
+        p_recvd_mgid->mgid.multicast.raw_group_id[i])
+      return;
+  }
+#endif
+
+  if(p_ctxt->p_mgrp)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__search_mgrp_by_mgid: ERR 1F08: "
+             "Multiple MCGROUP for same MGID.\n" );
+    return;
+  }
+  p_ctxt->p_mgrp = p_mgrp;
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__get_mgrp_by_mgid(
+  IN osm_pr_rcv_t* const p_rcv,
+  IN ib_path_rec_t* p_recvd_path_rec,
+  OUT osm_mgrp_t **pp_mgrp)
+{
+  osm_sa_pr_mcmr_search_ctxt_t mcmr_search_context;
+
+  mcmr_search_context.p_mgid = &p_recvd_path_rec->dgid;
+  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;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static
+osm_mgrp_t *
+__get_mgrp_by_mlid(
+  IN const osm_pr_rcv_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;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pr_get_mgrp(
+  IN osm_pr_rcv_t*         const p_rcv,
+  IN const osm_madw_t*     const p_madw,
+  OUT osm_mgrp_t           **pp_mgrp )
+{
+  ib_path_rec_t*           p_pr;
+  const ib_sa_mad_t*       p_sa_mad;
+  ib_net64_t               comp_mask;
+  ib_api_status_t          status;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_get_mgrp );
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+  comp_mask = p_sa_mad->comp_mask;
+
+  if( comp_mask & IB_PR_COMPMASK_DGID )
+  {
+    status = __get_mgrp_by_mgid( p_rcv, p_pr, pp_mgrp );
+    if( status != IB_SUCCESS )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_pr_get_mgrp: ERR 1F09: "
+               "No MC group found for PathRecord destination GID.\n" );
+      goto Exit;
+    }
+  }
+
+  if( comp_mask & IB_PR_COMPMASK_DLID )
+  {
+    if( *pp_mgrp)
+    {
+      /* check that the MLID in the MC group is */
+      /* the same as the DLID in the PathRecord */
+      if( (*pp_mgrp)->mlid != p_pr->dlid )
+      {
+       /* Note: perhaps this might be better indicated as an invalid request */
+        osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                 "__osm_pr_get_mgrp: ERR 1F10: "
+                 "MC group MLID does not match PathRecord destination LID.\n" );
+        *pp_mgrp = NULL;
+        goto Exit;
+      }
+    }
+    else
+    {
+      *pp_mgrp = __get_mgrp_by_mlid( p_rcv, p_pr->dlid );
+      if( *pp_mgrp == NULL)
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                 "__osm_pr_get_mgrp: ERR 1F11: "
+                 "No MC group found for PathRecord destination LID.\n" );
+      }
+    }
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_pr_match_mgrp_attributes(
+  IN osm_pr_rcv_t*         const p_rcv,
+  IN const osm_madw_t*     const p_madw,
+  IN const osm_mgrp_t*     const p_mgrp )
+{
+  const ib_path_rec_t*     p_pr;
+  const ib_sa_mad_t*       p_sa_mad;
+  ib_net64_t               comp_mask;
+  ib_api_status_t          status = IB_ERROR;
+  uint32_t                 flow_label;
+  uint8_t                  sl;
+  uint8_t                  hop_limit;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_match_mgrp_attributes );
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+  comp_mask = p_sa_mad->comp_mask;
+
+  /* If SGID and/or SLID specified, should validate as part of MC group */
+  /* Also, not checking MTU, rate, packet lifetime, and raw traffic currently */
+  if( comp_mask & IB_PR_COMPMASK_PKEY )
+  {
+    if( p_pr->pkey != p_mgrp->mcmember_rec.pkey )
+      goto Exit;
+  }
+
+  ib_member_get_sl_flow_hop( p_mgrp->mcmember_rec.sl_flow_hop,
+                             &sl, &flow_label, &hop_limit );
+
+  if( comp_mask & IB_PR_COMPMASK_SL )
+  {
+    if( ( p_pr->sl & 0xf ) != sl )
+      goto Exit;
+  }
+
+  if( comp_mask & IB_PR_COMPMASK_NUMBPATH )
+  {
+    if( ( p_pr->num_path & 0x7f ) == 0 )
+      goto Exit;
+  }
+
+  if( comp_mask & IB_PR_COMPMASK_FLOWLABEL )
+  {
+    if( ib_path_rec_flow_lbl( p_pr ) != flow_label )
+      goto Exit;
+  }
+
+  if( comp_mask & IB_PR_COMPMASK_HOPLIMIT )
+  {
+    if( ib_path_rec_hop_limit( p_pr ) != hop_limit )
+      goto Exit;
+  }
+
+  if( comp_mask & IB_PR_COMPMASK_TCLASS )
+  {
+    if( p_pr->tclass != p_mgrp->mcmember_rec.tclass )
+      goto Exit;
+  }
+
+  status = IB_SUCCESS;
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+__osm_pr_rcv_check_mcast_dest(
+  IN osm_pr_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;
+  ib_net64_t               comp_mask;
+  boolean_t                is_multicast = FALSE;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_check_mcast_dest );
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+  comp_mask = p_sa_mad->comp_mask;
+
+  if( comp_mask & IB_PR_COMPMASK_DGID )
+  {
+    is_multicast = ib_gid_is_multicast( &p_pr->dgid );
+    if( is_multicast )
+      goto Exit;
+  }
+
+  if( comp_mask & IB_PR_COMPMASK_DLID )
+  {
+    if( cl_ntoh16( p_pr->dlid ) >= IB_LID_MCAST_START_HO &&
+        cl_ntoh16( p_pr->dlid ) <= IB_LID_MCAST_END_HO )
+      is_multicast = TRUE;
+    else if( is_multicast )
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_pr_rcv_check_mcast_dest: ERR 1F12: "
+               "PathRecord request indicates MGID but not MLID.\n" );
+  }
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( is_multicast );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pr_rcv_respond(
+  IN osm_pr_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_path_rec_t*           p_resp_pr;
+  ib_api_status_t          status;
+  const ib_sa_mad_t*    p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  osm_pr_item_t*        p_pr_item;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_respond );
+
+  num_rec = cl_qlist_count( p_list );
+
+  /*
+   * C15-0.1.30 :
+   * If we do a SubAdmGet 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_pr_rcv_respond: ERR 1F13: "
+             "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_pr_item = (osm_pr_item_t*)cl_qlist_remove_head( p_list );
+    while( p_pr_item != (osm_pr_item_t*)cl_qlist_end( p_list ) )
+    {
+      cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item );
+      p_pr_item = (osm_pr_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_path_rec_t);
+  if (trim_num_rec < num_rec)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+             "__osm_pr_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_pr_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_path_rec_t) + IB_SA_MAD_HDR_SIZE,
+                                  &p_madw->mad_addr );
+  if( !p_resp_madw )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_pr_rcv_respond: ERR 1F14: "
+             "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 );
+
+  cl_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 151 p 782) */
+  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_path_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_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+  if ( num_rec == 0 )
+  {
+    if (p_resp_sa_mad->method == IB_MAD_METHOD_GET_RESP)
+      p_resp_sa_mad->status = IB_SA_MAD_STATUS_NO_RECORDS;
+    cl_memclr( p_resp_pr, sizeof(*p_resp_pr) );
+  }
+  else
+  {
+    p_pr_item = (osm_pr_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_pr_item != (osm_pr_item_t*)cl_qlist_end( p_list ) )
+    {
+      /*  Copy the Path Records from the list into the MAD */
+      if (num_copied < num_rec)
+      {
+        *p_resp_pr = p_pr_item->path_rec;
+        num_copied++;
+      }
+      cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item );
+      p_resp_pr++;
+      p_pr_item = (osm_pr_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_pr_rcv_respond: ERR 1F15: "
+             "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_pr_rcv_process(
+  IN osm_pr_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;
+  const osm_port_t*        p_src_port;
+  const osm_port_t*        p_dest_port;
+  cl_qlist_t               pr_list;
+  ib_net16_t               sa_status;
+  osm_port_t*              requestor_port;
+  osm_mgrp_t*              p_mgrp = NULL;
+  ib_api_status_t          status;
+  osm_pr_item_t*           p_pr_item;
+  uint32_t                 flow_label;
+  uint8_t                  sl;
+  uint8_t                  hop_limit;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_pr_rcv_process );
+
+  CL_ASSERT( p_madw );
+
+  /* update the requestor physical port. */
+  requestor_port =
+    osm_get_port_by_mad_addr(p_rcv->p_log,
+                             p_rcv->p_subn,
+                             osm_madw_get_mad_addr_ptr(p_madw) );
+  if (requestor_port == NULL)
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_pr_rcv_process: ERR 1F16: "
+             "Cannot find requestor physical port.\n" );
+    goto Exit;
+  }
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  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_PATH_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_ERROR,
+             "osm_pr_rcv_process: ERR 1F17: " 
+             "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;
+  }
+
+  if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+    osm_dump_path_record( p_rcv->p_log, p_pr, 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 );
+
+  /* Handle multicast destinations separately */
+  if( __osm_pr_rcv_check_mcast_dest( p_rcv, p_madw ) )
+    goto McastDest;
+
+  osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+           "osm_pr_rcv_process: "
+           "Unicast destination requested.\n" );
+
+  sa_status = __osm_pr_rcv_get_end_points( p_rcv, p_madw,
+                                           &p_src_port, &p_dest_port );
+
+  if( sa_status != IB_SA_MAD_STATUS_SUCCESS )
+  {
+    cl_plock_release( p_rcv->p_lock );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+    goto Exit;
+  }
+
+  /*
+    What happens next depends on the type of endpoint information
+    that was specified....
+  */
+  if( p_src_port )
+  {
+    if( p_dest_port )
+      __osm_pr_rcv_process_pair( p_rcv, p_pr, requestor_port, p_src_port, p_dest_port,
+                                 p_sa_mad->comp_mask, &pr_list );
+    else
+      __osm_pr_rcv_process_half( p_rcv, p_pr, requestor_port, p_src_port, NULL,
+                                 p_sa_mad->comp_mask, &pr_list );
+  }
+  else
+  {
+    if( p_dest_port )
+      __osm_pr_rcv_process_half( p_rcv, p_pr, requestor_port, NULL, p_dest_port,
+                                 p_sa_mad->comp_mask, &pr_list );
+    else
+      /*
+        Katie, bar the door!
+      */
+      __osm_pr_rcv_process_world( p_rcv, p_pr, requestor_port,
+                                  p_sa_mad->comp_mask, &pr_list );
+  }
+  goto Unlock;
+
+ McastDest:
+  osm_log(p_rcv->p_log, OSM_LOG_DEBUG,
+             "osm_pr_rcv_process: "
+             "Multicast destination requested.\n" );
+
+  /* First, get the MC info */
+  __osm_pr_get_mgrp( p_rcv, p_madw, &p_mgrp );
+
+  if ( p_mgrp )
+  {
+    /* Make sure the rest of the PathRecord matches the MC group attributes */
+    status = __osm_pr_match_mgrp_attributes( p_rcv, p_madw, p_mgrp);
+    if ( status == IB_SUCCESS )
+    {
+      p_pr_item = (osm_pr_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_pr_rcv_process: ERR 1F18: "
+                 "Unable to allocate path record for MC group.\n" );
+      }
+      else
+      {
+       /* Copy PathRecord request into response */
+        p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+        p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+        p_pr_item->path_rec = *p_pr;
+
+        /* Now, use the MC info to cruft up the PathRecord response */        
+        p_pr_item->path_rec.dgid = p_mgrp->mcmember_rec.mgid;
+        p_pr_item->path_rec.dlid = p_mgrp->mcmember_rec.mlid;
+       p_pr_item->path_rec.tclass = p_mgrp->mcmember_rec.tclass;
+       p_pr_item->path_rec.num_path = 1;
+       p_pr_item->path_rec.pkey = p_mgrp->mcmember_rec.pkey;
+
+       /* MTU, rate, and packet lifetime should be exactly */
+       p_pr_item->path_rec.mtu = (2<<6) | p_mgrp->mcmember_rec.mtu;
+        p_pr_item->path_rec.rate = (2<<6) | p_mgrp->mcmember_rec.rate;
+        p_pr_item->path_rec.pkt_life = (2<<6) | p_mgrp->mcmember_rec.pkt_life;
+
+       /* SL, Hop Limit, and Flow Label */
+        ib_member_get_sl_flow_hop( p_mgrp->mcmember_rec.sl_flow_hop,
+                                   &sl, &flow_label, &hop_limit );
+       p_pr_item->path_rec.sl = sl;
+        p_pr_item->path_rec.hop_flow_raw = (uint32_t)(hop_limit) |
+                                           (flow_label << 8);
+
+        cl_qlist_insert_tail( &pr_list,
+                              (cl_list_item_t*)&p_pr_item->pool_item );
+
+      }
+    }
+    else
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_pr_rcv_process: ERR 1F19: "
+               "MC group attributes don't match PathRecord request.\n" );
+    }
+  }
+
+  /* Now, (finally) respond to the PathRecord request */
+
+ Unlock:
+  cl_plock_release( p_rcv->p_lock );
+  __osm_pr_rcv_respond( p_rcv, p_madw, &pr_list );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
diff --git a/trunk/ulp/opensm/user/opensm/osm_sa_path_record_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_path_record_ctrl.c
new file mode 100644 (file)
index 0000000..e5f9d8e
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <opensm/osm_sa_path_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_sa_pkey_record.c b/trunk/ulp/opensm/user/opensm/osm_sa_pkey_record.c
new file mode 100644 (file)
index 0000000..bbd7bb3
--- /dev/null
@@ -0,0 +1,587 @@
+/*
+ * 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$
+ */
+
+
+/*
+  Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_rcv, 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 );
+
+  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 );
+  }
+
+  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( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__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
+             );
+  }
+
+  cl_memclr( &p_rec_item->rec, 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 );
+    }
+  }
+
+  //Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 requestor 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 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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_net64_t                comp_mask;
+  osm_physp_t*              p_req_physp;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_pkey_rec_rcv_process );
+
+  CL_ASSERT( p_rcv );
+  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 );
+
+  /* update the requestor 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 requestor physical port.\n" );
+    goto Exit;
+  }
+
+  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_SA_MAD_STATUS_REQ_INVALID);
+    goto Exit;
+  }
+  /*
+     p819 - P_KeyTableRecords shall only be provided in response
+     to trusted requests.
+     Check that the requestor is a trusted one.
+  */
+  if ( p_rcvd_mad->sm_key != p_rcv->p_subn->opt.sm_key )
+  {
+    /* This is not a trusted requestor! */
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "osm_pkey_rec_rcv_process ERR 4608: "
+             "Request from non-trusted requestor: "
+             "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;
+  }
+
+  p_tbl = &p_rcv->p_subn->port_lid_tbl;
+  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 )
+  {
+
+    CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 );
+
+    if ((uint16_t)cl_ptr_vector_get_size(p_tbl) > cl_ntoh16(p_rcvd_rec->lid))
+    {
+      p_port = cl_ptr_vector_get( p_tbl, cl_ntoh16(p_rcvd_rec->lid) );
+    }
+    else
+    { /* port out of range */
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_pkey_rec_rcv_process: "
+               "Given LID (%u) is out of range:%u.\n",
+               cl_ntoh16(p_rcvd_rec->lid), cl_ptr_vector_get_size(p_tbl));
+    }
+  }
+
+  /* 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 SubAdmGet 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_pkey_rec_rcv_process: "
+             "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.
+  */
+
+  cl_memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method = (uint8_t)(p_resp_sa_mad->method | 0x80);
+  /* C15-0.1.5 - always return SM_Key = 0 (table 151 p 782) */
+  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/trunk/ulp/opensm/user/opensm/osm_sa_pkey_record_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_pkey_record_ctrl.c
new file mode 100644 (file)
index 0000000..9b0313d
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * 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$
+ */
+
+
+/*
+  Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_sa_portinfo_record.c b/trunk/ulp/opensm/user/opensm/osm_sa_portinfo_record.c
new file mode 100644 (file)
index 0000000..d113eac
--- /dev/null
@@ -0,0 +1,794 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.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 <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;
+
+} osm_pir_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pir_rcv_construct(
+  IN osm_pir_rcv_t* const p_rcv )
+{
+  cl_memclr( p_rcv, 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 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_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_ERROR,
+             "__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 ) );
+  }
+
+  cl_memclr( &p_rec_item->rec, 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              lid_ho;
+  uint16_t              max_lid_ho;
+  uint16_t              base_lid_ho;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_pir_create );
+
+  if(p_physp->p_node->node_info.node_type == IB_NODE_TYPE_SWITCH)
+  {
+    lmc = 0;
+    base_lid_ho = cl_ntoh16(
+      osm_physp_get_base_lid(
+        osm_node_get_physp_ptr(p_physp->p_node, 0))
+      );
+    max_lid_ho = base_lid_ho;
+  }
+  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 )
+  {
+    __osm_pir_rcv_new_pir( p_rcv, p_physp, p_ctxt->p_list,
+                           p_ctxt->p_rcvd_rec->lid );
+  }
+  else
+  {
+    for( lid_ho = base_lid_ho; lid_ho <= max_lid_ho; lid_ho++ )
+    {
+      __osm_pir_rcv_new_pir( p_rcv, p_physp, p_ctxt->p_list,
+                             cl_hton16( lid_ho ) );
+    }
+  }
+  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 );
+    
+  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;
+  }
+  if( comp_mask & IB_PIR_COMPMASK_CAPMASK )
+  {
+    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_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_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_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;
+  }
+
+  __osm_sa_pir_create( p_rcv, p_physp, p_ctxt );
+
+ Exit:
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 requestor 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 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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_net64_t               comp_mask;
+  osm_physp_t*             p_req_physp;
+  boolean_t                trusted_req = TRUE;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_pir_rcv_process );
+
+  CL_ASSERT( p_rcv );
+  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 );
+
+  /* update the requestor 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 requestor physical port. \n" );
+    goto Exit;
+  }
+
+  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_SA_MAD_STATUS_REQ_INVALID);
+    goto Exit;
+  }
+
+  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;
+
+  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 )
+  {
+    if ((uint16_t)cl_ptr_vector_get_size(p_tbl) > cl_ntoh16(p_rcvd_rec->lid))
+    {
+      p_port = cl_ptr_vector_get( p_tbl, cl_ntoh16(p_rcvd_rec->lid) );
+    }
+    else
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_pir_rcv_process: "
+               "Given LID (%u) is out of range:%u.\n",
+               cl_ntoh16(p_rcvd_rec->lid), cl_ptr_vector_get_size(p_tbl));
+    }
+  }
+  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
+      {
+        osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+                 "osm_pir_rcv_process: "
+                 "Given LID (%u) is out of range:%u.\n",
+                 cl_ntoh16(p_pi->base_lid), cl_ptr_vector_get_size(p_tbl));
+      }
+    }
+  }
+
+  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 SubAdmGet 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_pir_rcv_process: "
+             "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.
+  */
+
+  cl_memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method = (uint8_t)(p_resp_sa_mad->method | 0x80);
+  /* C15-0.1.5 - always return SM_Key = 0 (table 151 p 782) */
+  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
+
+  /*
+    p819 - 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/trunk/ulp/opensm/user/opensm/osm_sa_portinfo_record_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_portinfo_record_ctrl.c
new file mode 100644 (file)
index 0000000..2d0657a
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_sa_response.c b/trunk/ulp/opensm/user/opensm/osm_sa_response.c
new file mode 100644 (file)
index 0000000..eacf399
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_sa_resp_t.
+ * This object represents the generic attribute respuester.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+/*
+  Next available error code: 0x300
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_resp, 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 151 p 782)
+   */
+  p_resp_sa_mad->sm_key = 0;
+
+  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/trunk/ulp/opensm/user/opensm/osm_sa_service_record.c b/trunk/ulp/opensm/user/opensm/osm_sa_service_record.c
new file mode 100644 (file)
index 0000000..fb95d25
--- /dev/null
@@ -0,0 +1,1218 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <iba/ib_types.h>
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_rcv, 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 requestor 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 requestor 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 requestor 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
+     * 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 SubAdmGet 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 );
+
+  cl_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 151 p 782) */
+  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;
+    cl_memclr( p_resp_sr, sizeof(*p_resp_sr) );
+  }
+  else
+  {
+    /*
+      p819 - 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)
+          cl_memclr(p_resp_sr->service_key, 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(
+      cl_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(cl_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(
+      cl_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 requestor 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: "
+               "requestor 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 form 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 requestor 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 requestor 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 );
+
+  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);
+
+  if ((p_sa_mad->method == IB_MAD_METHOD_GET) &&
+     (cl_qlist_count( &sr_match_item.sr_list ) == 0))
+  {
+    cl_plock_release(p_rcv->p_lock);
+
+    osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+             "osm_sr_rcv_process_get_method: "
+             "No Records Matched the query Service Record\n");
+
+    osm_sa_send_error( p_rcv->p_resp, p_madw,
+                       IB_SA_MAD_STATUS_NO_RECORDS );
+    goto Exit;
+  }
+
+  cl_plock_release(p_rcv->p_lock);
+
+  __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 )
+  {
+    /*       cl_timer_trim(&p_rcv->sr_timer, */
+    /*    p_recvd_service_rec->service_lease * 1000 ); */
+    /*  This was a bug since no check was made to see if too long */
+    /*  just make sure the timer works - geta 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;
+  ib_service_record_t*  p_recvd_service_rec;
+  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 );
+  p_recvd_service_rec =
+    (ib_service_record_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+  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\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\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: "
+             "Bad Method (%s)\n", ib_get_sa_method_str( p_sa_mad->method ));
+    osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status);
+    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/trunk/ulp/opensm/user/opensm/osm_sa_service_record_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_service_record_ctrl.c
new file mode 100644 (file)
index 0000000..110fdf3
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <complib/cl_memory.h>
+#include <opensm/osm_sa_service_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_sa_slvl_record.c b/trunk/ulp/opensm/user/opensm/osm_sa_slvl_record.c
new file mode 100644 (file)
index 0000000..8b6d061
--- /dev/null
@@ -0,0 +1,551 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_rcv, 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 );
+
+  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 );
+  }
+
+  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( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__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
+             );
+  }
+
+  cl_memclr( &p_rec_item->rec, 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 (out_port_num && out_port_num == in_port_num) */
+        /*  continue; */
+
+        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 requestor 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_net64_t                  comp_mask;
+  osm_physp_t*                p_req_physp;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_slvl_rec_rcv_process );
+
+  CL_ASSERT( p_rcv );
+  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 );
+
+  /* update the requestor 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 requestor physical port. \n" );
+    goto Exit;
+  }
+
+  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_SA_MAD_STATUS_REQ_INVALID);
+    goto Exit;
+  }
+
+  p_tbl = &p_rcv->p_subn->port_lid_tbl;
+  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 )
+  {
+
+    CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 );
+
+    if ((uint16_t)cl_ptr_vector_get_size(p_tbl) > cl_ntoh16(p_rcvd_rec->lid))
+    {
+      p_port = cl_ptr_vector_get( p_tbl, cl_ntoh16(p_rcvd_rec->lid) );
+    }
+    else
+    { /*  port out of range */
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_slvl_rec_rcv_process: "
+               "Given LID (%u) is out of range:%u.\n",
+               cl_ntoh16(p_rcvd_rec->lid), cl_ptr_vector_get_size(p_tbl));
+    }
+  }
+
+  /* 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_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 SubAdmGet 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_slvl_rec_rcv_process: "
+             "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.
+  */
+
+  cl_memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method = (uint8_t)(p_resp_sa_mad->method | 0x80);
+  /* C15-0.1.5 - always return SM_Key = 0 (table 151 p 782) */
+  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/trunk/ulp/opensm/user/opensm/osm_sa_slvl_record_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_slvl_record_ctrl.c
new file mode 100644 (file)
index 0000000..7cc78c9
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_sa_sminfo_record.c b/trunk/ulp/opensm/user/opensm/osm_sa_sminfo_record.c
new file mode 100644 (file)
index 0000000..89924a1
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.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>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_smir_rcv_construct(
+  IN osm_smir_rcv_t* const p_rcv )
+{
+  cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_smir_rcv_destroy(
+  IN osm_smir_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_smir_rcv_destroy );
+
+  CL_ASSERT( p_rcv );
+  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;
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_smir_rcv_process(
+  IN osm_smir_rcv_t*       const p_rcv,
+  IN const osm_madw_t*     const p_madw )
+{
+  const ib_sminfo_record_t*   p_sminfo_rec;
+  ib_sminfo_record_t*         p_resp_sminfo_rec;
+  const ib_sa_mad_t*       p_sa_mad;
+  ib_sa_mad_t*          p_resp_sa_mad;
+  osm_madw_t*              p_resp_madw;
+  ib_api_status_t          status;
+  osm_physp_t*                p_req_physp;
+  ib_net64_t                  local_guid;
+  osm_port_t*                 local_port;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_smir_rcv_process );
+
+  CL_ASSERT( p_rcv );
+  CL_ASSERT( p_madw );
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+  p_sminfo_rec = (ib_sminfo_record_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+  /* update the requestor 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 requestor physical port. \n" );
+    goto Exit;
+  }
+
+  CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_SMINFO_RECORD );
+
+  if (p_sa_mad->method != IB_MAD_METHOD_GET)
+  {
+    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_sa_mad->method ) );
+    osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+    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,
+                                 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 2801: "
+            "Unable to acquire response MAD.\n" );
+    goto Exit;
+  }
+
+  p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );
+  p_resp_sminfo_rec =
+    (ib_sminfo_record_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+  p_resp_sminfo_rec->resv0 = 0;
+
+  /* HACK: This handling is incorrect. The record to return is
+     records of known SMs by our SM, and not just the details of
+     our SM. */
+  /* check a matching of pkeys with the local physp the sm is on. */
+  local_guid = p_rcv->p_subn->sm_port_guid;
+  local_port = (osm_port_t*)cl_qmap_get( &p_rcv->p_subn->port_guid_tbl, local_guid );
+  if (FALSE == 
+      osm_physp_share_pkey( p_rcv->p_log, p_req_physp,
+                            osm_port_get_default_phys_ptr(local_port) ))
+  {
+    osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+            "osm_smir_rcv_process: ERR 2802: "
+            "Cannot get sminfo record - pkey violation.\n" );
+    goto Exit;
+  }
+
+  cl_plock_acquire( p_rcv->p_lock );
+
+  /*  get our local sm_base_lid to send in the sminfo */
+  p_resp_sminfo_rec->lid = p_rcv->p_subn->sm_base_lid;
+  p_resp_sminfo_rec->sm_info.guid = p_rcv->p_subn->sm_port_guid;
+  p_resp_sminfo_rec->sm_info.sm_key = p_rcv->p_subn->opt.sm_key;
+  p_resp_sminfo_rec->sm_info.act_count =
+    cl_ntoh32(p_rcv->p_stats->qp0_mads_sent);
+  p_resp_sminfo_rec->sm_info.pri_state = p_rcv->p_subn->sm_state;
+
+  cl_plock_release( p_rcv->p_lock );
+
+  p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+
+  /*  Copy the MAD header back into the response mad */
+  cl_memcpy( p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method = (uint8_t)(p_resp_sa_mad->method | 0x80);
+  /* 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) );
+
+  /* C15-0.1.5 - always return SM_Key = 0 (table 151 p 782) */
+  p_resp_sa_mad->sm_key = 0;
+
+  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/trunk/ulp/opensm/user/opensm/osm_sa_sminfo_record_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_sminfo_record_ctrl.c
new file mode 100644 (file)
index 0000000..4311552
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_sa_vlarb_record.c b/trunk/ulp/opensm/user/opensm/osm_sa_vlarb_record.c
new file mode 100644 (file)
index 0000000..4dc4e45
--- /dev/null
@@ -0,0 +1,573 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_rcv, 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 );
+
+  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 );
+  }
+
+  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( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__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
+             );
+  }
+
+  cl_memclr( &p_rec_item->rec, 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 is left is to get thr 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 );
+    }
+  }
+
+  /* Exit: */
+  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 requestor
+         and the p_phsyp 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 requestor 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_net64_t                     comp_mask;
+  osm_physp_t*                p_req_physp;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_vlarb_rec_rcv_process );
+
+  /* update the requestor 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 requestor physical port. \n" );
+    goto Exit;
+  }
+
+  CL_ASSERT( p_rcv );
+  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 );
+
+  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_SA_MAD_STATUS_REQ_INVALID);
+    goto Exit;
+  }
+
+  p_tbl = &p_rcv->p_subn->port_lid_tbl;
+  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 )
+  {
+
+    CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 );
+    if ((uint16_t)cl_ptr_vector_get_size(p_tbl) > cl_ntoh16(p_rcvd_rec->lid))
+    {
+      p_port = cl_ptr_vector_get( p_tbl, cl_ntoh16(p_rcvd_rec->lid) );
+    }
+    else
+    { /*  port out of range */
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "osm_vlarb_rec_rcv_process: "
+               "Given LID (%u) is out of range:%u.\n",
+               cl_ntoh16(p_rcvd_rec->lid), cl_ptr_vector_get_size(p_tbl));
+    }
+  }
+
+  /* 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 SubAdmGet 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_vlarb_rec_rcv_process: "
+             "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.
+  */
+
+  cl_memcpy( p_resp_sa_mad, p_rcvd_mad, IB_SA_MAD_HDR_SIZE );
+  p_resp_sa_mad->method = (uint8_t)(p_resp_sa_mad->method | 0x80);
+  /* C15-0.1.5 - always return SM_Key = 0 (table 151 p 782) */
+  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/trunk/ulp/opensm/user/opensm/osm_sa_vlarb_record_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sa_vlarb_record_ctrl.c
new file mode 100644 (file)
index 0000000..c8a9800
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_service.c b/trunk/ulp/opensm/user/opensm/osm_service.c
new file mode 100644 (file)
index 0000000..4daaecc
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * 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$
+ */
+
+
+
+/*
+ * 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 <complib/cl_memory.h>
+#include <complib/cl_timer.h>
+#include <opensm/osm_service.h>
+
+/**********************************************************************
+ **********************************************************************/
+
+void
+osm_svcr_construct(
+  IN osm_svcr_t* const p_svcr )
+{
+  cl_memclr( p_svcr, sizeof(*p_svcr) );
+}
+/**********************************************************************
+ **********************************************************************/
+
+void
+osm_svcr_destroy(
+  IN osm_svcr_t* const p_svcr )
+{
+  cl_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();
+  /*   p_svcr->svc_id = p_svc_rec->service_id; */
+
+  /* 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*)cl_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 = cl_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 a new Service Record\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/trunk/ulp/opensm/user/opensm/osm_slvl_map_rcv.c b/trunk/ulp/opensm/user/opensm/osm_slvl_map_rcv.c
new file mode 100644 (file)
index 0000000..dde027d
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <iba/ib_types.h>
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rcv_destroy(
+  IN osm_slvl_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_slvl_rcv_destroy );
+
+  CL_ASSERT( p_rcv );
+  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;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_slvl_rcv_process );
+
+  CL_ASSERT( p_rcv );
+  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 ) )
+  {
+    if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+    {
+      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/trunk/ulp/opensm/user/opensm/osm_slvl_map_rcv_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_slvl_map_rcv_ctrl.c
new file mode 100644 (file)
index 0000000..c495834
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_sm.c b/trunk/ulp/opensm/user/opensm/osm_sm.c
new file mode 100644 (file)
index 0000000..48eb00b
--- /dev/null
@@ -0,0 +1,844 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <complib/cl_signal_osd.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 )
+   {
+      osm_log( p_sm->p_log, OSM_LOG_DEBUG,
+               "__osm_sm_sweeper: " "Masking ^C Signals.\n" );
+      cl_sig_mask_sigint(  );
+
+      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 iniated "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 )
+{
+   cl_memclr( p_sm, 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 );
+
+   if( p_sm->p_report_buf != NULL )
+      cl_free( p_sm->p_report_buf );
+
+   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;
+
+   p_sm->p_report_buf = cl_malloc( OSM_REPORT_BUF_SIZE );
+   if( p_sm->p_report_buf == NULL )
+   {
+      osm_log( p_sm->p_log, OSM_LOG_ERROR,
+               "osm_sm_init: ERR 2E09: " "Can't allocate report buffer.\n" );
+      status = IB_INSUFFICIENT_MEMORY;
+      goto Exit;
+   }
+   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_report_buf,
+                                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_report_buf, 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 * ) cl_malloc( sizeof( osm_mcast_mgr_ctxt_t ) );
+   cl_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 );
+
+   /* Exit: */
+   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 * ) cl_malloc( sizeof( osm_mcast_mgr_ctxt_t ) );
+   cl_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 ) );
+         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.
+    */
+   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_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/trunk/ulp/opensm/user/opensm/osm_sm_mad_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sm_mad_ctrl.c
new file mode 100644 (file)
index 0000000..f15836b
--- /dev/null
@@ -0,0 +1,1061 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.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 );
+
+  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 );
+  }
+
+  /*
+    Acquire the lock non-exclusively.
+    Other modules that send MADs grab this lock exclusively.
+    These modules that are in the process of sending MADs
+    will hold the lock until they finish posting all the MADs
+    they plan to send.  While the other module is sending MADs
+    the outstanding count may temporarily go to zero.
+    Thus, by grabbing the lock ourselves, we get an accurate
+    view of whether or not the number of outstanding MADs is
+    really zero.
+  */
+  CL_PLOCK_ACQUIRE( p_ctrl->p_lock );
+  outstanding = p_ctrl->p_stats->qp0_mads_outstanding;
+  CL_PLOCK_RELEASE( p_ctrl->p_lock );
+
+  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( !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).\n",
+               CL_STATUS_MSG( status ) );
+      goto Exit;
+    }
+  }
+  else
+  {
+    /*
+      We received a response for which there is no recipient!!
+    */
+    CL_ASSERT( FALSE );
+  }
+
+ 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 ) );
+  }
+
+  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 a known 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 );
+
+  }
+
+  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 a known 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 );
+
+  }
+
+  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 a known 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;
+
+  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( ib_smp_get_status( p_smp ) != 0 )
+  {
+    osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+             "__osm_sm_mad_ctrl_rcv_callback: ERR 3111: "
+             "Error status = 0x%X.\n", ib_smp_get_status( p_smp ) );
+    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;
+  osm_physp_t* p_physp;
+  ib_api_status_t status;
+  ib_smp_t* p_smp;
+
+  OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_send_err_cb );
+
+  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 ) );
+
+  CL_ASSERT( p_madw );
+  CL_ASSERT( p_madw->resp_expected == TRUE );
+
+  /* 
+     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: "
+                 "Fail 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 );
+      }
+    }
+
+  /*
+    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 );
+  cl_memclr( p_ctrl, 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.  Call unbind first. " );
+    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/trunk/ulp/opensm/user/opensm/osm_sm_state_mgr.c b/trunk/ulp/opensm/user/opensm/osm_sm_state_mgr.c
new file mode 100644 (file)
index 0000000..7537ea4
--- /dev/null
@@ -0,0 +1,862 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_state_mgr_t.
+ * This file implements the Discovery Done Manager object.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.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" );   /* 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 )
+{
+   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" );
+   }
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+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.
+    */
+   cl_memclr( &context, 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;
+
+   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 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 );
+
+   cl_memclr( &context, 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%X \n", 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 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 found current (or new) master.
+    */
+   __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 : ERROR 1000: "
+               "Failed to start timer\n" );
+   }
+
+   OSM_LOG_EXIT( p_sm_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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. It 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 retrys"
+               "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 : ERROR 1000: "
+               "Failed to re-start 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 )
+{
+   cl_memclr( p_sm_mgr, 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 )
+{
+   OSM_LOG_ENTER( p_sm_mgr->p_log, osm_sm_state_mgr_destroy );
+
+   CL_ASSERT( p_sm_mgr );
+
+   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;
+
+   OSM_LOG_ENTER( p_sm_mgr->p_log, osm_sm_state_mgr_process );
+
+   CL_ASSERT( p_sm_mgr );
+
+   /*
+    * 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;
+      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 occure 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 \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 happend 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;
+
+   OSM_LOG_ENTER( p_sm_mgr->p_log, osm_sm_state_mgr_check_legality );
+
+   CL_ASSERT( p_sm_mgr );
+
+   /*
+    * 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:
+         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/trunk/ulp/opensm/user/opensm/osm_sminfo_rcv.c b/trunk/ulp/opensm/user/opensm/osm_sminfo_rcv.c
new file mode 100755 (executable)
index 0000000..eba36bd
--- /dev/null
@@ -0,0 +1,778 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <iba/ib_types.h>
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sminfo_rcv_destroy(
+  IN osm_sminfo_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_sminfo_rcv_destroy );
+
+  CL_ASSERT( p_rcv );
+  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.
+**********************************************************************/
+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) );
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+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.
+  */
+  cl_memclr( payload, 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 
+    requestor 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 requestor 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.
+ **********************************************************************/
+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 );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+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.
+  */
+  cl_memclr( payload, 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 
+    requestor 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 requestor 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 maseter_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 signalUpdating "
+             "sm_state_mgr master_guid: 0x%X.\n",
+             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.
+ **********************************************************************/
+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%X.\n",
+                 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;
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+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;
+  ib_api_status_t          status;
+  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 an Other 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 = cl_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;
+    }
+
+    status = osm_remote_sm_init( p_sm, p_port, p_smi );
+    if( status != IB_SUCCESS )
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_sminfo_rcv_process_get_response: ERR 2F15: "
+               "Other SM object initialization failed (%s).\n",
+               ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+    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 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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/trunk/ulp/opensm/user/opensm/osm_sminfo_rcv_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sminfo_rcv_ctrl.c
new file mode 100644 (file)
index 0000000..cd6db17
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <complib/cl_memory.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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_state_mgr.c b/trunk/ulp/opensm/user/opensm/osm_state_mgr.c
new file mode 100644 (file)
index 0000000..df29764
--- /dev/null
@@ -0,0 +1,2931 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_state_mgr_t.
+ * This file implements the Discovery Done Manager object.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.13 $
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <iba/ib_types.h>
+#include <complib/cl_memory.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 <vendor/osm_vendor_api.h>
+#include <opensm/osm_sm_state_mgr.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_state_mgr_construct(
+   IN osm_state_mgr_t * const p_mgr )
+{
+   cl_memclr( p_mgr, 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 )
+{
+   OSM_LOG_ENTER( p_mgr->p_log, osm_state_mgr_destroy );
+
+   CL_ASSERT( p_mgr );
+
+   /*  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 char *const p_report_buf,
+   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 );
+   CL_ASSERT( p_report_buf );
+
+   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->p_report_buf = p_report_buf;
+   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;
+   }
+
+   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" );
+   }
+}
+
+/**********************************************************************
+ **********************************************************************/
+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(%d) in state %s.\n",
+            osm_get_sm_signal_str( signal ),
+            signal, osm_get_sm_state_str( p_mgr->state ) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 just a 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(%d) 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 );
+
+   cl_memclr( &context, 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 );
+   cl_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 ) );
+
+   cl_memclr( &mad_context, 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;
+
+   /* 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 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 );
+
+   cl_memclr( path_array, 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 clearning 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 );
+
+      cl_memclr( &ni_context, 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 );
+
+   cl_memclr( path_array, 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:
+      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: "
+               " Supported node type that hosts SM is CA or SW only" );
+   }
+
+ Exit:
+   OSM_LOG_EXIT( p_mgr->p_log );
+   return ( status );
+}
+
+/**********************************************************************
+ Initiates a light-weight 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;
+
+   cl_memclr( path_array, 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;
+
+   OSM_LOG_ENTER( p_mgr->p_log, osm_topology_file_create );
+
+   CL_PLOCK_ACQUIRE( p_mgr->p_lock );
+
+   file_name =
+      ( char * )cl_malloc( strlen( p_mgr->p_subn->opt.dump_files_dir ) + 12 );
+
+   CL_ASSERT( file_name );
+
+   strcpy( file_name, p_mgr->p_subn->opt.dump_files_dir );
+   strcat( file_name, "/subnet.lst" );
+
+   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;
+            }
+
+            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_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_ntoh32( p_node->node_info.device_id ),
+                     cl_ntoh32( p_node->node_info.revision ),
+                     p_node->node_desc.description,
+                     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;
+            }
+
+
+            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 ),
+                     p_nbnode->node_desc.description,
+                     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:
+   cl_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;
+   char line[OSM_REPORT_LINE_SIZE];
+   uint8_t node_type;
+   uint32_t line_num = 0;
+
+   OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_report );
+
+   if( !osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+   {
+      goto Exit;
+   }
+
+   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++ )
+      {
+         if( line_num == 0 )
+         {
+            strcpy( p_mgr->p_report_buf,
+                    "\n==================================================="
+                    "====================================================" );
+            strcat( p_mgr->p_report_buf,
+                    "\nVendor      : Ty "
+                    ": #  : Sta : LID  : LMC : MTU  : LWA : LSA : Port GUID    "
+                    "    : Neighbor Port (Port #)\n" );
+            line_num++;
+         }
+
+         p_physp = osm_port_get_phys_ptr( p_port, port_num );
+         if( ( p_physp == NULL ) || ( !osm_physp_is_valid( p_physp ) ) )
+            continue;
+
+         sprintf( line, "%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 );
+
+         strcat( p_mgr->p_report_buf, line );
+
+         p_pi = osm_physp_get_port_info_ptr( p_physp );
+
+         /*
+          * Port state is not defined for switch port 0
+          */
+         if( port_num == 0 )
+            strcat( p_mgr->p_report_buf, "     :" );
+         else
+         {
+            sprintf( line, " %s :",
+                     osm_get_port_state_str_fixed_width
+                     ( ib_port_info_get_port_state( p_pi ) ) );
+            strcat( p_mgr->p_report_buf, line );
+         }
+
+         /*
+          * LID values are only meaningful in select cases.
+          */
+         if( ib_port_info_get_port_state( p_pi ) != IB_LINK_DOWN )
+         {
+            if( ( ( node_type == IB_NODE_TYPE_SWITCH ) && ( port_num == 0 ) )
+                || ( node_type != IB_NODE_TYPE_SWITCH ) )
+            {
+               sprintf( line, " %04X :  %01X  :",
+                        cl_ntoh16( p_pi->base_lid ),
+                        ib_port_info_get_lmc( p_pi ) );
+
+               strcat( p_mgr->p_report_buf, line );
+            }
+            else
+               strcat( p_mgr->p_report_buf, "      :     :" );
+         }
+         else
+            strcat( p_mgr->p_report_buf, "      :     :" );
+
+         if( port_num != 0 )
+         {
+            sprintf( line, " %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
+         {
+            sprintf( line, " %s : %s : %s ", "   ", "   ", "   " );
+         }
+         strcat( p_mgr->p_report_buf, line );
+
+         if( osm_physp_get_port_guid( p_physp ) ==
+             p_mgr->p_subn->sm_port_guid )
+         {
+            sprintf( line, "* %016" PRIx64 " *",
+                     cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) );
+         }
+         else
+         {
+            sprintf( line, ": %016" PRIx64 " :",
+                     cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) );
+         }
+         strcat( p_mgr->p_report_buf, line );
+
+         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 ) )
+            {
+               sprintf( line, " %016" PRIx64 " (%02X)",
+                        cl_ntoh64( osm_physp_get_port_guid
+                                   ( p_remote_physp ) ),
+                        osm_physp_get_port_num( p_remote_physp ) );
+               strcat( p_mgr->p_report_buf, line );
+            }
+            else
+               strcat( p_mgr->p_report_buf, " UNKNOWN" );
+         }
+
+         strcat( p_mgr->p_report_buf, "\n" );
+
+         if( ++line_num >= OSM_REPORT_BUF_THRESHOLD )
+         {
+            osm_log_raw( p_mgr->p_log, OSM_LOG_VERBOSE, p_mgr->p_report_buf );
+            line_num = 0;
+         }
+      }
+      strcat( p_mgr->p_report_buf,
+              "------------------------------------------------------"
+              "------------------------------------------------\n" );
+      p_port = ( osm_port_t * ) cl_qmap_next( &p_port->map_item );
+   }
+
+   CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+   if( line_num != 0 )
+      osm_log_raw( p_mgr->p_log, OSM_LOG_VERBOSE, p_mgr->p_report_buf );
+
+ Exit:
+   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 );
+   }
+
+
+   cl_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 update 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.
+ **********************************************************************/
+osm_remote_sm_t *
+__osm_state_mgr_exists_other_master(
+   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 );
+
+   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: "
+                  "Found remote master sm with guid:0x%X \n",
+                  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.
+ **********************************************************************/
+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 given.
+ **********************************************************************/
+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 testablity 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.
+    */
+
+   cl_memclr( &context, 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: "
+            "Handover 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 requestor
+    * 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 requestor 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,
+                         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.
+ **********************************************************************/
+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;
+
+   OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_report_new_ports );
+
+   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( &notice, CL_HTON32( 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;
+      cl_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 );
+      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 ?
+                 ( char * )( p_port->p_node->node_desc.description ) :
+                 "UNKNOWN" ) );
+
+      p_port =
+         ( osm_port_t
+           * ) ( cl_list_remove_head( &p_mgr->p_subn->new_ports_list ) );
+   }
+
+   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 to 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.
+ **********************************************************************/
+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 anyways */
+   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 occure 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 that, the port 
+          * is updated with its original lid in our data-base, 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%X 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%X, 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%X 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_LOG_ENTER( p_mgr->p_log, osm_state_mgr_process );
+   CL_ASSERT( p_mgr );
+
+   /* 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;
+
+               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....
+             */
+            signal = OSM_SIGNAL_NONE;
+            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....
+             */
+            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 outstanding transaction 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 typcially
+             * 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( 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 assigning */
+            osm_drop_mgr_process( p_mgr->p_drop_mgr );
+            p_mgr->state = OSM_SM_STATE_SET_SM_UCAST_LID;
+
+            /*
+             * 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 );
+
+            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 );
+            }
+            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 typcially
+             * 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 = cl_zalloc( 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;
+   }
+
+
+   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/trunk/ulp/opensm/user/opensm/osm_state_mgr_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_state_mgr_ctrl.c
new file mode 100644 (file)
index 0000000..d20ee8b
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x1601
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_subnet.c b/trunk/ulp/opensm/user/opensm/osm_subnet.c
new file mode 100644 (file)
index 0000000..9ab35f7
--- /dev/null
@@ -0,0 +1,938 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <opensm/osm_subnet.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_node.h>
+#include <opensm/osm_multicast.h>
+#include <opensm/osm_inform.h>
+#include <stdlib.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_subn_construct(
+  IN osm_subn_t* const p_subn )
+{
+  cl_memclr( p_subn, 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_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 );
+    cl_free( p_rsm );
+  }
+
+  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_pro_ignore_guids));
+  cl_map_destroy(&(p_subn->opt.port_pro_ignore_guids));
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_subn_init(
+  IN osm_subn_t* const p_subn,
+  IN const osm_subn_opt_t* const p_opt )
+{
+  cl_status_t status;
+
+  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_pro_ignore_guids), 10);
+
+  /* ignore_existing_lfts follows the 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_gid_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 )
+{
+  const cl_ptr_vector_t*  p_tbl;
+  const osm_port_t*       p_port = NULL;
+  const osm_physp_t*      p_physp = NULL;
+  ib_gid_t                request_gid;
+
+  /* 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) );
+    p_physp = osm_port_get_phys_ptr( p_port, p_port->default_port_num);
+    request_gid.unicast.interface_id = p_physp->port_guid;
+    request_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 request_gid;
+}
+
+/**********************************************************************
+ **********************************************************************/
+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)
+             );
+    
+    goto Exit;
+  }
+
+ 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)
+             );
+    goto Exit;
+  }
+
+ Exit:
+  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;
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_subn_set_default_opt(
+  IN osm_subn_opt_t* const p_opt )
+{
+  cl_memclr(p_opt, sizeof(osm_subn_opt_t));
+  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->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->max_op_vls = OSM_DEFAULT_MAX_OP_VLS;
+  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->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 = 4;
+  p_opt->force_heavy_sweep = FALSE;
+  p_opt->log_flags = 0;
+  p_opt->dump_files_dir = getenv("OSM_TMP_DIR");
+  if (!p_opt->dump_files_dir)
+    p_opt->dump_files_dir = OSM_DEFAULT_TMP_DIR;
+
+  p_opt->log_file = OSM_DEFAULT_LOG_FILE;
+  p_opt->port_profile_switch_nodes = FALSE;
+  p_opt->max_port_profile = 0xffffffff;
+  p_opt->pfn_ui_pre_lid_assign = NULL;
+  p_opt->ui_pre_lid_assign_ctx = NULL;
+  p_opt->pfn_ui_ucast_fdb_assign = NULL;
+  p_opt->ui_ucast_fdb_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->updn_activate = FALSE;
+  p_opt->updn_guid_file = NULL;
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 (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);
+      *p_val = (char *)cl_malloc(strlen(p_val_str));
+      strcpy( *p_val, p_val_str);
+    }
+  }
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 = 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(
+        "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_uint8(
+        "max_op_vls",
+        p_key, p_val, &p_opts->max_op_vls);
+
+      __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(
+        "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_boolean(
+        "updn_activate",
+        p_key, p_val, &p_opts->updn_activate);
+
+      __osm_subn_opts_unpack_charp(
+        "log_file" , p_key, p_val, &p_opts->log_file);
+
+      __osm_subn_opts_unpack_charp(
+        "dump_files_dir" ,
+        p_key, p_val, &p_opts->dump_files_dir);
+
+      __osm_subn_opts_unpack_charp( 
+        "updn_guid_file" ,
+        p_key, p_val, &p_opts->updn_guid_file);
+    }
+  }
+  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 = 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"
+    "# M_Key value sent to all ports qualifing 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"
+    "# The code of maximal time a packet can live in a switch\n"
+    "# The actual time is 4.096usec * 2^<packet_life_time code>\n"
+    "# The value 0x14 disables this mechanism\n"
+    "packet_life_time 0x%02x\n\n"
+    "# The code of maximal time a packet can wait at the head of\n"
+    "# transmision 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 HCA\n"
+    "leaf_head_of_queue_lifetime 0x%02x\n\n"
+    "# Limit the maximal operational VLs\n"
+    "max_op_vls %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 code>\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->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->packet_life_time,
+    p_opts->head_of_queue_lifetime,
+    p_opts->leaf_head_of_queue_lifetime,
+    p_opts->max_op_vls,
+    p_opts->subnet_timeout,
+    p_opts->local_phy_errors_threshold,
+    p_opts->overrun_errors_threshold
+    );
+
+  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 re-assigned\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 same traps (>10) are supressed\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 do not count switches as link subscriptions\n"
+    "port_profile_switch_nodes %s\n\n"
+    "# Activate the Up/Down routing algorithm\n"
+    "updn_activate %s\n\n",
+    p_opts->port_profile_switch_nodes ? "TRUE" : "FALSE",
+    p_opts->updn_activate ? "TRUE" : "FALSE"
+    );
+  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);
+  
+  fprintf( 
+    opts_file,    
+    "#\n# HANDOVER - MULTIPLE SM's OPTIONS\n#\n"
+    "# SM priority used for deciding who is the master\n"
+    "sm_priority %u\n\n"
+    "# If TRUE other SM's on the subnet should be ignored\n"
+    "ignore_other_sm %s\n\n"
+    "# Timeout in [sec] 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",
+    p_opts->sm_priority,
+    p_opts->ignore_other_sm ? "TRUE" : "FALSE",
+    p_opts->sminfo_polling_timeout,
+    p_opts->polling_retry_number
+    );
+    
+  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 then one message in the queue and the last message\n"
+    "# stayed in the queue more then this value any SA request will be \n"
+    "# immediatly 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" 
+    "# The directory to hold the file OpenSM dumps\n"
+    "dump_files_dir %s\n\n"
+    "# If TRUE if 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",
+    p_opts->log_flags,
+    p_opts->force_log_flush ? "TRUE" : "FALSE",
+    p_opts->log_file,
+    p_opts->dump_files_dir,
+    p_opts->no_multicast_option ? "TRUE" : "FALSE",
+    p_opts->disable_multicast ? "TRUE" : "FALSE"
+    );
+  
+  /* optional string attributes ... */
+  
+  fclose(opts_file);
+}
+
diff --git a/trunk/ulp/opensm/user/opensm/osm_sw_info_rcv.c b/trunk/ulp/opensm/user/opensm/osm_sw_info_rcv.c
new file mode 100644 (file)
index 0000000..5ac945d
--- /dev/null
@@ -0,0 +1,719 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <iba/ib_types.h>
+#include <complib/cl_memory.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>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_si_rcv_clear_sc_bit(
+  IN const osm_si_rcv_t* const p_rcv,
+  IN osm_node_t* const p_node,
+  IN ib_switch_info_t* const p_si )
+{
+  uint8_t payload[IB_SMP_DATA_SIZE];
+  ib_api_status_t status;
+  osm_madw_context_t context;
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_clear_sc_bit );
+
+  context.si_context.node_guid = osm_node_get_node_guid( p_node );
+  context.si_context.set_method = TRUE;
+  context.si_context.light_sweep = FALSE;
+
+  cl_memcpy( payload, p_si, IB_SMP_DATA_SIZE );
+
+  status = osm_req_set( p_rcv->p_req,
+                        osm_node_get_any_dr_path_ptr( p_node ),
+                        payload,
+                        IB_MAD_ATTR_SWITCH_INFO,
+                        0,
+                        CL_DISP_MSGID_NONE,
+                        &context );
+
+  if( status != IB_SUCCESS )
+  {
+    osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+             "__osm_si_rcv_clear_sc_bit: ERR 3601: "
+             "Unable to clear state change bit for switch "
+             "with GUID = 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.
+**********************************************************************/
+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;
+
+  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.
+**********************************************************************/
+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 );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+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 );
+}
+
+/**********************************************************************
+   Lock must be held on entry to this function.
+**********************************************************************/
+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;
+
+  OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_process_new );
+
+  CL_ASSERT( p_rcv );
+  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;
+  }
+
+  /*
+    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...
+**********************************************************************/
+boolean_t
+__osm_si_rcv_process_existing(
+  IN const osm_si_rcv_t* const p_rcv,
+  IN osm_node_t* const p_node,
+  IN osm_switch_t* const p_sw,
+  IN const osm_madw_t* const p_madw )
+{
+  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_node );
+  CL_ASSERT( p_sw );
+  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 )
+{
+  cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_si_rcv_destroy(
+  IN osm_si_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_si_rcv_destroy );
+
+  CL_ASSERT( p_rcv );
+  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;
+  cl_qmap_t *p_sw_guid_tbl;
+  ib_switch_info_t *p_si;
+  ib_smp_t *p_smp;
+  osm_node_t *p_node;
+  osm_switch_t *p_sw;
+  ib_net64_t node_guid;
+  osm_si_context_t *p_context;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_si_rcv_process );
+
+  CL_ASSERT( p_rcv );
+  CL_ASSERT( p_madw );
+
+  p_node_guid_tbl = &p_rcv->p_subn->node_guid_tbl;
+  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 );
+
+  /*
+    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.
+    */
+    p_sw = (osm_switch_t*)cl_qmap_get( p_sw_guid_tbl,
+                                       node_guid );
+    if( p_sw == (osm_switch_t*)cl_qmap_end( p_sw_guid_tbl ) )
+    {
+      __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_sw, 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/trunk/ulp/opensm/user/opensm/osm_sw_info_rcv_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sw_info_rcv_ctrl.c
new file mode 100644 (file)
index 0000000..04132ff
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_sweep_fail_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_sweep_fail_ctrl.c
new file mode 100644 (file)
index 0000000..fa2d09c
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <complib/cl_memory.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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_switch.c b/trunk/ulp/opensm/user/opensm/osm_switch.c
new file mode 100644 (file)
index 0000000..489a4e6
--- /dev/null
@@ -0,0 +1,544 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <complib/cl_memory.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 );
+  cl_memclr( p_sw, 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 );
+
+  p_sw->p_pro = cl_zalloc( sizeof(*p_sw->p_pro) * num_ports );
+  if( p_sw->p_pro == NULL )
+  {
+    status = IB_INSUFFICIENT_MEMORY;
+    goto Exit;
+  }
+
+  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_pro_construct( &p_sw->p_pro[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 );
+  cl_free( p_sw->p_pro );
+  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 );
+  cl_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*)cl_zalloc( sizeof(*p_sw) );
+  if( 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 )
+  {
+    cl_memclr( p_block, 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,
+  IN const uint32_t max_routes_subscribed,
+  IN boolean_t      ui_ucast_fdb_assign_func_defined
+  )
+{
+  /*
+    We support an enhanced LMC aware routing mode:
+    In 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, enquire 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 || ui_ucast_fdb_assign_func_defined )
+        {
+          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 un-healthy */
+      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_pro_path_count_get(
+          &p_sw->p_pro[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)
+        {
+          /* printf("LID:%u SYS:%d NODE:%d\n", lid_ho,*p_num_used_sys, *p_num_used_nodes); */
+
+          /* 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 (!cl_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 (!cl_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) &&
+            (check_count <= max_routes_subscribed))
+        {
+          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);
+    cl_memcpy(&remote_node_guids[*p_num_used_nodes],
+              &(p_rem_node->node_info.node_guid),
+              sizeof(uint64_t));
+    (*p_num_used_nodes)++;
+    cl_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_pro_construct( &p_sw->p_pro[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/trunk/ulp/opensm/user/opensm/osm_trap_rcv.c b/trunk/ulp/opensm/user/opensm/osm_trap_rcv.c
new file mode 100644 (file)
index 0000000..7dd44d1
--- /dev/null
@@ -0,0 +1,735 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <iba/ib_types.h>
+#include <complib/cl_memory.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:%u 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 )
+{
+  cl_memclr( p_rcv, 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 )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_trap_rcv_destroy );
+
+  CL_ASSERT( p_rcv );
+
+  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 */
+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
+*/
+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;
+}
+
+/**********************************************************************
+ **********************************************************************/
+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.
+  */
+  cl_memclr( payload, sizeof( payload ) );
+  cl_memclr( &tmp_madw, 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.
+   */
+
+  cl_memcpy(payload, &(p_smp->data), IB_SMP_DATA_SIZE);
+  cl_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 a SLID=0 Trap. local LID=0. Ignoring mad. \n");
+        goto Exit;
+      }
+      osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+               "__osm_trap_rcv_process_request: "
+               "Received a 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))
+    {
+      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 Vend 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)
+    {
+      osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+               "__osm_trap_rcv_process_request: ERR 3804: "
+               "Received the trap %u times continuously.\n",
+               num_received);
+      /*
+       * If the trap provides info about a bad port
+       * we will 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: "
+                   "Fail 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 loosing 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 then 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 conetxt */
+                         );
+    else
+      cl_event_wheel_reg(&p_rcv->trap_aging_tracker,
+                         trap_key,
+                         cl_get_time_stamp() + event_wheel_timeout,
+                         NULL, /*  no callback */
+                         NULL /*  no conetxt */
+                         );
+
+    /* If was already registered do nothing more */
+    if ( num_received > 10 && run_heavy_sweep == FALSE )
+    {
+      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)
+    {
+      cl_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;
+  }
+
+  status = osm_report_notice(p_rcv->p_log, p_rcv->p_subn, p_ntci);
+  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 );
+}
+
+/**********************************************************************
+ CURRENTLY WE ARE NOT CREATING TRAPS - SO THIS CALL IS AN ERROR
+**********************************************************************/
+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: "
+           "This function is not supported yet.\n");
+
+
+  OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
+/**********************************************************************
+ CURRENTLY WE ARE NOT CREATING TRAPS - SO THIS CALL IN AN ERROR
+**********************************************************************/
+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: "
+           "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/trunk/ulp/opensm/user/opensm/osm_trap_rcv_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_trap_rcv_ctrl.c
new file mode 100644 (file)
index 0000000..2cd19e9
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <complib/cl_memory.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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/osm_ucast_mgr.c b/trunk/ulp/opensm/user/opensm/osm_ucast_mgr.c
new file mode 100644 (file)
index 0000000..796eb94
--- /dev/null
@@ -0,0 +1,1171 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * Abstract:
+ *    Implementation of osm_ucast_mgr_t.
+ * This file implements the LID Manager object.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.14 $
+ */
+
+/*
+  Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_memory.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>
+
+#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 )
+{
+  cl_memclr( p_mgr, sizeof(*p_mgr) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ucast_mgr_destroy(
+  IN osm_ucast_mgr_t* const p_mgr )
+{
+  OSM_LOG_ENTER( p_mgr->p_log, osm_ucast_mgr_destroy );
+
+  CL_ASSERT( p_mgr );
+  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 char* const p_report_buf,
+  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->p_report_buf = p_report_buf;
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ucast_mgr_dump_path_distribution(
+  IN const osm_ucast_mgr_t* const p_mgr,
+  IN const osm_switch_t* const p_sw )
+{
+  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;
+  char line[OSM_REPORT_LINE_SIZE];
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_ucast_mgr_dump_path_distribution );
+
+  if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+  {
+    p_node = osm_switch_get_node_ptr( p_sw );
+
+    num_ports = osm_switch_get_num_ports( p_sw );
+    sprintf( p_mgr->p_report_buf, "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 );
+      sprintf( line, "\n %03u : %u", i, num_paths );
+      strcat( p_mgr->p_report_buf, line );
+      if( i == 0 )
+      {
+        strcat( p_mgr->p_report_buf, " (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:
+        strcat( p_mgr->p_report_buf, " (link to switch" );
+        break;
+      case IB_NODE_TYPE_ROUTER:
+        strcat( p_mgr->p_report_buf, " (link to router" );
+        break;
+      case IB_NODE_TYPE_CA:
+        strcat( p_mgr->p_report_buf, " (link to CA" );
+        break;
+      default:
+        strcat( p_mgr->p_report_buf, " (link to unknown type, node" );
+        break;
+      }
+
+      sprintf( line, " 0x%" PRIx64 ")", remote_guid_ho );
+      strcat( p_mgr->p_report_buf, line );
+    }
+
+    strcat( p_mgr->p_report_buf, "\n" );
+
+    osm_log_raw( p_mgr->p_log, OSM_LOG_ROUTING, p_mgr->p_report_buf );
+  }
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ucast_mgr_dump_ucast_routes(
+  IN const osm_ucast_mgr_t*   const p_mgr,
+  IN const osm_switch_t*      const p_sw )
+{
+  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;
+  char                  line[OSM_REPORT_LINE_SIZE];
+  uint32_t              line_num = 0;
+  FILE  *              p_fdbFile;
+  boolean_t            ui_ucast_fdb_assign_func_defined;
+  char                *file_name = NULL;
+  
+  OSM_LOG_ENTER( p_mgr->p_log, osm_ucast_mgr_dump_ucast_routes );
+
+  if( !osm_log_is_active( p_mgr->p_log, OSM_LOG_ROUTING ) )
+    goto Exit;
+
+  file_name = 
+    (char*)cl_malloc(strlen(p_mgr->p_subn->opt.dump_files_dir) + 10);
+  
+  CL_ASSERT(file_name);
+  
+  strcpy(file_name, p_mgr->p_subn->opt.dump_files_dir);
+  strcat(file_name,"/osm.fdbs");
+  
+  /* Open the file or error */
+  p_fdbFile = fopen(file_name, "a");
+  if (! p_fdbFile)
+  {
+    osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+             "osm_ucast_mgr_dump_ucast_routes: ERR 3A12: "
+             "Fail to open fdb file (%s).\n",
+             file_name );
+    goto Exit;
+  }
+
+  p_node = osm_switch_get_node_ptr( p_sw );
+
+  max_lid_ho = osm_switch_get_max_lid_ho( p_sw );
+
+  for( lid_ho = 1; lid_ho <= max_lid_ho; lid_ho++ )
+  {
+    if( line_num == 0 )
+    {
+      sprintf( p_mgr->p_report_buf, "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 ) ) );
+      line_num++;
+    }
+
+    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 assignemnts.  Running SM with --reassign_lids
+        will reassign and compress the LID range.  The
+        subnet should work fine either way.
+      */
+      sprintf( line, "0x%04X : UNREACHABLE\n", lid_ho );
+      strcat( p_mgr->p_report_buf, line );
+      line_num++;
+      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 )
+    {
+      sprintf( line, "0x%04X : UNREACHABLE\n", lid_ho );
+      strcat( p_mgr->p_report_buf, line );
+      line_num++;
+      continue;
+    }
+
+    best_hops = osm_switch_get_least_hops( p_sw, lid_ho );
+    sprintf( line, "0x%04X : %03u  : %02u   : ",
+             lid_ho, port_num, num_hops );
+    strcat( p_mgr->p_report_buf, line );
+
+    if( best_hops == num_hops )
+      strcat( p_mgr->p_report_buf, "yes" );
+    else
+    {
+      if (p_mgr->p_subn->opt.pfn_ui_ucast_fdb_assign) {
+        ui_ucast_fdb_assign_func_defined = TRUE;
+      } else {
+        ui_ucast_fdb_assign_func_defined = FALSE;
+      }
+      best_port = osm_switch_recommend_path(
+        p_sw, lid_ho, TRUE,
+        NULL, NULL, NULL, NULL, /* No LMC Optimization */
+        0xffffffff, ui_ucast_fdb_assign_func_defined );
+      sprintf( line, "No %u hop path possible via port %u!",
+               best_hops, best_port );
+      strcat( p_mgr->p_report_buf, line );
+    }
+
+    strcat( p_mgr->p_report_buf, "\n" );
+
+    if( ++line_num >= OSM_REPORT_BUF_THRESHOLD )
+    {
+      fprintf(p_fdbFile,"%s",p_mgr->p_report_buf );
+      line_num = 0;
+    }
+  }
+
+  if( line_num != 0 )
+    fprintf(p_fdbFile,"%s\n",p_mgr->p_report_buf );
+
+  fclose(p_fdbFile);
+
+ Exit:
+  if (file_name)
+    cl_free(file_name);
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+   Add each switch's own LID 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;
+  cl_status_t status;
+
+  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 );
+
+  /*
+    Starting a rebuild, so notify the switch so it can
+    clear tables, etc...
+  */
+  osm_switch_prepare_path_rebuild( p_sw );
+
+  lid_ho = cl_ntoh16( osm_node_get_base_lid( p_node, 0 ) );
+
+  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).\n",
+             CL_STATUS_MSG( status ) );
+  }
+
+  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;
+/*   case IB_NODE_TYPE_SWITCH: */
+/*     base_lid_ho = cl_ntoh16( osm_node_get_base_lid( */
+/*                                p_remote_node, 0 ) ); */
+/*     lmc = 0; */
+/*     break; */
+
+  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 ignore_existing, is_ignored_by_port_pro;
+  ib_net64_t node_guid;
+  boolean_t  ui_ucast_fdb_assign_func_defined;
+  /*
+    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 = cl_zalloc( 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. Memory insufficient.\n");
+    goto Exit;
+  }
+
+  remote_node_guids = cl_zalloc( 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. Memory insufficient.\n");
+    goto Exit;
+  }
+
+  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 an 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 ) );
+
+  /* Flag to mark whether or not a ui ucast fdb assign function was given */
+  if (p_mgr->p_subn->opt.pfn_ui_ucast_fdb_assign)
+    ui_ucast_fdb_assign_func_defined = TRUE;
+  else
+    ui_ucast_fdb_assign_func_defined = FALSE;
+
+  /*
+    If the user request a complete subnet reconfiguration,
+    then ignore existing paths when choosing paths now.
+    Note that if there is a ui ucast fdb assign function - then the 
+    ignore_existing should be false.
+  */
+  ignore_existing = p_mgr->p_subn->ignore_existing_lfts &&
+    (!ui_ucast_fdb_assign_func_defined) ;
+
+  /*
+    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, ignore_existing,
+                                        remote_sys_guids, &num_used_sys,
+                                        remote_node_guids, &num_used_nodes,
+                                        p_mgr->p_subn->opt.max_port_profile,
+                                        ui_ucast_fdb_assign_func_defined );
+    else
+      port = osm_switch_recommend_path( p_sw, lid_ho, ignore_existing,
+                                        NULL, NULL, NULL, NULL,
+                                        p_mgr->p_subn->opt.max_port_profile,
+                                        ui_ucast_fdb_assign_func_defined );
+
+    /*
+      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_pro = 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->opt.updn_activate)
+      {
+        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_pro =
+       osm_port_pro_is_ignored_port(p_mgr->p_subn, cl_ntoh64(node_guid), port);
+
+      /*
+       We also would ignore this route if the target lid if 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_pro |=
+         (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.
+    */
+    osm_switch_set_path( p_sw, lid_ho, port, is_ignored_by_port_pro);
+  }
+ Exit:
+  if (remote_sys_guids) cl_free(remote_sys_guids);
+  if (remote_node_guids) cl_free(remote_node_guids);
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_set_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];
+
+  OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_set_table );
+
+  CL_ASSERT( p_mgr );
+  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 );
+  si.lin_top = cl_hton16( osm_switch_get_max_lid_ho( p_sw ) );
+
+  /* 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 ) )
+    si.life_state = ( (p_mgr->p_subn->opt.packet_life_time <<3 )
+                      | ( si.life_state & IB_SWITCH_PSC ) )  & 0xfc;
+  else
+    si.life_state = (p_mgr->p_subn->opt.packet_life_time <<3 ) & 0xf8;
+
+  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_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,
+                        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_table: ERR 3A06: "
+             "Sending SwitchInfo attribute failed (%s).\n",
+             ib_get_err_str( status ) );
+  }
+
+  /*
+    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;
+
+  while( osm_switch_get_fwd_tbl_block( p_sw, block_id_ho, block ) )
+  {
+    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_table: "
+               "Writing FT block %u.\n", block_id_ho );
+    }
+
+    status = osm_req_set( p_mgr->p_req,
+                          p_path,
+                          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_table: ERR 3A05: "
+               "Sending linear fwd. tbl. block failed (%s).\n",
+               ib_get_err_str( status ) );
+    }
+
+    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 ) ));
+  }
+
+  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_table( p_mgr, p_sw );
+
+  osm_ucast_mgr_dump_path_distribution( p_mgr, p_sw );
+  osm_ucast_mgr_dump_ucast_routes( 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;
+  ib_net64_t remote_node_guid;
+  osm_switch_t *p_remote_sw;
+  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 )
+        && (osm_node_get_type( p_remote_node )
+            == IB_NODE_TYPE_SWITCH ))
+    {
+      /* 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;
+
+      remote_node_guid = osm_node_get_node_guid( p_remote_node );
+
+      p_remote_sw = (osm_switch_t*)cl_qmap_get(
+        &p_mgr->p_subn->sw_guid_tbl, remote_node_guid );
+
+      if( p_remote_sw == (osm_switch_t*)cl_qmap_end(
+            &p_mgr->p_subn->sw_guid_tbl ) )
+      {
+        osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+                 "__osm_ucast_mgr_process_neighbors: ERR 3A07: "
+                 "No switch object for Node GUID = 0x%" PRIx64 ".\n",
+                 cl_ntoh64( remote_node_guid ) );
+      }
+      else
+      {
+        __osm_ucast_mgr_process_neighbor(
+          p_mgr,
+          p_sw,
+          p_remote_sw,
+          (uint8_t)port_num,
+          remote_port_num );
+      }
+    }
+  }
+
+
+  OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_signal_t
+osm_ucast_mgr_process(
+  IN osm_ucast_mgr_t* const p_mgr )
+{
+  uint32_t i;
+  uint32_t iteration_max;
+  osm_signal_t signal;
+  cl_qmap_t *p_sw_guid_tbl;
+
+  OSM_LOG_ENTER( p_mgr->p_log, osm_ucast_mgr_process );
+
+  p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+  CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
+
+  osm_log(p_mgr->p_log, OSM_LOG_VERBOSE,
+          "osm_ucast_mgr_process: "
+          "Starting switches Min Hop Table Assignment.\n");
+  
+  /*
+    Set the switch matrixes for each switch's own port 0 LID,
+    then set the lid matrixes 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 matrixes 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_mgr->p_subn->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_process: "
+             "Min-hop propagated in %d steps\n",
+             i
+             );
+
+    /*
+      This is the place where we can load pre-defined routes
+      into the switches fwd_tbl structures.
+
+      Later code will use these values if not configured for
+      re-assignment.
+    */
+    if (p_mgr->p_subn->opt.pfn_ui_ucast_fdb_assign)
+    {
+      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: "
+                 "Invoking UI function pfn_ui_ucast_fdb_assign\n");
+      }
+      p_mgr->p_subn->opt.pfn_ui_ucast_fdb_assign(p_mgr->p_subn->opt.ui_ucast_fdb_assign_ctx);
+    } else {
+        osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+                 "osm_ucast_mgr_process: "
+                 "UI pfn was not invoked\n");
+    }
+
+    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 matrixes have been built, we can
+      build and download the switch forwarding tables.
+    */
+
+    /* initialize the fdb dump file: */
+    if( osm_log_is_active( p_mgr->p_log, OSM_LOG_ROUTING ) )
+      unlink("/tmp/osm.fdbs");
+
+    cl_qmap_apply_func( p_sw_guid_tbl,
+                        __osm_ucast_mgr_process_tbl, p_mgr );
+
+    /*
+      For now dont' bother checking if the switch forwarding tables
+      actually needed updating.  The current code will always update
+      them, and thus leave transactions pending on the wire.
+      Therefore, return OSM_SIGNAL_DONE_PENDING.
+    */
+
+    signal = OSM_SIGNAL_DONE_PENDING;
+  }
+  else
+    signal = OSM_SIGNAL_DONE;
+
+  osm_log(p_mgr->p_log, OSM_LOG_VERBOSE,
+          "osm_ucast_mgr_process: "
+          "LFT Tables configured on all switches.\n");
+
+  CL_PLOCK_RELEASE( p_mgr->p_lock );
+  OSM_LOG_EXIT( p_mgr->p_log );
+  return( signal );
+}
+
diff --git a/trunk/ulp/opensm/user/opensm/osm_ucast_updn.c b/trunk/ulp/opensm/user/opensm/osm_ucast_updn.c
new file mode 100644 (file)
index 0000000..3d604f3
--- /dev/null
@@ -0,0 +1,1206 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <complib/cl_qmap.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_ucast_updn.h>
+#include <stdlib.h>
+
+
+/* ///////////////////////////////// */
+/*  Globals */
+/* ///////////////////////////////// */
+/*  This var is pre defined and initialized */
+extern osm_opensm_t osm;
+
+/**********************************************************************
+ **********************************************************************/
+/* This function returns direction based on rank and guid info of current &
+   remote ports */
+
+updn_switch_dir_t
+__updn_get_dir(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 = osm.p_updn_ucast_routing->updn_ucast_reg_inputs.num_guids;
+  uint64_t *p_guid = osm.p_updn_ucast_routing->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 does not connect
+     directly , but in case they are we assign to root node an UP direction to allow UPDN discover
+     correctly (and not from the point of view of the last root node) the subnet .
+  */
+
+  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 */
+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*) cl_zalloc(sizeof(*p_next_step));
+  CL_ASSERT (p_next_step != NULL);
+
+  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 */
+
+int
+__updn_update_rank(
+  IN cl_qmap_t *p_guid_rank_tbl,
+  IN ib_net64_t guid_index,
+  IN uint8_t rank)
+{
+  updn_rank_t *p_updn_rank;
+
+  p_updn_rank = (updn_rank_t*) cl_qmap_get(p_guid_rank_tbl, guid_index);
+  if (p_updn_rank == (updn_rank_t*) cl_qmap_end(p_guid_rank_tbl))
+  {
+    p_updn_rank = (updn_rank_t*) cl_malloc(sizeof(updn_rank_t));
+    CL_ASSERT (p_updn_rank);
+
+    p_updn_rank->rank = rank;
+
+    cl_qmap_insert(p_guid_rank_tbl, guid_index , &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 do the bfs of min hop table calculation by guid index as a
+ * starting point.
+ **********************************************************************/
+int
+__updn_bfs_by_node(IN osm_subn_t *p_subn, IN ib_net64_t guid_index, IN cl_qmap_t *p_guid_rank_tbl)
+{
+  /*  Init local vars */
+  osm_port_t *p_port;
+  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_ENTER( &(osm.log) , __updn_bfs_by_node);
+
+  /* Init the list pointers */
+  p_nextList = (cl_list_t*)cl_malloc(sizeof(cl_list_t));
+  cl_list_construct( p_nextList );
+  cl_list_init( p_nextList, 10 );
+  p_currList = p_nextList;
+
+  p_port = (osm_port_t*) cl_qmap_get(&(p_subn->port_guid_tbl),guid_index);
+  /* TODO : check if p_port is not NULL */
+  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( &(osm.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(&(osm.log), OSM_LOG_DEBUG,
+          "__updn_bfs_by_node:"
+          "Starting lid : 0x%x \n", root_lid);
+
+  if (osm_node_get_type( p_port->p_node ) == IB_NODE_TYPE_SWITCH)
+  {
+    p_self_node = osm_get_switch_by_guid(p_subn, guid_index);
+    /* Update its Min Hop Table */
+    osm_log(&(osm.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 an HCA 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 (osm_node_get_type(p_remote_physp->p_node) != IB_NODE_TYPE_SWITCH)
+      {
+        osm_log(&(osm.log), OSM_LOG_ERROR,
+                "__updn_bfs_by_node:  ERR AA07: "
+                "This is a non switched subnet OR non valid connection, cannot perform Algorithm\n");
+        OSM_LOG_EXIT( &(osm.log));
+        return 1;
+      } else
+      {
+        p_self_node = osm_get_switch_by_guid(p_subn,
+                                             osm_physp_get_port_guid
+                                             (p_remote_physp));
+        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(&(osm.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(&(osm.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( &(osm.log));
+          return 1;
+        }
+      }
+    }
+  }
+
+  CL_ASSERT(p_self_node);
+
+  osm_log(&(osm.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(&(osm.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(&(osm.log), OSM_LOG_VERBOSE,
+          "__updn_bfs_by_node:"
+          "BFS the subnet [\n");
+
+  while (!cl_is_list_empty(p_currList))
+  {
+    osm_log(&(osm.log), OSM_LOG_DEBUG,
+            "__updn_bfs_by_node:"
+            "Starting a new iteration with %d elements in current list\n", cl_list_count(p_currList));
+    /* Init the switch directed list */
+    p_nextList = (cl_list_t*)cl_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(&(osm.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 %d\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 = osm_get_switch_by_guid(p_subn, remote_guid);
+        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_cur_rank->rank, p_rem_rank->rank,
+                                   current_guid, remote_guid);
+
+        osm_log(&(osm.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(&(osm.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(&(osm.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 : %d"
+                  " \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(&(osm.log), OSM_LOG_ERROR,
+                    "__updn_bfs_by_node (less) ERR AA1: "
+                    "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(&(osm.log), OSM_LOG_ERROR,
+                      "__updn_bfs_by_node:  ERR AA2: "
+                      "Could not create updn_next_step_t\n");
+              return 1;
+            }
+            osm_log(&(osm.log), OSM_LOG_DEBUG,
+                    "__updn_bfs_by_node: "
+                    "Inserting a 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(&(osm.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 : %d"
+                  "\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(&(osm.log), OSM_LOG_ERROR,
+                    "__updn_bfs_by_node (less) ERR AA3: "
+                    "Invalid value returned from set min hop is : %d\n", set_hop_return_value);
+          }
+        }
+      }
+      cl_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 );
+    cl_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 );
+  cl_free (p_currList);
+  osm_log(&(osm.log), OSM_LOG_VERBOSE,
+          "__updn_bfs_by_node:"
+          "BFS the subnet ]\n");
+  OSM_LOG_EXIT( &(osm.log));
+  return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 (&(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);
+    cl_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)
+    cl_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 )))
+    cl_free( p_guid_list_item );
+
+  cl_list_remove_all( p_updn->p_root_nodes );
+  cl_list_destroy( p_updn->p_root_nodes );
+  cl_free ( p_updn->p_root_nodes );
+  cl_free (p_updn);
+}
+
+updn_t*
+updn_construct(void)
+{
+  updn_t* p_updn;
+
+  OSM_LOG_ENTER( &(osm.log) , updn_construct);
+
+  p_updn = cl_zalloc(sizeof(updn_t));
+  if (p_updn == NULL)
+  {
+    goto Exit;
+  }
+  Exit :
+    OSM_LOG_EXIT( &(osm.log) );
+  return(p_updn);
+}
+
+/**********************************************************************
+ **********************************************************************/
+cl_status_t
+updn_init(
+  IN updn_t* const p_updn )
+{
+  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( &(osm.log) , updn_init );
+  p_updn->state = UPDN_INIT;
+  cl_qmap_init( &p_updn->guid_rank_tbl);
+  p_list = (cl_list_t*)cl_malloc(sizeof(cl_list_t));
+  if (!p_list)
+  {
+    status = IB_ERROR;
+    goto Exit_Bad;
+  }
+  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 if updn is activated , then fetch root nodes */
+  if (osm.subn.opt.updn_activate)
+  {
+    /*
+       Check the source for root node list, if file parse it, otherwise
+       wait for a callback to activate auto detection
+    */
+    if (osm.subn.opt.updn_guid_file)
+    {
+      /* Now parse guid from file */
+      p_updn_guid_file = fopen(osm.subn.opt.updn_guid_file, "r");
+      if (p_updn_guid_file == NULL)
+      {
+        osm_log( &osm.log, OSM_LOG_ERROR,
+                 "osm_opensm_init : ERR AA02: "
+                 "Fail to open guid list file (%s).\n",
+                 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 = cl_malloc(sizeof(uint64_t));
+            *p_tmp = strtoull(line,NULL,16);
+            cl_list_insert_tail(osm.p_updn_ucast_routing->p_root_nodes, p_tmp);
+          }
+        }
+        else
+        {
+          osm_log( &osm.log, OSM_LOG_ERROR,
+                   "osm_opensm_init : ERR AA03: "
+                   "Bad formatted guid in file (%s) : %s.\n"
+                   , osm.subn.opt.updn_guid_file,line);
+          status = IB_NOT_FOUND;
+          break;
+        }
+      }
+
+      /* For Debug Purposes ... */
+      osm_log( &osm.log, OSM_LOG_DEBUG,
+               "osm_opensm_init : "
+               "UPDN - Root nodes fetching by file %s.\n",
+               osm.subn.opt.updn_guid_file);
+      guid_iterator = cl_list_head(osm.p_updn_ucast_routing->p_root_nodes);
+      while( guid_iterator != cl_list_end(osm.p_updn_ucast_routing->p_root_nodes) )
+      {
+        osm_log( &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
+    {
+      osm.p_updn_ucast_routing->auto_detect_root_nodes = TRUE;
+    }
+    /* If auto mode detection reuired - will be executed in main b4 the assignment of UI Ucast */
+  }
+
+  goto Exit;
+
+  Exit_Bad :
+    return 1;
+  Exit :
+    OSM_LOG_EXIT( &(osm.log) );
+  return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* NOTE : PLS check if we need to decide that the first */
+/*        rank is a SWITCH for BFS purpose */
+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_ENTER( &(osm.log) , updn_subn_rank);
+
+  osm_log(&(osm.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*)cl_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(&(osm.subn.port_guid_tbl)));
+  if (tbl_size == 0)
+  {
+    osm_log(&(osm.log), OSM_LOG_ERROR,
+            "updn_subn_rank: ERR AA04: "
+            "Port guid table is empty, cannot perform ranking.\n");
+    OSM_LOG_EXIT( &(osm.log));
+    return 1;
+  }
+
+  p_root_port = (osm_port_t*) cl_qmap_get(&(osm.subn.port_guid_tbl), \
+                                          cl_ntoh64(root_guid));
+  if( p_root_port == (osm_port_t*)cl_qmap_end( &(osm.subn.port_guid_tbl) ) )
+  {
+
+    osm_log(&(osm.log), OSM_LOG_ERROR,
+            "updn_subn_rank: ERR AA05: "
+            "Wrong guid value : 0x%" PRIx64 ".\n", root_guid);
+    OSM_LOG_EXIT( &(osm.log));
+    return 1;
+  }
+
+  /* Rank the first chosen guid anyway since its the base rank */
+  osm_log(&(osm.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(&(osm.log), OSM_LOG_VERBOSE,
+          "updn_subn_rank: "
+          "BFS the subnet [\n");
+
+  while (!cl_is_list_empty(p_currList))
+  {
+    rank++;
+    p_nextList = (cl_list_t*)cl_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(&(osm.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 occure 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(&(osm.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(&(osm.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(&(osm.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 );
+    cl_free(p_currList);
+    /* p_currList is empty - need to assign it to p_nextList */
+    p_currList = p_nextList;
+  }
+
+  osm_log(&(osm.log), OSM_LOG_VERBOSE,
+          "updn_subn_rank: "
+          "BFS the subnet ]\n");
+
+  cl_list_destroy( p_currList );
+  cl_free(p_currList);
+
+  /* Print Summary of ranking */
+  osm_log(&(osm.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( &(osm.log));
+  return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+int
+osm_subn_set_up_down_min_hop_table(
+  IN updn_t* p_updn)
+{
+  /* Init local vars */
+  osm_subn_t *p_subn = &(osm.subn);
+  osm_switch_t *p_next_sw,*p_sw;
+  osm_port_t *p_next_port,*p_port;
+  ib_net64_t port_guid;
+
+  OSM_LOG_ENTER( &(osm.log) , osm_subn_set_up_down_min_hop_table );
+  if (p_updn->state == UPDN_INIT)
+  {
+    osm_log(&(osm.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( &(osm.log));
+    return 1;
+  }
+
+  /* Check if its a non switched subnet .. */
+  if ( cl_is_qmap_empty( &p_subn->sw_guid_tbl ) )
+  {
+    osm_log(&(osm.log), OSM_LOG_ERROR,
+            "osm_subn_set_up_down_min_hop_table: ERR AA10: "
+            "This is a non switched subnet , cannot perform Algorithm\n");
+    OSM_LOG_EXIT( &(osm.log));
+    return 1;
+  }
+  /* Go over all the switches in the subnet - for each init their Min Hop
+     Table */
+  osm_log(&(osm.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 ) )
+  {
+    uint16_t max_lid_ho,lid_ho;
+
+    p_sw = p_next_sw;
+    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 */
+    osm_lid_matrix_clear(&(p_sw->lmx));
+    max_lid_ho = osm_switch_get_max_lid_ho(p_sw);
+    for (lid_ho=1 ; lid_ho <= max_lid_ho ; lid_ho++)
+      osm_switch_set_path(p_sw,lid_ho,OSM_NO_PATH,TRUE);
+  }
+
+  osm_log(&(osm.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(&(osm.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(&(osm.log), OSM_LOG_DEBUG,
+            "BFS through port guid 0x%" PRIx64 ".\n"
+            , cl_ntoh64(port_guid));
+    if(__updn_bfs_by_node(p_subn,port_guid,
+                          &p_updn->guid_rank_tbl))
+    {
+      OSM_LOG_EXIT( &(osm.log));
+      return 1;
+    }
+  }
+
+  osm_log(&(osm.log), OSM_LOG_INFO,
+          "osm_subn_set_up_down_min_hop_table:"
+          "BFS through all port guids in the subnet ]\n");
+  /* Cleanup */
+  OSM_LOG_EXIT( &(osm.log));
+  return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+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( &(osm.log) , osm_subn_calc_up_down_min_hop_table );
+  osm_log(&(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(&(osm.log), OSM_LOG_ERROR,
+            "osm_subn_calc_up_down_min_hop_table :"
+            "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(&(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 (&(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);
+    cl_free( (updn_rank_t *)p_map_item);
+    p_map_item = cl_qmap_head( &p_updn->guid_rank_tbl);
+  }
+
+  OSM_LOG_EXIT( &(osm.log));
+  return status;
+
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+/* UPDN callback function */
+
+int __osm_updn_call( void *ctx) {
+  OSM_LOG_ENTER(&(osm.log), __osm_updn_call);
+  /* First auto detect root nodes - if required */
+  if ( ((updn_t*)ctx)->auto_detect_root_nodes )
+  {
+    /*    printf ("-V- b4 osm_updn_find_root_nodes_by_min_hop\n");*/
+    osm_updn_find_root_nodes_by_min_hop( ((updn_t*)ctx) );
+  }
+  /*  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 ( ((updn_t*)ctx)->updn_ucast_reg_inputs.num_guids > 0)
+  {
+    osm_log (&(osm.log), OSM_LOG_DEBUG,
+             "__osm_updn_call : "
+             "activating UPDN algorithm.\n");
+    osm_subn_calc_up_down_min_hop_table( ((updn_t*)ctx)->updn_ucast_reg_inputs.num_guids,
+                                         ((updn_t*)ctx)->updn_ucast_reg_inputs.guid_list
+                                         , ((updn_t*)ctx) );
+  }
+  else
+    osm_log (&(osm.log), OSM_LOG_INFO,
+             "__osm_updn_call : "
+             "disable UPDN algorithm , no root nodes were found.\n");
+  
+  OSM_LOG_EXIT(&(osm.log));
+  return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* UPDN convert cl_list to guid array in updn struct */
+void __osm_updn_convert_list2array (IN updn_t * p_updn) {
+  uint32_t i = 0,max_num = 0;
+  uint64_t * p_guid;
+
+  OSM_LOG_ENTER(&(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)
+    cl_free(p_updn->updn_ucast_reg_inputs.guid_list);
+  p_updn->updn_ucast_reg_inputs.guid_list = (uint64_t *)cl_zalloc(
+    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;
+      cl_free(p_guid);
+      i++;
+    }
+    max_num = i;
+    for (i=0;i < max_num ; i++ )
+      osm_log (&(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(&(osm.log));
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* Registration function to ucast routing manager (instead of
+   Min Hop Algorithm) */
+
+int
+osm_updn_reg_calc_min_hop_table(
+  IN updn_t * p_updn,
+  IN osm_subn_opt_t* p_opt )
+{
+  OSM_LOG_ENTER(&(osm.log), osm_updn_reg_calc_min_hop_table);
+  /*
+     If root nodes were supplied by the user - we need to convert into array
+     otherwise, will be created & converted in callback function activation
+  */
+  if (!p_updn->auto_detect_root_nodes)
+  {
+    __osm_updn_convert_list2array(p_updn);
+  }
+  osm_log (&(osm.log), OSM_LOG_DEBUG,
+           "osm_updn_reg_calc_min_hop_table : "
+           "assigning ucast fdb UI function with updn callback\n");
+  p_opt->pfn_ui_ucast_fdb_assign = __osm_updn_call;
+  p_opt->ui_ucast_fdb_assign_ctx = (void *)p_updn;
+  OSM_LOG_EXIT(&(osm.log));
+  return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* Find Root nodes automatically by Min Hop Table info */
+int
+osm_updn_find_root_nodes_by_min_hop( OUT updn_t *  p_updn )
+{
+  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(&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(&(osm.log), osm_updn_find_root_nodes_by_min_hop);
+  osm_log (&(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(&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*)cl_malloc(sizeof(cl_list_t)); 
+     cl_list_construct( p_ca_list ); 
+     cl_list_init( p_ca_list, 10 );
+  */
+
+  /* Find the Maximum number of Cas for `histogram normalization */
+  osm_log (&(osm.log), OSM_LOG_VERBOSE,
+           "osm_updn_find_root_nodes_by_min_hop : "
+           "Find the number of CA and store them in cl_list.\n");
+  p_next_port = (osm_port_t*)cl_qmap_head( &osm.subn.port_guid_tbl );
+  while( p_next_port != (osm_port_t*)cl_qmap_end( &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_CA )
+    {
+      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 = cl_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 (&(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 (&(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( &osm.subn.sw_guid_tbl );
+  osm_log (&(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( &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 (&(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*) cl_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 (&(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 (&(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 (&(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 (&(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 (&(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 );
+      cl_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 = cl_malloc(sizeof(uint64_t));
+      *p_guid = cl_ntoh64(osm_node_get_node_guid(p_sw->p_node));
+      osm_log (&(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(&(osm.log));
+  return 0;
+}
diff --git a/trunk/ulp/opensm/user/opensm/osm_vl15intf.c b/trunk/ulp/opensm/user/opensm/osm_vl15intf.c
new file mode 100644 (file)
index 0000000..1b9aa20
--- /dev/null
@@ -0,0 +1,463 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x403
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <iba/ib_types.h>
+#include <complib/cl_signal_osd.h>
+#include <complib/cl_memory.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)
+  {
+    cl_sig_mask_sigint();
+    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 )
+      {
+        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.
+        */
+        mads_sent = cl_atomic_dec( &p_vl->p_stats->qp0_mads_sent );
+      }
+      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 on wire, %u outstanding, %u unicasts sent, "
+                   "%u sent total.\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 should put back these mads...
+  */
+
+  OSM_LOG_EXIT( p_vl->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vl15_construct(
+  IN osm_vl15_t* const p_vl )
+{
+  cl_memclr( p_vl, 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 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+  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;
+
+  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;
+
+ 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 MADs on wire, %u 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 );
+
+  /* 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 );
+    cl_atomic_dec( &p_vl->p_stats->qp0_mads_outstanding );
+
+    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/trunk/ulp/opensm/user/opensm/osm_vl_arb_rcv.c b/trunk/ulp/opensm/user/opensm/osm_vl_arb_rcv.c
new file mode 100644 (file)
index 0000000..1a54150
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 <iba/ib_types.h>
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_rcv, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vla_rcv_destroy(
+  IN osm_vla_rcv_t* const p_rcv )
+{
+  OSM_LOG_ENTER( p_rcv->p_log, osm_vla_rcv_destroy );
+
+  CL_ASSERT( p_rcv );
+  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 A 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;
+
+  OSM_LOG_ENTER( p_rcv->p_log, osm_vla_rcv_process );
+
+  CL_ASSERT( p_rcv );
+  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 ) )
+  {
+    if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+    {
+      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/trunk/ulp/opensm/user/opensm/osm_vl_arb_rcv_ctrl.c b/trunk/ulp/opensm/user/opensm/osm_vl_arb_rcv_ctrl.c
new file mode 100644 (file)
index 0000000..8f0d97d
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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 $
+ */
+
+/*
+  Next available error code: 0x203
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_memory.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 )
+{
+  cl_memclr( p_ctrl, 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/trunk/ulp/opensm/user/opensm/st.c b/trunk/ulp/opensm/user/opensm/st.c
new file mode 100644 (file)
index 0000000..a214eae
--- /dev/null
@@ -0,0 +1,626 @@
+/*
+ * 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$
+ */
+
+
+/* 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 <stdlib.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
+#if 0
+void *xmalloc(long);
+void *xcalloc(long, long);
+void *xrealloc(void *, long);
+void xfree(void *);
+#endif
+
+static void rehash(st_table *);
+
+#define alloc(type) (type*)xmalloc((unsigned)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("/tmp/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;
+     int 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)
+     int 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)
+     int 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;
+  int 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((unsigned)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/trunk/ulp/opensm/user/osmtest/Makefile b/trunk/ulp/opensm/user/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/trunk/ulp/opensm/user/osmtest/SOURCES b/trunk/ulp/opensm/user/osmtest/SOURCES
new file mode 100644 (file)
index 0000000..b2a4ff3
--- /dev/null
@@ -0,0 +1,71 @@
+!if $(FREEBUILD)
+TARGETNAME=osmtest
+!else
+TARGETNAME=osmtestd
+!endif
+
+!if !defined(WINIBHOME)
+WINIBHOME=..\..\..\..
+!endif
+
+LIBPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)
+
+!if defined(OSM_TARGET)
+TARGETPATH=$(OSM_TARGET)\bin\user\obj$(BUILD_ALT_DIR)
+!else
+TARGETPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)
+!endif
+
+TARGETTYPE=PROGRAM
+UMTYPE=console
+USE_CRTDLL=1
+OVR_DIR=..\addon
+
+
+SOURCES=\
+       osmt_slvl_vl_arb.c \
+       osmt_service.c \
+       osmt_multicast.c \
+       osmt_inform.c \
+       osmtest.c \
+       main.c \
+
+
+
+OSM_HOME=..
+
+TARGETLIBS=\
+!if $(FREEBUILD)
+                       $(LIBPATH)\*\ibal.lib \
+                       $(LIBPATH)\*\complib.lib \
+                       $(TARGETPATH)\*\osmv_ibal.lib \
+                       $(TARGETPATH)\*\opensm_ibal.lib \
+                       $(CRT_LIB_PATH)\msvcrt.lib
+
+!else
+                       $(LIBPATH)\*\ibald.lib \
+                       $(LIBPATH)\*\complibd.lib \
+                       $(TARGETPATH)\*\osmv_ibald.lib \
+                       $(TARGETPATH)\*\opensm_ibald.lib \
+                       $(CRT_LIB_PATH)\msvcrt.lib
+!endif
+
+#DO NOT TOUCH the order of search path , until ib_types.h merging process will be done
+INCLUDES= \
+       $(OSM_HOME)\include; \
+       $(OSM_HOME); \
+       $(WINIBHOME)\inc; \
+       $(WINIBHOME)\inc\user;
+
+# Could be any special flag needed for this project 
+USER_C_FLAGS=$(USER_C_FLAGS) /MD
+#Add preproccessor definitions
+C_DEFINES=$(C_DEFINES) -DWIN32 -D__WIN__ -D__i386__ -Dinline=__inline -DMT_LITTLE_ENDIAN -DOSM_VENDOR_INTF_AL
+!if !$(FREEBUILD)
+#C_DEFINES=$(C_DEFINES) -D_DEBUG -DDEBUG -DDBG
+C_DEFINES=$(C_DEFINES) 
+!endif
+
+LINKER_FLAGS= $(LINKER_FLAGS)
+MSC_WARNING_LEVEL= /W3
+
diff --git a/trunk/ulp/opensm/user/osmtest/error.h b/trunk/ulp/opensm/user/osmtest/error.h
new file mode 100644 (file)
index 0000000..11e2559
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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$
+ */
+
+
+/*
+ * 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/trunk/ulp/opensm/user/osmtest/main.c b/trunk/ulp/opensm/user/osmtest/main.c
new file mode 100644 (file)
index 0000000..6f7affb
--- /dev/null
@@ -0,0 +1,543 @@
+/*
+ * 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$
+ */
+
+
+
+/*
+ * Abstract:
+ *     Command line interface for osmtest.
+ *
+ * Environment:
+ *     Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef __WIN__
+#include <getopt.h>
+#endif
+#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_ ) */
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 - mutiple 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" );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+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 osm_osmtest_init: %s.\n",
+                               ib_get_err_str( status ) );
+               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();
+
+#ifndef __WIN__
+   complib_exit();
+#endif
+
+  Exit:
+       return ( status );
+}
diff --git a/trunk/ulp/opensm/user/osmtest/osmt_inform.c b/trunk/ulp/opensm/user/osmtest/osmt_inform.c
new file mode 100644 (file)
index 0000000..9841403
--- /dev/null
@@ -0,0 +1,964 @@
+/*
+ * 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$
+ */
+
+
+#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 $
+ */
+
+/* next error code: 16A    */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_memory.h>
+
+#include <opensm/osm_vendor_mlx_hca.h>
+#include "osmtest.h"
+#include "osmt_inform.h"
+
+/*
+ * Prepare an a synchronous 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;
+  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], &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" );
+    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 */
+  cl_memclr(p_qp_ctx->p_send_buf, 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 */
+  cl_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: "
+             "Un Subscribing 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 un-subsribe:
+     * o13-2.1.1 - QPN Field need to be set when un-subscribing.
+     */
+    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);
+    /*    for (i = 56; i < 253; i++) { */
+    /*   if ( i % 8 == 0 ) { printf("\n %d : ", i);} */
+    /*   printf("0x%02X ", p_qp_ctx->p_send_buf[i]); */
+    /* } */
+    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 exmaine 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 a 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 a 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 (targetted 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_osmt->log, osmt_send_trap_wait_for_forward );
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_send_trap_wait_for_forward: "
+           "Sending Traps to QP0 of SA LID:%X\n",
+           p_osmt->local_port.sm_lid);
+
+  /* init the MAD */
+  cl_memclr(p_smp, 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(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 exmaine 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_send_trap_wait_for_forward: "
+               "Received the Report !\n");
+      status = IB_SUCCESS;
+    }
+    else
+    {
+      osm_log( &p_osmt->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)
+               );
+    }
+  }
+  else
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_send_trap_wait_for_forward: ERR 1020"
+             "Receive an Un-Expected Method:%d.\n",
+             p_smp->method
+             );
+  }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->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_osmt->log, osmt_trap_wait );
+
+  osm_log( &p_osmt->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 exmaine 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)
+               );
+    }
+  }
+  else
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_trap_wait: ERR 1020"
+             "Receive an Un-Expected Method:%d.\n",
+             p_smp->method
+             );
+  }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->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) {
+
+  cl_memclr(p_ii, 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) {
+
+  cl_memclr(p_ii, 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 un-subscribe */
+  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 un-subscribe 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 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 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 */
+  /*   sleep (p_osmt->opt.wait_time); */
+
+  /* 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 un-subscribe 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/trunk/ulp/opensm/user/osmtest/osmt_inform.h b/trunk/ulp/opensm/user/osmtest/osmt_inform.h
new file mode 100644 (file)
index 0000000..866641b
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * 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$
+ */
+
+#ifndef __OSMT_INFORM__
+#define __OSMT_INFORM__
+
+#include <opensm/osm_vendor_mlx_inout.h>
+#include <ib_mgt.h>
+#include "osmt_mtl_regular_qp.h"
+
+typedef struct _osmt_qp_ctx
+{
+  osmt_mtl_mad_res_t qp_bind_hndl;
+  uint8_t *p_send_buf;
+  uint8_t *p_recv_buf;
+  IB_MGT_mad_hndl_t ib_mgt_qp0_handle; 
+}
+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/trunk/ulp/opensm/user/osmtest/osmt_mtl_regular_qp.c b/trunk/ulp/opensm/user/osmtest/osmt_mtl_regular_qp.c
new file mode 100644 (file)
index 0000000..06347d9
--- /dev/null
@@ -0,0 +1,461 @@
+/*
+ * 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$
+ */
+
+#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,v 1.1 2003/03/20 16:41:48 eitan Exp $
+ *
+ *  Authors:
+ *    Eitan Zahavi
+ * 
+ *  Changes:
+ */           
+#include <inttypes.h>
+#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 */
+}
+
+
+#ifndef __KERNEL__
+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
+
+
+
+#ifdef __KERNEL__
+int init_module(void)
+{
+  MTL_TRACE1("mad module loaded.\n");
+  return(0);
+}
+
+void cleanup_module(void)
+{
+  MTL_TRACE1("mad module unloaded.\n");
+}
+#endif
+
+#endif /*  OSM_VENDOR_INTF_MTL */
diff --git a/trunk/ulp/opensm/user/osmtest/osmt_mtl_regular_qp.h b/trunk/ulp/opensm/user/osmtest/osmt_mtl_regular_qp.h
new file mode 100644 (file)
index 0000000..56afd0b
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * 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$
+ */
+
+/*                  - Mellanox Confidential and Proprietary -
+ *
+ *  Copyright (C) Apr. 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 ......................................................
+ *
+ *    mad.h -
+ *      Header file for common special QP resources creation code.
+ *
+ *  Creation date:
+ *
+ *  Version: $Id: osmt_mtl_regular_qp.h,v 1.2 2003/03/20 16:05:10 eitan Exp $
+ *
+ *  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. */
+#ifndef __KERNEL__
+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
+
+
+#endif
diff --git a/trunk/ulp/opensm/user/osmtest/osmt_multicast.c b/trunk/ulp/opensm/user/osmtest/osmt_multicast.c
new file mode 100644 (file)
index 0000000..c0ebdef
--- /dev/null
@@ -0,0 +1,3246 @@
+/*
+ * 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$
+ */
+
+/*
+ * Abstract:
+ *    Implementation of Multicast Member testing flow..
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+/* next error code: 16A    */
+#ifndef __WIN__
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_memory.h>
+#include "osmtest.h"
+#ifdef OSM_VENDOR_INTF_MTL
+#include "osmt_inform.h"
+#endif
+
+
+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 = cl_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.
+   */
+
+  cl_memclr( &req, sizeof( req ) );
+  cl_memclr( &user, 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 ) );
+  user.comp_mask = 0;
+
+  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;
+  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_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);
+    cl_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 exist already */
+    if( p_mgids_res != cl_list_end( p_mgids_list ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_query_mcast: ERR 0203: "
+               "MCG MGIDS are the same - invalid MGID : 0x% "
+               PRIx64 " 0x% " 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*)cl_malloc( sizeof(*p_mgrp) );
+    if (!p_mgrp)
+    {
+      osm_log( &p_osmt->log , OSM_LOG_ERROR,
+               "osmt_query_mcast: ERR 0204: "
+               "Could not allocate MCG new.\n");
+      status = IB_ERROR;
+      goto Exit;
+    }
+    cl_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.
+   */
+  cl_memclr( &req, sizeof( req ) );
+  cl_memclr( &user, sizeof( user ) );
+  cl_memclr( &context, sizeof( context ) );
+  cl_memclr( p_res, 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;
+  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_send_mcast_request: ERR 0205: "
+             "ib_query failed (%s).\n", ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  /* ok it worked */
+  cl_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 )
+  {
+    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 */
+  cl_memclr(p_mc_req,sizeof(ib_member_rec_t));
+
+  /*  we leave the MGID to the user */
+  cl_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_INSUFFICIANT_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.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.
+ ***********************************************************************/
+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 IPoIBIsFound=0,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;
+
+
+  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,                      /*  multicat 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
+     },
+  };
+
+
+#ifdef OSM_VENDOR_INTF_MTL
+  ib_inform_info_t         inform_info;
+  osmt_qp_ctx_t  qp_ctx;
+#endif
+
+  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 MCG ...\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;
+
+  }
+
+  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 at SA DB is %d.\n",start_cnt);
+  }
+
+  /* This flow is being added due to bug discovered using Infinicon  stack -
+     The bug was initializing MCast with MTU & RATE min values that does
+     not match the subnet capability , even though that OpenSM
+     reposnds 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 respond 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 (!cl_memcmp(&osm_ipoib_good_mgid,&p_mgrp->mcmember_rec.mgid,sizeof(osm_ipoib_good_mgid)) ||
+        !cl_memcmp(&osm_ts_ipoib_good_mgid,&p_mgrp->mcmember_rec.mgid,sizeof(osm_ts_ipoib_good_mgid)))
+    {
+      IPoIBIsFound=1;
+    }
+    else 
+       mcg_outside_test_cnt++; 
+
+    p_mgrp = (osmtest_mgrp_t*)cl_qmap_next( &p_mgrp->map_item );
+  }
+
+  if (IPoIBIsFound)
+  {
+    /* 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 Infinicon Bug Flow ...\n");
+    /* Try to join first like IPoIB of Infinicon */
+    cl_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: "
+            "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));
+    /* 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 Infinicon - 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 mtu & rate phhysible that will allow check the 
+        exact statement of OpenSM */
+    mtu_phys = p_mc_res->mtu ;
+    rate_phys = p_mc_res->rate ;
+
+    cl_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 02ee : "
+               "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;
+    }
+    else 
+    {
+        mtu_phys = 0 ;
+        rate_phys = 0 ;
+    }
+    /* 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;
+
+  status = osmt_send_mcast_request( p_osmt, 0xee, /*  User Defined query Get */
+                                    &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 2E0 "
+             "Succceed SubnAdmGet with invalid mlid 0x%x.\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);
+  cl_memclr(&mc_req_rec.port_gid.unicast.interface_id,sizeof(ib_net64_t));
+  comp_mask =
+    IB_MCR_COMPMASK_GID;
+
+  status = osmt_send_mcast_request( p_osmt, 0xee, /*  User Defined query Get */
+                                    &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 2E4 "
+             "Succceed SubnAdmGet with invalid port guid .\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 insufficiant comp_mask */
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Join with insufficiant comp mask qkey & pkey (o15.0.1.3)...\n"
+           );
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: "
+           " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+           );
+  /* no MGID */
+  cl_memclr(&mc_req_rec.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_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;
+
+  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: "
+           " Expected Errors:    vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\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 0206: "
+             "Expecetd 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) )
+             );
+    goto Exit;
+  }
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Join with insufficiant comp mask - sl (15.0.1.3)...\n"
+           );
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: "
+           " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+           );
+  /* no MGID */
+  cl_memclr(&mc_req_rec.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_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: "
+           " Expected Errors:    vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\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 0206: "
+             "Expecetd 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) )
+             );
+    goto Exit;
+  }
+
+  osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+  /* no MGID */
+  cl_memclr(&mc_req_rec.mgid,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 insufficiant comp mask - flow label (o15.0.1.3)...\n"
+           );
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: "
+           " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\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;
+
+  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: "
+           " Expected Errors:    vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\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 0206: "
+             "Expecetd 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) )
+             );
+    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 insufficiant comp mask - tclass  (o15.0.1.3)...\n"
+           );
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: "
+           " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\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;
+
+  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: "
+           " Expected Errors:    vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\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 0206: "
+             "Expecetd 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) )
+             );
+    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 insufficiant comp mask - tclass qkey (o15.0.1.3)...\n"
+           );
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: "
+           " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+           );
+  /* no MGID */
+  /* cl_memclr(&mc_req_rec.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_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;
+
+  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: "
+           " Expected Errors:    vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\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 0206: "
+             "Expecetd 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) )
+             );
+    goto Exit;
+  }
+
+#if 0
+  /*  CURRENTLY NOT SUPPORTED !!!! "Unrealizable" condition not available by OSM */
+
+  /*  o15.0.1.8:  */
+  /*  - Request join with irrelevant RATE : get a ERR_INSUFFICIANT_COMPONENTS */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Join with un-realistic 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;
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  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: "
+             "Expecetd 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) )
+             );
+    goto Exit;
+  }
+
+  /* Check Valid value which is unreasonable now */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Join with un-realistic rate 30GB (o15.0.1.8)...\n"
+           );
+
+  /* impossible requested rate */
+  mc_req_rec.rate =
+    IB_PATH_RECORD_RATE_30_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;
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  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: "
+             "Expecetd 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) )
+             );
+    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 then 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;
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  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: "
+             "Expecetd 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) )
+             );
+    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 un-realistic mtu (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;
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  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) )
+             );
+    goto Exit;
+  }
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Join with un-realistic mtu (o15.0.1.8)...\n"
+           );
+/* Checking above max value of MTU which is impossible */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Join with un-realistic mtu : \n\t\tless then 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;
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  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: "
+             "Expecetd 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) )
+             );
+    goto Exit;
+  }
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Join with un-realistic 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;
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  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: "
+             "Expecetd 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) )
+             );
+    goto Exit;
+  }
+
+  /* Check PacketLifeTime as 0 */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Create with un-realistic packet life value less than 0 (o15.0.1.8)...\n"
+           );
+
+  /* impossible requested rate */
+  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;
+
+  status = osmt_send_mcast_request( p_osmt, 1,
+                                    &mc_req_rec,
+                                    comp_mask,
+                                    &res_sa_mad );
+  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: "
+             "Expecetd 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) )
+             );
+    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"
+           );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: "
+           " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\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 */
+  cl_memclr(&mc_req_rec.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_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;
+
+  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: "
+           " Expected Errors:    vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\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 0206: "
+             "Expecetd 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) )
+             );
+    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 at SA DB is %d.\n",middle_cnt);
+    if (middle_cnt != start_cnt)
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_run_mcast_flow: ERR 02ab: "
+               "Got different number of records stored in SA DB (before any creation)\n"
+               "Instead of %d got %d.\n",start_cnt,middle_cnt);
+      status=IB_ERROR;
+      goto Exit;
+    }
+  }
+
+
+  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"
+           );
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: "
+           " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\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 */
+  cl_memclr(&mc_req_rec.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_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;
+
+  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: "
+           " Expected Errors:    vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\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 0206: "
+             "Expecetd 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) )
+             );
+    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"
+           );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: "
+           " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\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 */
+  cl_memclr(&mc_req_rec.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_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;
+
+  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: "
+           " Expected Errors:    vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\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 0206: "
+             "Expecetd 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) )
+             );
+    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 then max RATE \n\t\t"
+           "Third above min MTU , Second less then max MTU \n\t\t"
+           "Fifth exact MTU & RATE physible , Sixth exact RATE physible\n\t\t"
+           "Seventh exact MTU physible (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 0208: "
+             "Fail to create MGC for MGID=0 with higher then minimum RATE.\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+  /* 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 020ab: "
+             "Fail to create MGC for MGID=0 with less then highest RATE.\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+
+  /* 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: "
+             "Fail to create MGC for MGID=0 with less then highest MTU.\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+   /* 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: "
+             "Fail to create MGC for MGID=0 with higher then lowest MTU.\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+   /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */
+   /* Using Exact physible MTU & RATE */
+
+  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: "
+             "Fail to create MGC for MGID=0 with exact MTU & RATE.\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+     /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */
+   /* Using Exact physible RATE */
+
+  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: "
+             "Fail to create MGC for MGID=0 with exact RATE.\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+
+     /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */
+   /* Using Exact physible MTU */
+
+  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 0240: "
+             "Fail to create MGC for MGID=0 with exact MTU.\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+
+
+
+  /*  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 "\n",
+             p_mc_res->mgid
+             );
+    status = IB_ERROR;
+    goto Exit;
+  }
+
+  /* Lets try another multicast request */
+  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 */
+  cl_memclr(&mc_req_rec.mgid,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 0208: "
+             "Fail to create MGC for MGID=0.\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+  /*  o15.0.1.6: */
+  /*  - Create a new MCG with valid requested MGID. */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Checking Create given 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;
+
+  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: "
+             "Fail to create MGC for MGID=0x%016" PRIx64 " : "
+             "0x%016" PRIx64 " (o15.0.1.6)...\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad)),
+             cl_ntoh64(good_mgid.unicast.prefix),
+             cl_ntoh64(good_mgid.unicast.interface_id));
+    goto Exit;
+  }
+
+  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 0211: "
+             "Validating MGID failed. MGID:0x%016" PRIx64 "\n",
+             p_mc_res->mgid
+             );
+    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: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\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: "
+           " Expected Errors:   vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\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 0212: "
+             "Fail to recognize MGID error for MGID=0xFA......\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"
+           );
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: "
+           " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\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 */
+
+  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: "
+           " Expected Errors:  vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\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: "
+             "Fail 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"
+           );
+
+
+
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: "
+           " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+           );
+
+
+  mc_req_rec.mgid = good_mgid;
+
+  mc_req_rec.mgid.raw[0] = 0xEF;
+
+  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: "
+           " Expected Errors:   vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\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 0212: "
+             "Fail to recognize MGID PREFIX error for MGID=0xEF....\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 0210: "
+             "Fail to create MGC for MGID=0x%016" PRIx64 " : "
+             "0x%016" PRIx64 ".\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ),
+             cl_ntoh64(good_mgid.unicast.prefix),
+             cl_ntoh64(good_mgid.unicast.interface_id));
+    goto Exit;
+  }
+
+
+  /* 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: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\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: "
+           " Expected Errors:   vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\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: "
+             "Fail to recognize create with invalid flags value 0x2\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 0210: "
+             "Fail to create MGC for MGID=0xFF02:0:0:0:0:0:0:1.\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+
+
+  /*  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: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+           );
+  mc_req_rec.mgid = good_mgid;
+  mc_req_rec.mgid.raw[12] = 0xFF;
+  mc_req_rec.scope_state = 0x22; /*  link-local scope */
+
+  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: "
+           " Expected Errors:    vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\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: "
+             "Fail to recognize create with JoinState != FullMember\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 invalid 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 0210: "
+             "Fail to create MGC with valid join state 0x3.\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+
+
+  /* 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: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\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: "
+           " Expected Errors:   vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\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: "
+             "Fail to recognize create with JoinState != FullMember\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 with valid join state (o15.0.1.9)...\n"
+           );
+
+  mc_req_rec.mgid = good_mgid;
+  mc_req_rec.mgid.raw[12] = 0xFB;
+  cl_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 0210: "
+             "Fail to create MGC with valid join state 0xF\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+             );
+    goto Exit;
+  }
+
+  /*  o15.0.1.10 - can't check on a single client .-- obsolete -
+      checked by Infinicon 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 */
+  cl_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: "
+             "Fail to join MGC 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 0215: "
+             "Fail to update existing MGID\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 0216: "
+             "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 0218: "
+             "Fail 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 delete succeffully 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 0215: "
+             "Fail to update existing MCG\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 0216: "
+             "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 0215: "
+             "Fail to update existing MGID\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 0216: "
+             "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 0215: "
+             "Fail to update existing MGID\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 0216: "
+             "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: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\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: "
+           " Expected Errors:    vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\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: "
+             "Fail 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: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\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: "
+           " Expected Errors:   vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\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: "
+             "Fail 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 then 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: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\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: "
+           " Expected Errors:   vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\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 02cd: "
+             "Fail 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 0218: "
+             "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 0219: "
+             "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 0218: "
+             "Fail 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 0219: "
+             "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.14)...\n"
+           );
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: "
+           " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+           );
+  mc_req_rec.scope_state = 0x22; /*  use non member - so if no group fail */
+  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: "
+           " Expected Errors:    vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+           );
+  if (status != IB_REMOTE_ERROR)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 0221: "
+             "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: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\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: "
+           " Expected Errors:    vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\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 0222: "
+             "Fail 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 0210: "
+             "Fail to create MGC for 0x%016" PRIx64 " : "
+             "0x%016" PRIx64 ".\n",
+             ib_get_err_str( status ),
+             ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ),
+             cl_ntoh64(good_mgid.unicast.prefix),
+             cl_ntoh64(good_mgid.unicast.interface_id));
+    goto Exit;
+  }
+
+#ifdef OSM_VENDOR_INTF_MTL
+
+  /*  - Register by InformInfo flow to receive trap 67 on MCG delete. */
+  /* bind the QP */
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmt_run_mcast_flow: "
+           "Setting InformInfo for Trap 67 (o15.0.1.14)...\n"
+           );
+  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);
+
+  /* limit to trap 67 from SM */
+  inform_info.lid_range_begin = cl_ntoh16(p_osmt->local_port.sm_lid);
+  inform_info.lid_range_end = cl_ntoh16(p_osmt->local_port.sm_lid);
+  inform_info.g_or_v.generic.trap_num = cl_hton16(67);
+
+  /* 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_mcast_flow: ERR 0127: "
+             "Error posting recv bufs .\n");
+    status = IB_ERROR;
+    goto Exit;
+  }
+  osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+           "osmt_run_mcast_flow: "
+           "Posted recv bufs .\n");
+
+#endif /*  OSM_VENDOR_INTF_MTL */
+
+  /*  - 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;
+  }
+
+#ifdef OSM_VENDOR_INTF_MTL
+
+  /*  - Wait for trap 67. */
+  status = osmt_trap_wait( p_osmt, &qp_ctx);
+
+  /* cleanup */
+  osmt_unbind_inform_qp( p_osmt, &qp_ctx);
+
+  if (status != IB_SUCCESS)
+  {
+    goto Exit;
+  }
+
+#endif
+
+
+  /*  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: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\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: "
+           " Expected Errors:    vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\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: "
+             "Fail 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 un-realistic mtu : \n"
+           "\t\tFirst create new MCG then try to join it \n"
+           "\t\twith unrealistic MTU greater then 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;
+  cl_memclr(&mc_req_rec.mgid,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 02ea "
+             "Failed to create new mgrp.\n");
+    goto Exit;
+  }
+  cl_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 then exist in MCG */
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_mcast_flow: "
+           " Expecting Errors: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
+           );
+  mc_req_rec.mtu = IB_MTU_LEN_4096 | IB_PATH_SELECTOR_GREATER_THAN << 6;
+  cl_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;
+
+  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: "
+           " Expected Errors:    vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+           );
+  if (status == IB_SUCCESS)
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_mcast_flow: ERR 02e4: "
+             "Expecetd 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 at 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);
+  cl_memclr( &context, 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 0007: "
+             "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: "
+               "current 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;
+    }
+  }
+
+  if (remote_port_guid != 0x0)
+  {
+    ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER);
+    cl_memclr(&mc_req_rec.mgid,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);
+    cl_memcpy(&proxy_mgid,&p_mc_res->mgid,sizeof(ib_gid_t));
+
+    /* First try a bad deletion then good one */
+    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;
+    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 02a9: "
+               "Succeed 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;
+    }
+    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 02ab: "
+               "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 then 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;
+      cl_memclr(&mc_req_rec.mgid,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 "
+                   "Succceed Join  with greater mlid then 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);
+        osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+                 "osmt_run_mcast_flow : "
+                 "Added to new MCGroup with Mlid 0x04%x\n",cur_mlid);
+      }
+      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);
+  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 at 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",cnt);
+
+  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 (cl_memcmp(&osm_ipoib_good_mgid,&p_mgrp->mcmember_rec.mgid,sizeof(osm_ipoib_good_mgid)) &&
+        cl_memcmp(&osm_ts_ipoib_good_mgid,&p_mgrp->mcmember_rec.mgid,sizeof(osm_ts_ipoib_good_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 (!cl_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: "
+                 "Fail 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++;
+      }
+    }
+    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 2FF "
+             "GetTable of all records has failed!\n");
+    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)
+  {
+      end_cnt = cl_qmap_count(&p_osmt->exp_subn.mgrp_mlid_tbl);
+      osm_log( &p_osmt->log, OSM_LOG_INFO,
+               "osmt_run_mcast_flow (After Deletion of all MCG): "
+               "Number of MC Records found at SA DB is %d.\n",end_cnt);
+          /* In a single mode we should treat the MCG as ours , if there are groups 
+            that could not be deleted it means that an outside source has used MC (porbably 
+            not from our port as well) , thus we cannot assure (in a single mode) that our 
+            comparison Start vs End count is valid  */
+      if (end_cnt != start_cnt && fail_to_delete_mcg == 0)
+      {
+        osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                 "osmt_run_mcast_flow: ERR 02ab: "
+                 "Got different number of records stored in SA DB at Start got \n\t\t"
+                 " %d , at End got %d\n",
+                 start_cnt,end_cnt);
+        osm_log( &p_osmt->log, OSM_LOG_INFO,
+                 "osmt_run_mcast_flow: "
+                 "At start got %d MCG external groups (not IPoIB) , at end got %d MCG that could not be deleted \n\t\t"
+                 " (registered from different port or different pkey)\n",mcg_outside_test_cnt,fail_to_delete_mcg);
+
+        status=IB_ERROR;
+        goto Exit;
+      }
+  }
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return status;
+}
diff --git a/trunk/ulp/opensm/user/osmtest/osmt_service.c b/trunk/ulp/opensm/user/osmtest/osmt_service.c
new file mode 100644 (file)
index 0000000..1c4a3f1
--- /dev/null
@@ -0,0 +1,1597 @@
+/*
+ * 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$
+ */
+
+/*
+ * 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 $
+ */
+
+/* next error code: 16A    */
+#ifndef __WIN__
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_memory.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));
+
+  cl_memclr( &req, sizeof( req ) );
+  cl_memclr( &context, sizeof( context ) );
+  cl_memclr( &user, sizeof( user ) );
+  cl_memclr( &svc_rec, 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;
+  cl_memclr(&svc_rec.service_key,16*sizeof(uint8_t));
+  svc_rec.service_key[0] = service_key_lsb;
+  cl_memclr(svc_rec.service_name, sizeof(svc_rec.service_name));
+  cl_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 0303: "
+             "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 0364: "
+             "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));
+
+  cl_memclr( &req, sizeof( req ) );
+  cl_memclr( &context, sizeof( context ) );
+  cl_memclr( &user, sizeof( user ) );
+  cl_memclr( &svc_rec, 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;
+  cl_memclr(&svc_rec.service_key,16*sizeof(uint8_t));
+  cl_memcpy(svc_rec.service_key,service_key,16*sizeof(uint8_t));
+  cl_memclr(svc_rec.service_name, sizeof(svc_rec.service_name));
+  cl_memclr(skey, 16*sizeof(uint8_t));
+  cl_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 0303: "
+             "ib_query failed (%s).\n", ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  status = context.result.status;
+
+  /*  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 (cl_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:"
+             "Data mismatch in service_key .\n"
+             );
+    goto Exit;
+  }
+
+  if( status != IB_SUCCESS )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_register_service_with_full_key: ERR 0364: "
+             "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;
+  }
+
+ 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));
+
+  cl_memclr( &req, sizeof( req ) );
+  cl_memclr( &context, sizeof( context ) );
+  cl_memclr( &user, sizeof( user ) );
+  cl_memclr( &svc_rec, 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;
+  cl_memclr(&svc_rec.service_key,16*sizeof(uint8_t));
+  svc_rec.service_key[0] = service_key_lsb;
+
+  /*  Copy data to service_data arrays */
+  cl_memcpy(svc_rec.service_data8,service_data8,16*sizeof(uint8_t));
+  cl_memcpy(svc_rec.service_data16,service_data16,8*sizeof(ib_net16_t));
+  cl_memcpy(svc_rec.service_data32,service_data32,4*sizeof(ib_net32_t));
+  cl_memcpy(svc_rec.service_data64,service_data64,2*sizeof(ib_net64_t));
+
+  cl_memclr(svc_rec.service_name, sizeof(svc_rec.service_name));
+  cl_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 0303: "
+             "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 0364: "
+             "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 (cl_memcmp(service_data8,p_rec->service_data8,16*sizeof(uint8_t)) != 0 ||
+      cl_memcmp(service_data16,p_rec->service_data16,8*sizeof(uint16_t)) != 0 ||
+      cl_memcmp(service_data32,p_rec->service_data32,4*sizeof(uint32_t)) != 0 ||
+      cl_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 ."
+             );
+    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 by 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.
+   */
+  cl_memclr( &svc_rec, sizeof( svc_rec ) );
+  cl_memclr( &req, sizeof( req ) );
+  cl_memclr( &context, sizeof( context ) );
+  cl_memclr( &user, sizeof( user ) );
+  /* set the new service record fields */
+  cl_memclr(svc_rec.service_name, sizeof(svc_rec.service_name));
+  cl_memcpy(svc_rec.service_name, sr_name,
+            (strlen(sr_name)+1)*sizeof(char));
+  svc_rec.service_id = sid;
+  /* prepare the data used for this query */
+  context.p_osmt = p_osmt;
+  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;
+  req.sm_key = 0;
+
+  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 0365: "
+             "ib_query failed (%s).\n", ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  status = context.result.status;
+
+  if( status != IB_SUCCESS )
+  {
+    num_recs = 0;
+    if (status != IB_INVALID_PARAMETER)
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_get_service_by_id_and_name: ERR 0370: "
+               "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_service_by_id_and_name: "
+               "Remote error = %s.\n",
+               ib_get_mad_status_str( osm_madw_get_mad_ptr
+                                      ( context.result.
+                                        p_result_madw ) ) );
+    }
+    goto Exit;
+  }
+  else
+  {
+    num_recs =  context.result.result_cnt;
+  }
+
+  if ( num_recs != rec_num )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_get_service_by_id_and_name: "
+             "Unmatched record number , Expeceted : %d , Got : %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 );
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_get_service_by_id_and_name: "
+           "Found Service Record by 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);
+  *p_out_rec = *p_rec;
+
+ Exit:
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_get_service_by_id_and_name: "
+           "Expected num of records is : %d , Found number of records : %d\n",
+           rec_num,num_recs);
+  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 by 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.
+   */
+  cl_memclr( &svc_rec, sizeof( svc_rec ) );
+  cl_memclr( &req, sizeof( req ) );
+  cl_memclr( &context, sizeof( context ) );
+  cl_memclr( &user, sizeof( user ) );
+  /* set the new service record fields */
+  svc_rec.service_id = sid;
+  /* prepare the data used for this query */
+  context.p_osmt = p_osmt;
+  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;
+  req.sm_key = 0;
+
+  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 0365: "
+             "ib_query failed (%s).\n", ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  status = context.result.status;
+
+  if( status != IB_SUCCESS )
+  {
+    num_recs = 0;
+    if (status != IB_INVALID_PARAMETER)
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_get_service_by_id: ERR 0370: "
+               "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_service_by_id: "
+               "Remote error = %s.\n",
+               ib_get_mad_status_str( osm_madw_get_mad_ptr
+                                      ( context.result.
+                                        p_result_madw ) ) );
+    }
+    goto Exit;
+  }
+  else
+  {
+    num_recs =  context.result.result_cnt;
+  }
+
+  if ( num_recs != rec_num )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_get_service_by_id: "
+             "Unmatched record number , Expeceted : %d , Got : %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 );
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_get_service_by_id: "
+           "Found Service Record by 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);
+  *p_out_rec = *p_rec;
+
+ Exit:
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_get_service_by_id: "
+           "Expected num of records is : %d , Found number of records : %d\n",
+           rec_num,num_recs);
+  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;
+  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 ) )
+  {
+    uint8_t i;
+    osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+             "osmt_get_service_by_name_and_key: "
+             "Getting Service Record by Name and Key :%s.\n",
+             sr_name);
+    for (i=0 ; i<=15 ; i++)
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "Service Key[%u] = %u\n",
+               i,skey[i]);
+  }
+
+  /*
+   * 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.
+   */
+  cl_memclr( &svc_rec, sizeof( svc_rec ) );
+  cl_memclr( &req, sizeof( req ) );
+  cl_memclr( &context, sizeof( context ) );
+  cl_memclr( &user, sizeof( user ) );
+  /* set the new service record fields */
+  cl_memclr(svc_rec.service_name, sizeof(svc_rec.service_name));
+  cl_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.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;
+  req.sm_key = 0;
+
+  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 0365: "
+             "ib_query failed (%s).\n", ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  status = context.result.status;
+
+  if( status != IB_SUCCESS )
+  {
+    num_recs = 0;
+    if (status != IB_INVALID_PARAMETER)
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_get_service_by_name_and_key: ERR 0370: "
+               "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_service_by_name_and_key: "
+               "Remote error = %s.\n",
+               ib_get_mad_status_str( osm_madw_get_mad_ptr
+                                      ( context.result.
+                                        p_result_madw ) ) );
+    }
+    goto Exit;
+  }
+  else
+  {
+    num_recs =  context.result.result_cnt;
+  }
+
+  if ( num_recs != rec_num )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_get_service_by_name_and_key: "
+             "Unmatched record number , Expeceted : %d , Got : %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 );
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_get_service_by_name_and_key: "
+           "Found Service Record by 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);
+  *p_out_rec = *p_rec;
+
+ Exit:
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_get_service_by_name_and_key: "
+           "Expected num of records is : %d , Found number of records : %d\n",
+           rec_num,num_recs);
+  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 by 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.
+   */
+  cl_memclr( &req, sizeof( req ) );
+  cl_memclr( &context, sizeof( context ) );
+
+  context.p_osmt = p_osmt;
+
+  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;
+  cl_memclr(service_name, sizeof(service_name));
+  cl_memcpy(service_name, sr_name, (strlen(sr_name)+1)*sizeof(char));
+  req.p_query_input = service_name;
+  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_service_by_name: ERR 0365: "
+             "ib_query failed (%s).\n", ib_get_err_str( status ) );
+    goto Exit;
+  }
+
+  status = context.result.status;
+
+  if( status != IB_SUCCESS )
+  {
+    /*  The context struct is not init OR result with illegal number of records */
+    num_recs = 0;
+    if (status != IB_INVALID_PARAMETER)
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmt_get_service_by_name: ERR 0370: "
+               "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_service_by_name: "
+               "Remote error = %s.\n",
+               ib_get_mad_status_str( osm_madw_get_mad_ptr
+                                      ( context.result.
+                                        p_result_madw ) ) );
+    }
+    goto Exit;
+  }
+  else
+  {
+    num_recs =  context.result.result_cnt;
+  }
+
+  if ( num_recs != rec_num )
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_get_service_by_name: "
+             "Unmatched record number , Expeceted : %d , Got : %u.\n",
+             rec_num , num_recs);
+    status = IB_REMOTE_ERROR;
+    goto Exit;
+  }
+
+  p_rec = osmv_get_query_svc_rec( context.result.p_result_madw, 0 );
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_get_service_by_name: "
+           "Found Service Record by 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);
+  *p_out_rec = *p_rec;
+
+ Exit:
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmt_get_service_by_name: "
+           "Expected num of records is : %d , Found number of records : %u\n",
+           rec_num,num_recs);
+
+  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_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*)cl_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.
+   */
+  cl_memclr( &req, sizeof( req ) );
+  cl_memclr( &context, 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 0371: "
+             "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 0372: "
+               "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 by 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(p_valid_service_names_arr[j],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 0377: "
+                   "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;
+}
+
+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);
+
+  cl_memclr( &svc_rec, sizeof( svc_rec ) );
+
+  status = osmt_get_service_by_name(p_osmt, sr_name,rec_num, &svc_rec);
+  if (status != IB_SUCCESS)
+  {
+      if (IsServiceExist) 
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                 "osmt_delete_service_by_name: ERR 001 "
+                 "Nothing to delete - fail to find service by name: %s \n", sr_name);
+      else
+      {
+          osm_log( &p_osmt->log, OSM_LOG_INFO,
+                 "osmt_delete_service_by_name: "
+                 "Record Should not exist , i.e BAD flow\n");
+          status = IB_SUCCESS;
+      }
+      goto ExitNoDel;
+  }
+
+  cl_memclr( &req, sizeof( req ) );
+  cl_memclr( &context, sizeof( context ) );
+  cl_memclr( &user, sizeof( user ) );
+
+  /* set the new service record fields */
+  cl_memclr(svc_rec.service_name, sizeof(svc_rec.service_name));
+  cl_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; /*  basicallya 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 0373: "
+             "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_delete_service_by_name: ERR 0374: "
+             "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: "
+               "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;
+  }
+
+ 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++ ) {
+    uint64_t rand1 = rand()-(uint64_t)i;
+    id[i] = abs((int)(pid - rand1));
+    /* Just to be unique any place on any host */
+    sprintf((char*)(service_name[i]),
+            "osmt.srvc.%" PRIu64 ".%" PRIu64 ,rand1,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(0x00000001), /*  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 */
+    cl_memclr (service_data8,16*sizeof(uint8_t));
+    cl_memclr (service_data16,8*sizeof(uint16_t));
+    cl_memclr (service_data32,4*sizeof(uint32_t));
+    cl_memclr (service_data64,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 */
+  cl_memclr (service_key,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);
+
+  status = osmt_get_service_by_name(p_osmt,
+                                    (char*)service_name[0],1, &srv_rec);
+  if (status != IB_SUCCESS)
+  {
+    goto Exit;
+  }
+
+  status = osmt_get_service_by_name(p_osmt,
+                                    (char*)service_name[1],1, &srv_rec);
+  if (status != IB_SUCCESS)
+  {
+    goto Exit;
+  }
+
+  status = osmt_get_service_by_name(p_osmt,
+                                    (char*)service_name[2],1, &srv_rec);
+  if (status != IB_SUCCESS)
+  {
+    goto Exit;
+  }
+
+  /*  Try to get osmt.srvc.4 b4 (there should be 1 records ) and after 10 sec - It should be deleted */
+  status = osmt_get_service_by_name(p_osmt,
+                                    (char*)service_name[3],1, &srv_rec);
+  if (status != IB_SUCCESS)
+  {
+    goto Exit;
+  }
+  sleep(10);
+  status = osmt_get_service_by_name(p_osmt,
+                                    (char*)service_name[3],0, &srv_rec);
+  if (status == IB_SUCCESS)
+  {
+    goto Exit;
+  }
+  /*  Check that for the current Service ID only one record exists */
+  status = osmt_get_service_by_id(p_osmt, 1, cl_ntoh64(id[5]),&srv_rec);
+  if (status != IB_SUCCESS)
+  {
+    goto Exit;
+  }
+
+  /*  Bad Flow of Get with invalid Service ID */
+  status = osmt_get_service_by_id(p_osmt, 0,cl_ntoh64(id[7]),&srv_rec);
+  if (status == IB_SUCCESS)
+  {
+    goto Exit;
+  }
+  /*  Check that for correct name and ID we get record set b4 */
+  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)
+  {
+    goto Exit;
+  }
+  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)
+  {
+    goto Exit;
+  }
+
+  /* Bad Flow of Get with valid name and invalid ID */
+  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)
+  {
+    goto Exit;
+  }
+  /*  Bad Flow of Get with unmatched name (exists but not with the following ID) and valid ID */
+  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)
+  {
+    goto Exit;
+  }
+
+  status = osmt_get_service_by_name(p_osmt,
+                                    (char*)service_name[4],0, &srv_rec);
+  if (status == IB_SUCCESS)
+  {
+    goto Exit;
+  }
+  /*  Bad Flow : Check that getting osmt.srvc.6 brings no records since another service has been updated with the same ID - osmt.srvc.7 */
+  status = osmt_get_service_by_name(p_osmt,
+                                    (char*)service_name[5],0, &srv_rec);
+  if (status == IB_SUCCESS)
+  {
+    goto Exit;
+  }
+  /*  Check that getting osmt.srvc.7 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)
+  {
+    goto Exit;
+  }
+
+  /*  Test Service Key */
+  cl_memclr(service_key,16*sizeof(uint8_t));
+  status = osmt_get_service_by_name_and_key (p_osmt ,
+                                             (char*)service_name[5],
+                                             0, service_key,&srv_rec);  
+  if (status == IB_SUCCESS)
+  {
+    goto Exit;
+  }
+  else
+  {
+    status = IB_SUCCESS;
+  }
+  status = osmt_get_service_by_name_and_key (p_osmt ,
+                                             (char*)service_name[6],
+                                             0, service_key,&srv_rec);
+  if (status == IB_SUCCESS)
+  {
+    goto Exit;
+  }
+  else
+  {
+    status = IB_SUCCESS;
+  }
+      
+  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],
+                                             0, service_key,&srv_rec);
+  if (status == IB_SUCCESS)
+  {
+    goto Exit;
+  }
+  else
+  {
+    status = IB_SUCCESS;
+  }
+
+#ifdef VENDOR_RMPP_SUPPORT
+
+     
+  cl_memcpy(&service_valid_names[0],&service_name[0],sizeof(uint8_t)*64);
+  cl_memcpy(&service_valid_names[1],&service_name[2],sizeof(uint8_t)*64);
+  cl_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)
+  {
+    goto Exit;
+  }
+
+
+#endif
+  status = osmt_delete_service_by_name(p_osmt,1,
+                                       (char*)service_name[0],1);
+  if (status != IB_SUCCESS)
+  {
+    goto Exit;
+  }
+
+  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 001 "
+             "Expected not to find osmt.srvc.1 \n");
+    status = IB_ERROR;
+    goto Exit;
+  }
+  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+           "osmt_run_service_records_flow: "
+           "IS EXPECTED ERR ^^^^\n");
+
+  sleep(3);
+
+  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 001 "
+             "Expected not to find osmt.srvc.2 \n");
+    status = IB_ERROR;
+    goto Exit;
+  }
+  else
+  {
+    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+             "osmt_run_service_records_flow: "
+             "IS EXPECTED ERR ^^^^\n");
+    status = IB_SUCCESS;
+  }
+
+  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 001 "
+             "Expected to find service osmt.srvc.3\n" );
+    goto Exit;
+  }
+  status = osmt_delete_service_by_name(p_osmt,1,
+                                       (char*)service_name[6],1);
+  if (status != IB_SUCCESS)
+  {
+    goto Exit;
+  }
+
+  /*  Bad Flow */
+  status = osmt_delete_service_by_name(p_osmt,0,
+                                       (char*)service_name[5],1);
+  if (status == IB_SUCCESS)
+  {
+    goto Exit;
+  }
+
+  status = osmt_delete_service_by_name(p_osmt,1,
+                                       (char*)service_name[2],1);
+  if (status != IB_SUCCESS)
+  {
+    goto Exit;
+  }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return status;
+}
+
diff --git a/trunk/ulp/opensm/user/osmtest/osmt_slvl_vl_arb.c b/trunk/ulp/opensm/user/osmtest/osmt_slvl_vl_arb.c
new file mode 100644 (file)
index 0000000..89707c2
--- /dev/null
@@ -0,0 +1,543 @@
+/*
+ * 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$
+ */
+
+#ifdef OSM_VENDOR_INTF_MTL
+
+/*
+ * Abstract:
+ *    Implementation of SLtoVL and VL Arbitration testing flow..
+ *    Top level is osmt_run_slvl_vlarbs_records_flow:
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+/* next error code: 16A    */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_memory.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_port_info );
+
+  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, osmtest_get_port_rec );
+
+  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.
+   */
+  cl_memclr( &req, sizeof( req ) );
+  cl_memclr( &user, sizeof( user ) );
+  cl_memclr( &context, 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 )
+    {
+      if (status != IB_INVALID_PARAMETER)
+        {
+          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);
+  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, osmtest_write_all_path_recs );
+
+  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
+   * for each pair that are not switch ports get the path record
+   */
+
+  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 numbr 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: "
+                       "Fail 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: "
+                       "Fail 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_port_info );
+
+  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, 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, osmtest_get_port_rec );
+
+  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.
+   */
+  cl_memclr( &req, sizeof( req ) );
+  cl_memclr( &user, sizeof( user ) );
+  cl_memclr( &context, 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 )
+    {
+      if (status != IB_INVALID_PARAMETER)
+        {
+          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);
+  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 );
+
+  /*
+   * Go over all ports that exist in the subnet
+   * for each pair that are not switch ports 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 numbr 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: "
+                     "Fail 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: "
+                     "Fail 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: "
+                       "Fail 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;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmt_run_vlarb_records_flow );
+
+  fh = fopen("vl_arbs.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;
+    }
+
+ Exit:
+  fclose(fh);
+  OSM_LOG_EXIT( &p_osmt->log );
+  return status;
+}
+
+#endif /*  OSM_VENDOR_INTF_MTL */
+
diff --git a/trunk/ulp/opensm/user/osmtest/osmtest.c b/trunk/ulp/opensm/user/osmtest/osmtest.c
new file mode 100644 (file)
index 0000000..b88cf79
--- /dev/null
@@ -0,0 +1,6272 @@
+/*
+ * 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$
+ */
+
+/* TODO : Check why we dont free the cl_qmap_items we store when reading DB */
+
+/*
+ * Abstract:
+ *    Implementation of osmtest_t.
+ * This object represents the opensm super object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ *    Linux User Mode
+ *
+ * $Revision: 1.10 $
+ */
+#ifdef __WIN__
+#pragma warning(disable : 4996)
+#endif
+
+/* next error code: 16A    */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_memory.h>
+#include "osmtest.h"
+#include <complib/cl_timer.h> 
+
+
+#ifdef LINUX
+#define strnicmp strncasecmp
+#endif
+
+#define POOL_MIN_ITEMS  64
+#define GUID_ARRAY_SIZE 64
+
+typedef enum _osmtest_token_val
+  {
+    OSMTEST_TOKEN_COMMENT = 0,
+    OSMTEST_TOKEN_END,
+    OSMTEST_TOKEN_DEFINE_NODE,
+    OSMTEST_TOKEN_DEFINE_PORT,
+    OSMTEST_TOKEN_DEFINE_PATH,
+    OSMTEST_TOKEN_DEFINE_LINK,
+    OSMTEST_TOKEN_LID,
+    OSMTEST_TOKEN_BASE_VERSION,
+    OSMTEST_TOKEN_CLASS_VERSION,
+    OSMTEST_TOKEN_NODE_TYPE,
+    OSMTEST_TOKEN_NUM_PORTS,
+    OSMTEST_TOKEN_SYS_GUID,
+    OSMTEST_TOKEN_NODE_GUID,
+    OSMTEST_TOKEN_PORT_GUID,
+    OSMTEST_TOKEN_PARTITION_CAP,
+    OSMTEST_TOKEN_DEVICE_ID,
+    OSMTEST_TOKEN_REVISION,
+    OSMTEST_TOKEN_PORT_NUM,
+    OSMTEST_TOKEN_VENDOR_ID,
+    OSMTEST_TOKEN_DGID,
+    OSMTEST_TOKEN_SGID,
+    OSMTEST_TOKEN_DLID,
+    OSMTEST_TOKEN_SLID,
+    OSMTEST_TOKEN_HOP_FLOW_RAW,
+    OSMTEST_TOKEN_TCLASS,
+    OSMTEST_TOKEN_NUM_PATH,
+    OSMTEST_TOKEN_PKEY,
+    OSMTEST_TOKEN_SL,
+    OSMTEST_TOKEN_RATE,
+    OSMTEST_TOKEN_PKT_LIFE,
+    OSMTEST_TOKEN_PREFERENCE,
+    OSMTEST_TOKEN_MKEY,
+    OSMTEST_TOKEN_SUBN_PREF,
+    OSMTEST_TOKEN_BASE_LID,
+    OSMTEST_TOKEN_SM_BASE_LID,
+    OSMTEST_TOKEN_CAP_MASK,
+    OSMTEST_TOKEN_DIAG_CODE,
+    OSMTEST_TOKEN_MKEY_LEASE_PER,
+    OSMTEST_TOKEN_LOC_PORT_NUM,
+    OSMTEST_TOKEN_LINK_WID_EN,
+    OSMTEST_TOKEN_LINK_WID_SUP,
+    OSMTEST_TOKEN_LINK_WID_ACT,
+    OSMTEST_TOKEN_LINK_SPEED_SUP,
+    OSMTEST_TOKEN_PORT_STATE,
+    OSMTEST_TOKEN_STATE_INFO2,
+    OSMTEST_TOKEN_MKEY_PROT_BITS,
+    OSMTEST_TOKEN_LMC,
+    OSMTEST_TOKEN_LINK_SPEED,
+    OSMTEST_TOKEN_MTU_SMSL,
+    OSMTEST_TOKEN_VL_CAP,
+    OSMTEST_TOKEN_VL_HIGH_LIMIT,
+    OSMTEST_TOKEN_VL_ARB_HIGH_CAP,
+    OSMTEST_TOKEN_VL_ARB_LOW_CAP,
+    OSMTEST_TOKEN_MTU_CAP,
+    OSMTEST_TOKEN_VL_STALL_LIFE,
+    OSMTEST_TOKEN_VL_ENFORCE,
+    OSMTEST_TOKEN_MKEY_VIOL,
+    OSMTEST_TOKEN_PKEY_VIOL,
+    OSMTEST_TOKEN_QKEY_VIOL,
+    OSMTEST_TOKEN_GUID_CAP,
+    OSMTEST_TOKEN_SUBN_TIMEOUT,
+    OSMTEST_TOKEN_RESP_TIME_VAL,
+    OSMTEST_TOKEN_ERR_THRESHOLD,
+    OSMTEST_TOKEN_MTU,
+    OSMTEST_TOKEN_UNKNOWN
+  }
+osmtest_token_val_t;
+
+typedef struct _osmtest_token
+{
+  osmtest_token_val_t val;
+  size_t str_size;
+  const char *str;
+
+}
+osmtest_token_t;
+
+const osmtest_token_t token_array[] = {
+  {OSMTEST_TOKEN_COMMENT, 1, "#"},
+  {OSMTEST_TOKEN_END, 3, "END"},
+  {OSMTEST_TOKEN_DEFINE_NODE, 11, "DEFINE_NODE"},
+  {OSMTEST_TOKEN_DEFINE_PORT, 11, "DEFINE_PORT"},
+  {OSMTEST_TOKEN_DEFINE_PATH, 11, "DEFINE_PATH"},
+  {OSMTEST_TOKEN_DEFINE_LINK, 11, "DEFINE_LINK"},
+  {OSMTEST_TOKEN_LID, 3, "LID"},
+  {OSMTEST_TOKEN_BASE_VERSION, 12, "BASE_VERSION"},
+  {OSMTEST_TOKEN_CLASS_VERSION, 13, "CLASS_VERSION"},
+  {OSMTEST_TOKEN_NODE_TYPE, 9, "NODE_TYPE"},
+  {OSMTEST_TOKEN_NUM_PORTS, 9, "NUM_PORTS"},
+  {OSMTEST_TOKEN_SYS_GUID, 8, "SYS_GUID"},
+  {OSMTEST_TOKEN_NODE_GUID, 9, "NODE_GUID"},
+  {OSMTEST_TOKEN_PORT_GUID, 9, "PORT_GUID"},
+  {OSMTEST_TOKEN_PARTITION_CAP, 13, "PARTITION_CAP"},
+  {OSMTEST_TOKEN_DEVICE_ID, 9, "DEVICE_ID"},
+  {OSMTEST_TOKEN_REVISION, 8, "REVISION"},
+  {OSMTEST_TOKEN_PORT_NUM, 8, "PORT_NUM"},
+  {OSMTEST_TOKEN_VENDOR_ID, 9, "VENDOR_ID"},
+  {OSMTEST_TOKEN_DGID, 4, "DGID"},
+  {OSMTEST_TOKEN_SGID, 4, "SGID"},
+  {OSMTEST_TOKEN_DLID, 4, "DLID"},
+  {OSMTEST_TOKEN_SLID, 4, "SLID"},
+  {OSMTEST_TOKEN_HOP_FLOW_RAW, 12, "HOP_FLOW_RAW"},
+  {OSMTEST_TOKEN_TCLASS, 6, "TCLASS"},
+  {OSMTEST_TOKEN_NUM_PATH, 8, "NUM_PATH"},
+  {OSMTEST_TOKEN_PKEY, 4, "PKEY"},
+  {OSMTEST_TOKEN_SL, 2, "SL"},
+  {OSMTEST_TOKEN_RATE, 4, "RATE"},
+  {OSMTEST_TOKEN_PKT_LIFE, 8, "PKT_LIFE"},
+  {OSMTEST_TOKEN_PREFERENCE, 10, "PREFERENCE"},
+  {OSMTEST_TOKEN_MKEY, 4, "M_KEY"},
+  {OSMTEST_TOKEN_SUBN_PREF, 13, "SUBNET_PREFIX"},
+  {OSMTEST_TOKEN_BASE_LID, 8, "BASE_LID"},
+  {OSMTEST_TOKEN_SM_BASE_LID, 18, "MASTER_SM_BASE_LID"},
+  {OSMTEST_TOKEN_CAP_MASK, 15, "CAPABILITY_MASK"},
+  {OSMTEST_TOKEN_DIAG_CODE, 9, "DIAG_CODE"},
+  {OSMTEST_TOKEN_MKEY_LEASE_PER, 18, "m_key_lease_period"},
+  {OSMTEST_TOKEN_LOC_PORT_NUM, 14 , "local_port_num"},
+  {OSMTEST_TOKEN_LINK_WID_EN, 18 , "link_width_enabled"},
+  {OSMTEST_TOKEN_LINK_WID_SUP, 20 , "link_width_supported"},
+  {OSMTEST_TOKEN_LINK_WID_ACT, 17 , "link_width_active"},
+  {OSMTEST_TOKEN_LINK_SPEED_SUP, 20 , "link_speed_supported"},
+  {OSMTEST_TOKEN_PORT_STATE, 10 , "port_state"},
+  {OSMTEST_TOKEN_STATE_INFO2, 10 , "state_info2"},
+  {OSMTEST_TOKEN_MKEY_PROT_BITS, 3 , "mpb"},
+  {OSMTEST_TOKEN_LMC, 3 , "lmc"},
+  {OSMTEST_TOKEN_LINK_SPEED, 10 , "link_speed"},
+  {OSMTEST_TOKEN_MTU_SMSL, 8 , "mtu_smsl"},
+  {OSMTEST_TOKEN_VL_CAP, 6 , "vl_cap"},
+  {OSMTEST_TOKEN_VL_HIGH_LIMIT, 13 , "vl_high_limit"},
+  {OSMTEST_TOKEN_VL_ARB_HIGH_CAP, 15, "vl_arb_high_cap"},
+  {OSMTEST_TOKEN_VL_ARB_LOW_CAP,  14, "vl_arb_low_cap"},
+  {OSMTEST_TOKEN_MTU_CAP, 7, "mtu_cap"},
+  {OSMTEST_TOKEN_VL_STALL_LIFE,   13, "vl_stall_life"},
+  {OSMTEST_TOKEN_VL_ENFORCE, 10,  "vl_enforce"},
+  {OSMTEST_TOKEN_MKEY_VIOL, 16,  "m_key_violations"},
+  {OSMTEST_TOKEN_PKEY_VIOL, 16,  "p_key_violations"},
+  {OSMTEST_TOKEN_QKEY_VIOL, 16,  "q_key_violations"},
+  {OSMTEST_TOKEN_GUID_CAP, 8,  "guid_cap"},
+  {OSMTEST_TOKEN_SUBN_TIMEOUT, 14,  "subnet_timeout"},
+  {OSMTEST_TOKEN_RESP_TIME_VAL, 15, "resp_time_value"},
+  {OSMTEST_TOKEN_ERR_THRESHOLD, 15, "error_threshold"},
+  {OSMTEST_TOKEN_MTU, 3, "MTU"}, /*  must be after the other mtu... tokens. */
+  {OSMTEST_TOKEN_UNKNOWN, 0, ""} /* must be last entry */
+};
+
+#define IB_MAD_STATUS_CLASS_MASK       (CL_HTON16(0xFF00))
+
+static const char ib_mad_status_str_busy[] = "IB_MAD_STATUS_BUSY";
+static const char ib_mad_status_str_redirect[] = "IB_MAD_STATUS_REDIRECT";
+static const char ib_mad_status_str_unsup_class_ver[] =
+"IB_MAD_STATUS_UNSUP_CLASS_VER";
+static const char ib_mad_status_str_unsup_method[] =
+"IB_MAD_STATUS_UNSUP_METHOD";
+static const char ib_mad_status_str_unsup_method_attr[] =
+"IB_MAD_STATUS_UNSUP_METHOD_ATTR";
+static const char ib_mad_status_str_invalid_field[] =
+"IB_MAD_STATUS_INVALID_FIELD";
+static const char ib_mad_status_str_no_resources[] =
+"IB_SA_MAD_STATUS_NO_RESOURCES";
+static const char ib_mad_status_str_req_invalid[] =
+"IB_SA_MAD_STATUS_REQ_INVALID";
+static const char ib_mad_status_str_no_records[] =
+"IB_SA_MAD_STATUS_NO_RECORDS";
+static const char ib_mad_status_str_too_many_records[] =
+"IB_SA_MAD_STATUS_TOO_MANY_RECORDS";
+static const char ib_mad_status_str_invalid_gid[] =
+"IB_SA_MAD_STATUS_INVALID_GID";
+static const char ib_mad_status_str_insuf_comps[] =
+"IB_SA_MAD_STATUS_INSUF_COMPS";
+static const char generic_or_str[] = " | ";
+
+/**********************************************************************
+ **********************************************************************/
+const char *
+ib_get_mad_status_str( IN const ib_mad_t * const p_mad )
+{
+  static char line[512];
+  uint32_t offset = 0;
+  ib_net16_t status;
+  boolean_t first = TRUE;
+
+  line[offset] = '\0';
+
+  status = ( ib_net16_t ) ( p_mad->status & IB_SMP_STATUS_MASK );
+
+  if( status == 0 )
+    {
+      strcat( &line[offset], "IB_SUCCESS" );
+      return ( line );
+    }
+
+  if( status & IB_MAD_STATUS_BUSY )
+    {
+      strcat( &line[offset], ib_mad_status_str_busy );
+      offset += sizeof( ib_mad_status_str_busy );
+    }
+  if( status & IB_MAD_STATUS_REDIRECT )
+    {
+      if( !first )
+        {
+          strcat( &line[offset], generic_or_str );
+          offset += sizeof( generic_or_str ) - 1;
+        }
+      first = FALSE;
+      strcat( &line[offset], ib_mad_status_str_redirect );
+      offset += sizeof( ib_mad_status_str_redirect ) - 1;
+    }
+  if( status & IB_MAD_STATUS_UNSUP_CLASS_VER )
+    {
+      if( !first )
+        {
+          strcat( &line[offset], generic_or_str );
+          offset += sizeof( generic_or_str ) - 1;
+        }
+      first = FALSE;
+      strcat( &line[offset], ib_mad_status_str_unsup_class_ver );
+      offset += sizeof( ib_mad_status_str_unsup_class_ver ) - 1;
+    }
+  if( status & IB_MAD_STATUS_UNSUP_METHOD )
+    {
+      if( !first )
+        {
+          strcat( &line[offset], generic_or_str );
+          offset += sizeof( generic_or_str ) - 1;
+        }
+      first = FALSE;
+      strcat( &line[offset], ib_mad_status_str_unsup_method );
+      offset += sizeof( ib_mad_status_str_unsup_method ) - 1;
+    }
+  if( status & IB_MAD_STATUS_UNSUP_METHOD_ATTR )
+    {
+      if( !first )
+        {
+          strcat( &line[offset], generic_or_str );
+          offset += sizeof( generic_or_str ) - 1;
+        }
+      first = FALSE;
+      strcat( &line[offset], ib_mad_status_str_unsup_method_attr );
+      offset += sizeof( ib_mad_status_str_unsup_method_attr ) - 1;
+    }
+  if( status & IB_MAD_STATUS_INVALID_FIELD )
+    {
+      if( !first )
+        {
+          strcat( &line[offset], generic_or_str );
+          offset += sizeof( generic_or_str ) - 1;
+        }
+      first = FALSE;
+      strcat( &line[offset], ib_mad_status_str_invalid_field );
+      offset += sizeof( ib_mad_status_str_invalid_field ) - 1;
+    }
+  if( ( status & IB_MAD_STATUS_CLASS_MASK ) ==
+      IB_SA_MAD_STATUS_NO_RESOURCES )
+    {
+      if( !first )
+        {
+          strcat( &line[offset], generic_or_str );
+          offset += sizeof( generic_or_str ) - 1;
+        }
+      first = FALSE;
+      strcat( &line[offset], ib_mad_status_str_no_resources );
+      offset += sizeof( ib_mad_status_str_no_resources ) - 1;
+    }
+  if( ( status & IB_MAD_STATUS_CLASS_MASK ) ==
+      IB_SA_MAD_STATUS_REQ_INVALID )
+    {
+      if( !first )
+        {
+          strcat( &line[offset], generic_or_str );
+          offset += sizeof( generic_or_str ) - 1;
+        }
+      first = FALSE;
+      strcat( &line[offset], ib_mad_status_str_req_invalid );
+      offset += sizeof( ib_mad_status_str_req_invalid ) - 1;
+    }
+  if( ( status & IB_MAD_STATUS_CLASS_MASK ) == IB_SA_MAD_STATUS_NO_RECORDS )
+    {
+      if( !first )
+        {
+          strcat( &line[offset], generic_or_str );
+          offset += sizeof( generic_or_str ) - 1;
+        }
+      first = FALSE;
+      strcat( &line[offset], ib_mad_status_str_no_records );
+      offset += sizeof( ib_mad_status_str_no_records ) - 1;
+    }
+  if( ( status & IB_MAD_STATUS_CLASS_MASK ) ==
+      IB_SA_MAD_STATUS_TOO_MANY_RECORDS )
+    {
+      if( !first )
+        {
+          strcat( &line[offset], generic_or_str );
+          offset += sizeof( generic_or_str ) - 1;
+        }
+      first = FALSE;
+      strcat( &line[offset], ib_mad_status_str_too_many_records );
+      offset += sizeof( ib_mad_status_str_too_many_records ) - 1;
+    }
+  if( ( status & IB_MAD_STATUS_CLASS_MASK ) ==
+      IB_SA_MAD_STATUS_INVALID_GID )
+    {
+      if( !first )
+        {
+          strcat( &line[offset], generic_or_str );
+          offset += sizeof( generic_or_str ) - 1;
+        }
+      first = FALSE;
+      strcat( &line[offset], ib_mad_status_str_invalid_gid );
+      offset += sizeof( ib_mad_status_str_invalid_gid ) - 1;
+    }
+  if( ( status & IB_MAD_STATUS_CLASS_MASK ) ==
+      IB_SA_MAD_STATUS_INSUF_COMPS )
+    {
+      if( !first )
+        {
+          strcat( &line[offset], generic_or_str );
+          offset += sizeof( generic_or_str ) - 1;
+        }
+      first = FALSE;
+      strcat( &line[offset], ib_mad_status_str_insuf_comps );
+      offset += sizeof( ib_mad_status_str_insuf_comps ) - 1;
+    }
+
+  return ( line );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+subnet_construct( IN subnet_t * const p_subn )
+{
+  cl_qmap_init( &p_subn->link_tbl );
+  cl_qmap_init( &p_subn->node_lid_tbl );
+  cl_qmap_init( &p_subn->node_guid_tbl );
+  /*  NO WAY TO HAVE UNIQUE PORT BY LID OR GUID */
+  /*  cl_qmap_init( &p_subn->port_lid_tbl ); */
+  /*  cl_qmap_init( &p_subn->port_guid_tbl ); */
+  /*  port key is a lid and num pair */
+  cl_qmap_init( &p_subn->mgrp_mlid_tbl );
+  cl_qmap_init( &p_subn->port_key_tbl );
+  cl_qmap_init( &p_subn->path_tbl );
+}
+
+/**********************************************************************
+ **********************************************************************/
+cl_status_t
+subnet_init( IN subnet_t * const p_subn )
+{
+  cl_status_t status = IB_SUCCESS;
+
+  subnet_construct( p_subn );
+
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osmtest_construct( IN osmtest_t * const p_osmt )
+{
+  cl_memclr( p_osmt, sizeof( *p_osmt ) );
+  osm_log_construct( &p_osmt->log );
+  subnet_construct( &p_osmt->exp_subn );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osmtest_destroy( IN osmtest_t * const p_osmt )
+{
+    cl_map_item_t                      *p_next_item,*p_item;
+    
+    /* Currently there is a problem with IBAL exit flow - memory overrun , so we bypass the vendor deletion
+       Since it's already will be cleaned by the Windows OS . */
+#ifndef WIN32
+       if( p_osmt->p_vendor )
+    {
+      osm_vendor_delete( &p_osmt->p_vendor );
+    }
+#endif
+
+  cl_qpool_destroy( &p_osmt->port_pool );
+  cl_qpool_destroy( &p_osmt->node_pool );
+
+
+  /* destroy the qmap tables */
+  p_next_item = cl_qmap_head( &p_osmt->exp_subn.link_tbl );
+  while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.link_tbl ) )
+  {
+    p_item = p_next_item;
+    p_next_item = cl_qmap_next( p_item );
+    cl_free( p_item );
+  }
+  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_free( p_item );
+  }
+  p_next_item = cl_qmap_head( &p_osmt->exp_subn.node_guid_tbl );
+  while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.node_guid_tbl ) )
+  {
+    p_item = p_next_item;
+    p_next_item = cl_qmap_next( p_item );
+    cl_free( p_item );
+  }
+
+  p_next_item = cl_qmap_head( &p_osmt->exp_subn.node_lid_tbl );
+  while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.node_lid_tbl ) )
+  {
+    p_item = p_next_item;
+    p_next_item = cl_qmap_next( p_item );
+    cl_free( p_item );
+  }
+
+  p_next_item = cl_qmap_head( &p_osmt->exp_subn.path_tbl );
+  while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.path_tbl ) )
+  {
+    p_item = p_next_item;
+    p_next_item = cl_qmap_next( p_item );
+    cl_free( p_item );
+  }
+  p_next_item = cl_qmap_head( &p_osmt->exp_subn.port_key_tbl );
+  while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.port_key_tbl ) )
+  {
+    p_item = p_next_item;
+    p_next_item = cl_qmap_next( p_item );
+    cl_free( p_item );
+  }
+
+
+
+  osm_log_destroy( &p_osmt->log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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
+              )
+{
+  ib_api_status_t status;
+
+  /* Can't use log macros here, since we're initializing the log. */
+  osmtest_construct( p_osmt );
+
+  status = osm_log_init( &p_osmt->log, p_opt->force_log_flush,
+                         0x0001, p_opt->log_file );
+  if( status != IB_SUCCESS )
+    return ( status );
+  /* but we do not want any extra staff here */
+  osm_log_set_level( &p_osmt->log, log_flags );
+
+  osm_log( &p_osmt->log, OSM_LOG_FUNCS,
+           "osmtest_init: [\n" );
+
+  p_osmt->opt = *p_opt;
+
+  status = cl_qpool_init( &p_osmt->node_pool, POOL_MIN_ITEMS, 0,
+                          POOL_MIN_ITEMS, sizeof( node_t ), NULL, NULL,
+                          NULL );
+  CL_ASSERT( status == CL_SUCCESS );
+
+  status = cl_qpool_init( &p_osmt->port_pool, POOL_MIN_ITEMS, 0,
+                          POOL_MIN_ITEMS, sizeof( port_t ), NULL, NULL,
+                          NULL );
+  CL_ASSERT( status == CL_SUCCESS );
+
+  p_osmt->p_vendor = osm_vendor_new( &p_osmt->log,
+                                     p_opt->transaction_timeout );
+
+  if( p_osmt->p_vendor == NULL )
+    {
+      status = IB_INSUFFICIENT_RESOURCES;
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_init: ERR 0001: "
+               "Unable to allocate vendor object" );
+      goto Exit;
+    }
+
+  osm_mad_pool_construct( &p_osmt->mad_pool );
+  status = osm_mad_pool_init(
+                             &p_osmt->mad_pool, &p_osmt->log );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+ Exit:
+  osm_log( &p_osmt->log, OSM_LOG_FUNCS,
+           "osmtest_init: ]\n" );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osmtest_query_res_cb( IN osmv_query_res_t * p_rec )
+{
+  osmtest_req_context_t *const p_ctxt =
+    ( osmtest_req_context_t * ) p_rec->query_context;
+  osmtest_t *const p_osmt = p_ctxt->p_osmt;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_query_res_cb );
+
+  p_ctxt->result = *p_rec;
+
+  if( p_rec->status != IB_SUCCESS )
+    {
+      if ( p_rec->status != IB_INVALID_PARAMETER )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_query_res_cb: ERR 0003: "
+                   "Error on query (%s).\n", ib_get_err_str( p_rec->status ) );
+        }
+    }
+
+  OSM_LOG_EXIT( &p_osmt->log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 status = IB_SUCCESS;
+  osmv_user_query_t user;
+  osmv_query_req_t req;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_get_all_recs );
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+               "osmtest_get_all_recs: "
+               "Getting all %s records.\n", ib_get_sa_attr_str( attr_id ) );
+    }
+
+  /*
+   * Do a blocking query for all NodeRecords in the subnet.
+   * The result is returned in the result field of the caller's
+   * context structure.
+   *
+   * The query structures are locals.
+   */
+  cl_memclr( &req, sizeof( req ) );
+  cl_memclr( &user, sizeof( user ) );
+
+  p_context->p_osmt = p_osmt;
+  user.attr_id = attr_id;
+  user.attr_offset = cl_ntoh16( ( uint16_t ) ( attr_size >> 3 ) );
+
+  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 = p_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,
+               "osmtest_get_all_recs: ERR 0004: "
+               "ib_query failed (%s).\n", ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+  status = p_context->result.status;
+
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_get_all_recs: ERR 0064: "
+               "ib_query failed (%s).\n", ib_get_err_str( status ) );
+
+      if( status == IB_REMOTE_ERROR )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_get_all_recs: "
+                   "Remote error = %s.\n",
+                   ib_get_mad_status_str( osm_madw_get_mad_ptr
+                                          ( p_context->result.
+                                            p_result_madw ) ) );
+        }
+      goto Exit;
+    }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_validate_sa_class_port_info( IN osmtest_t * const p_osmt)
+{
+  ib_api_status_t status = IB_SUCCESS;
+  osmv_query_req_t req;
+  ib_class_port_info_t *p_cpi;
+  osmtest_req_context_t context;
+  osmtest_req_context_t *p_context = &context;
+  ib_sa_mad_t           *p_resp_sa_madp;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_get_sa_class_port_info );
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "osmtest_validate_sa_class_port_info: "
+               "Getting Class Port Info\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.
+   */
+  cl_memclr( &req, sizeof( req ) );
+
+  p_context->p_osmt = p_osmt;
+  req.query_type = OSMV_QUERY_CLASS_PORT_INFO;
+  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 = p_context;
+  req.pfn_query_cb = osmtest_query_res_cb;
+  req.p_query_input = 0;
+  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,
+               "osmtest_validate_sa_class_port_info: ERR 0065: "
+               "ib_query failed (%s).\n", ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+  status = p_context->result.status;
+
+  if( status != IB_SUCCESS )
+    {
+      if (status != IB_INVALID_PARAMETER)
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_validate_sa_class_port_info: ERR 0070: "
+                   "ib_query failed (%s).\n", ib_get_err_str( status ) );
+        }
+      if( status == IB_REMOTE_ERROR )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_validate_sa_class_port_info: "
+                   "Remote error = %s.\n",
+                   ib_get_mad_status_str( osm_madw_get_mad_ptr
+                                          ( p_context->result.
+                                            p_result_madw ) ) );
+        }
+      goto Exit;
+    }
+
+  /* ok we got it so please print it out */
+  p_resp_sa_madp = (ib_sa_mad_t*)osm_madw_get_mad_ptr(context.result.p_result_madw);
+  p_cpi = (ib_class_port_info_t*)ib_sa_mad_get_payload_ptr(p_resp_sa_madp );
+
+  osm_log( &p_osmt->log, OSM_LOG_INFO,
+           "osmtest_validate_sa_class_port_info:\n-----------------------------\nSA Class Port Info:\n"
+           " base_ver:%u\n class_ver:%u\n cap_mask:0x%X\n resp_time_val:0x%X\n-----------------------------\n",
+           p_cpi->base_ver, p_cpi->class_ver, p_cpi->cap_mask, p_cpi->resp_time_val
+           );
+
+ 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
+osmtest_get_node_rec( IN osmtest_t * const p_osmt,
+                      IN ib_net64_t const node_guid,
+                      IN OUT osmtest_req_context_t * const p_context )
+{
+  ib_api_status_t status = IB_SUCCESS;
+  osmv_user_query_t user;
+  osmv_query_req_t req;
+  ib_node_record_t record;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_get_node_rec );
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "osmtest_get_node_rec: "
+               "Getting node record for 0x%016" PRIx64 ".\n",
+               cl_ntoh64( node_guid ) );
+    }
+
+  /*
+   * 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.
+   */
+  cl_memclr( &req, sizeof( req ) );
+  cl_memclr( &user, sizeof( user ) );
+  cl_memclr( &record, sizeof( record ) );
+
+
+  record.node_info.node_guid = node_guid;
+
+  p_context->p_osmt = p_osmt;
+  user.comp_mask = IB_NR_COMPMASK_NODEGUID;
+  user.attr_id = IB_MAD_ATTR_NODE_RECORD;
+  user.attr_offset = cl_ntoh16( ( uint16_t ) ( sizeof( record ) >> 3 ) );
+  user.p_attr = &record;
+
+  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 = p_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,
+               "osmtest_get_node_rec: ERR 0071: "
+               "ib_query failed (%s).\n", ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+  status = p_context->result.status;
+
+  if( status != IB_SUCCESS )
+    {
+      if (status != IB_INVALID_PARAMETER)
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_get_node_rec: ERR 0072: "
+                   "ib_query failed (%s).\n", ib_get_err_str( status ) );
+        }
+      if( status == IB_REMOTE_ERROR )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_get_node_rec: "
+                   "Remote error = %s.\n",
+                   ib_get_mad_status_str( osm_madw_get_mad_ptr
+                                          ( p_context->result.
+                                            p_result_madw ) ) );
+        }
+      goto Exit;
+    }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ * Get a node record by node LID
+ **********************************************************************/
+ib_api_status_t
+osmtest_get_node_rec_by_lid( IN osmtest_t * const p_osmt,
+                             IN ib_net16_t const  lid,
+                             IN OUT osmtest_req_context_t * const p_context )
+{
+  ib_api_status_t status = IB_SUCCESS;
+  osmv_user_query_t user;
+  osmv_query_req_t req;
+  ib_node_record_t record;
+  ib_mad_t *p_mad;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_get_node_rec_by_lid );
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "osmtest_get_node_rec_by_lid: "
+               "Getting node record for LID 0x%02X.\n",
+               cl_ntoh16( lid ) );
+    }
+
+  /*
+   * 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.
+   */
+  cl_memclr( &req, sizeof( req ) );
+  cl_memclr( &user, sizeof( user ) );
+  cl_memclr( &record, sizeof( record ) );
+
+  record.lid = lid;
+
+  p_context->p_osmt = p_osmt;
+  user.comp_mask = IB_NR_COMPMASK_LID;
+  user.attr_id = IB_MAD_ATTR_NODE_RECORD;
+  user.attr_offset = cl_ntoh16( ( uint16_t ) ( sizeof( record ) >> 3 ) );
+  user.p_attr = &record;
+
+  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 = p_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,
+               "osmtest_get_node_rec_by_lid: ERR 0073: "
+               "ib_query failed (%s).\n", ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+  status = p_context->result.status;
+
+  if( status != IB_SUCCESS )
+    {
+      if (status != IB_INVALID_PARAMETER)
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_get_node_rec_by_lid: ERR 0074: "
+                   "ib_query failed (%s).\n", ib_get_err_str( status ) );
+        }
+      if( status == IB_REMOTE_ERROR )
+        {
+          p_mad = osm_madw_get_mad_ptr( p_context->result.p_result_madw );
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_get_node_rec_by_lid: "
+                   "Remote error = %s.\n",
+                   ib_get_mad_status_str( p_mad ));
+
+          status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK );
+        }
+      goto Exit;
+    }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_get_path_rec_by_guid_pair( IN osmtest_t * const p_osmt,
+                                  IN ib_net64_t sguid,
+                                  IN ib_net64_t dguid,
+                                  IN osmtest_req_context_t *p_context)
+{
+  cl_status_t status = IB_SUCCESS;
+  osmv_query_req_t req;
+  osmv_guid_pair_t guid_pair;
+
+  OSM_LOG_ENTER( &p_osmt->log,  osmtest_get_path_rec_by_guid_pair);
+
+  cl_memclr( p_context, sizeof( *p_context ) );
+
+  p_context->p_osmt = p_osmt;
+  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 = p_context;
+  req.pfn_query_cb = osmtest_query_res_cb;
+
+  req.query_type = OSMV_QUERY_PATH_REC_BY_PORT_GUIDS;
+
+  guid_pair.dest_guid = dguid;
+  guid_pair.src_guid = sguid;
+
+  req.p_query_input = &guid_pair;
+  req.sm_key = 0;
+
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmtest_get_path_rec_by_guid_pair: "
+           "Query for path from 0x%" PRIx64 " to 0x%" PRIx64"\n",
+           sguid,dguid );
+  status = osmv_query_sa( p_osmt->h_bind, &req );
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_get_path_rec_by_guid_pair: ERR 0063: "
+               "ib_query failed (%s)\n", ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+  status = (*p_context).result.status;
+
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_get_path_rec_by_guid_pair: ERR 0064: "
+               "ib_query failed (%s).\n", ib_get_err_str( status ) );
+
+      if( status == IB_REMOTE_ERROR )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_get_path_rec_by_guid_pair: "
+                   "Remote error = %s.\n",
+                   ib_get_mad_status_str( osm_madw_get_mad_ptr
+                                          ( (*p_context).result.
+                                            p_result_madw ) ) );
+        }
+      goto Exit;
+    }
+
+
+ Exit:
+
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+osmtest_get_port_rec( IN osmtest_t * const p_osmt,
+                      IN ib_net16_t const lid,
+                      IN OUT osmtest_req_context_t * const p_context )
+{
+  ib_api_status_t status = IB_SUCCESS;
+  osmv_user_query_t user;
+  osmv_query_req_t req;
+  ib_portinfo_record_t record;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_get_port_rec );
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+               "osmtest_get_port_rec: "
+               "Getting PortRecord for port with LID 0x%X.\n",
+               cl_ntoh16( lid ) );
+    }
+
+  /*
+   * 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.
+   */
+  cl_memclr( &req, sizeof( req ) );
+  cl_memclr( &user, sizeof( user ) );
+  cl_memclr( &record, sizeof( record ) );
+
+  record.lid = lid;
+
+  p_context->p_osmt = p_osmt;
+  user.comp_mask = IB_PIR_COMPMASK_LID;
+  user.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;
+  user.attr_offset = cl_ntoh16( ( uint16_t ) ( sizeof( record ) >> 3 ) );
+  user.p_attr = &record;
+
+  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 = p_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,
+               "osmtest_get_port_rec: ERR 0075: "
+               "ib_query failed (%s).\n", ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+  status = p_context->result.status;
+
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_get_port_rec: ERR 0076: "
+               "ib_query failed (%s).\n", ib_get_err_str( status ) );
+
+      if( status == IB_REMOTE_ERROR )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_get_port_rec: "
+                   "Remote error = %s.\n",
+                   ib_get_mad_status_str( osm_madw_get_mad_ptr
+                                          ( p_context->result.
+                                            p_result_madw ) ) );
+        }
+      goto Exit;
+    }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+ib_api_status_t
+osmtest_get_port_rec_by_num( IN osmtest_t * const p_osmt,
+                             IN ib_net16_t const lid,
+                             IN uint8_t const port_num,
+                             IN OUT osmtest_req_context_t * const p_context )
+{
+  ib_api_status_t status = IB_SUCCESS;
+  osmv_user_query_t user;
+  osmv_query_req_t req;
+  ib_portinfo_record_t record;
+  ib_mad_t *p_mad;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_get_port_rec );
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+               "osmtest_get_port_rec_by_num: "
+               "Getting PortRecord 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.
+   */
+  cl_memclr( &req, sizeof( req ) );
+  cl_memclr( &user, sizeof( user ) );
+  cl_memclr( &record, sizeof( record ) );
+
+  record.lid = lid;
+  record.port_num = port_num;
+  user.p_attr = &record;
+
+  p_context->p_osmt = p_osmt;
+
+  req.query_type = OSMV_QUERY_PORT_REC_BY_LID_AND_NUM;
+  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 = p_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,
+               "osmtest_get_port_rec_by_num: ERR 0077: "
+               "ib_query failed (%s).\n", ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+  status = p_context->result.status;
+
+  if( status != IB_SUCCESS )
+    {
+      if (status != IB_INVALID_PARAMETER)
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_get_port_rec_by_num: ERR 0078: "
+                   "ib_query failed (%s).\n", ib_get_err_str( status ) );
+        }
+
+      if( status == IB_REMOTE_ERROR )
+        {
+          p_mad = osm_madw_get_mad_ptr( p_context->result.p_result_madw );
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_get_port_rec_by_num: "
+                   "Remote error = %s.\n",
+                   ib_get_mad_status_str( p_mad ));
+          status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK );
+        }
+      goto Exit;
+    }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_stress_port_recs_large( IN osmtest_t * const p_osmt,
+                                OUT uint32_t * const p_num_recs,
+                                OUT uint32_t * const p_num_queries )
+{
+  osmtest_req_context_t context;
+  ib_portinfo_record_t *p_rec;
+  uint32_t i;
+  cl_status_t status;
+  uint32_t num_recs = 0;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_port_recs_large );
+
+  cl_memclr( &context, sizeof( context ) );
+  /*
+   * Do a blocking query for all NodeRecords in the subnet.
+   */
+  status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_PORTINFO_RECORD,
+                                 sizeof( *p_rec ), &context );
+
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_stress_port_recs_large: ERR 0006: "
+               "osmtest_get_all_recs failed (%s)\n",
+               ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+  /*
+   * Populate the database with the received records.
+   */
+  num_recs = context.result.result_cnt;
+  *p_num_recs += num_recs;
+  ++*p_num_queries;
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "osmtest_stress_port_recs_large: "
+               "Received %u records.\n", num_recs );
+
+      for( i = 0; i < num_recs; i++ )
+        {
+          p_rec =
+            osmv_get_query_portinfo_rec( context.result.p_result_madw, i );
+          osm_dump_portinfo_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );
+        }
+    }
+
+ 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 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_stress_node_recs_large( IN osmtest_t * const p_osmt,
+                                OUT uint32_t * const p_num_recs,
+                                OUT uint32_t * const p_num_queries )
+{
+  osmtest_req_context_t context;
+  ib_node_record_t *p_rec;
+  uint32_t i;
+  cl_status_t status;
+  uint32_t num_recs = 0;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_node_recs_large );
+
+  cl_memclr( &context, 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,
+               "osmtest_stress_node_recs_large: ERR 0007: "
+               "osmtest_get_all_recs failed (%s)\n",
+               ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+  /*
+   * Populate the database with the received records.
+   */
+  num_recs = context.result.result_cnt;
+  *p_num_recs += num_recs;
+  ++*p_num_queries;
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "osmtest_stress_node_recs_large: "
+               "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 );
+          osm_dump_node_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );
+        }
+    }
+
+ 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 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_stress_path_recs_large( IN osmtest_t * const p_osmt,
+                                OUT uint32_t * const p_num_recs,
+                                OUT uint32_t * const p_num_queries )
+{
+  osmtest_req_context_t context;
+  ib_path_rec_t *p_rec;
+  uint32_t i;
+  cl_status_t status;
+  uint32_t num_recs = 0;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_path_recs_large );
+
+  cl_memclr( &context, sizeof( context ) );
+
+  /*
+   * Do a blocking query for all Records in the subnet.
+   */
+  status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_PATH_RECORD,
+                                 sizeof( *p_rec ), &context );
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_stress_path_recs_large: ERR 0008: "
+               "osmtest_get_all_recs failed (%s)\n",
+               ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+  /*
+   * Populate the database with the received records.
+   */
+  num_recs = context.result.result_cnt;
+  *p_num_recs += num_recs;
+  ++*p_num_queries;
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "osmtest_stress_path_recs_large: "
+               "Received %u records.\n", num_recs );
+
+      for( i = 0; i < num_recs; i++ )
+        {
+          p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i );
+          osm_dump_path_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );
+        }
+    }
+
+ 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 );
+}
+
+ib_api_status_t
+osmtest_stress_path_recs_by_guid ( IN osmtest_t * const p_osmt,
+                                   OUT uint32_t * const p_num_recs,
+                                   OUT uint32_t * const p_num_queries )
+{
+  osmtest_req_context_t context;
+  ib_path_rec_t *p_rec;
+  uint32_t i;
+  cl_status_t status = IB_SUCCESS;
+  uint32_t num_recs = 0;
+  node_t *p_src_node, *p_dst_node;
+  cl_qmap_t *p_tbl;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_path_recs_by_guid );
+
+  cl_memclr( &context, sizeof( context ) );
+
+  context.p_osmt = p_osmt;
+
+  p_tbl = &p_osmt->exp_subn.node_guid_tbl;
+
+  p_src_node = ( node_t * ) cl_qmap_head( p_tbl );
+
+    /*
+   * Go over all nodes that exist in the subnet
+   * for each pair that are not switch nodes get the path record
+   */
+  while( p_src_node != ( node_t * ) cl_qmap_end( p_tbl ) ) {
+    p_dst_node = ( node_t * ) cl_qmap_head( p_tbl );
+
+    while( p_dst_node != ( node_t * ) cl_qmap_end( p_tbl ) ) {
+      /*
+        * Do a blocking query for CA to CA Path Record
+      */
+        osm_log(&p_osmt->log, OSM_LOG_VERBOSE,
+                "osmtest_stress_path_recs_by_guid:"
+                "Source : guid = 0x%" PRIx64 " type = %d"
+                "Target : guid = 0x%" PRIx64 " type = %d\n",
+                cl_ntoh64(p_src_node->rec.node_info.port_guid),p_src_node->rec.node_info.node_type,
+                cl_ntoh64(p_dst_node->rec.node_info.port_guid),p_dst_node->rec.node_info.node_type);
+
+        if (p_src_node->rec.node_info.node_type == IB_NODE_TYPE_CA 
+            && p_dst_node->rec.node_info.node_type == IB_NODE_TYPE_CA) 
+            {
+                status = osmtest_get_path_rec_by_guid_pair(p_osmt , 
+                                                   p_src_node->rec.node_info.port_guid,
+                                                   p_dst_node->rec.node_info.port_guid,
+                                                   &context);
+
+                /* In a case of TIMEOUT you still can try sending but cant count  , maybe its a temporary issue */
+                if( status != IB_SUCCESS )
+                {
+                    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                             "osmtest_stress_path_recs_by_guid: ERR 0008: "
+                             "osmtest_get_path_rec_by_guid_pair failed (%s)\n",
+                             ib_get_err_str( status ) );
+                    if (status != IB_TIMEOUT) 
+                        goto Exit;
+                }
+                else
+                {
+                    /* we might have received several records */
+                    num_recs = context.result.result_cnt;
+                /*
+                * Populate the database with the received records.
+                    */
+                    *p_num_recs += num_recs;
+                    ++*p_num_queries;
+                    if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+                        osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+                                 "osmtest_stress_path_recs_by_guid: "
+                                 "Received %u records.\n", num_recs );
+                    /* Dont waste time if not VERBOSE and above */
+                    if (p_osmt->log.level & OSM_LOG_VERBOSE) {
+                        for (i = 0; i < num_recs; i++) {
+                            p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i);
+                            osm_dump_path_record(&p_osmt->log,p_rec,OSM_LOG_VERBOSE);
+                        }
+                    }
+                }
+                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;
+                }
+        }
+        /* next one please */
+        p_dst_node = ( node_t * ) cl_qmap_next( &p_dst_node->map_item );
+      }
+      /* } */
+
+      p_src_node = ( node_t * ) cl_qmap_next( &p_src_node->map_item );
+    }
+
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_stress_port_recs_small( IN osmtest_t * const p_osmt,
+                                OUT uint32_t * const p_num_recs,
+                                OUT uint32_t * const p_num_queries )
+{
+  osmtest_req_context_t context;
+  ib_portinfo_record_t *p_rec;
+  uint32_t i;
+  cl_status_t status;
+  uint32_t num_recs = 0;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_port_recs_small );
+
+  cl_memclr( &context, sizeof( context ) );
+
+  /*
+   * Do a blocking query for our own PortRecord in the subnet.
+   */
+  status = osmtest_get_port_rec( p_osmt, 
+                                 cl_ntoh16(p_osmt->local_port.lid), 
+                                 &context );
+
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_stress_port_recs_small: ERR 0009: "
+               "osmtest_get_all_recs failed (%s)\n",
+               ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+  /*
+   * Populate the database with the received records.
+   */
+  num_recs = context.result.result_cnt;
+  *p_num_recs += num_recs;
+  ++*p_num_queries;
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "osmtest_stress_port_recs_small: "
+               "Received %u records.\n", num_recs );
+
+      for( i = 0; i < num_recs; i++ )
+        {
+          p_rec =
+            osmv_get_query_portinfo_rec( context.result.p_result_madw, i );
+          osm_dump_portinfo_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );
+        }
+    }
+
+ 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 );
+}
+
+/**********************************************************************
+ * Use a wrong SM_Key in a simple port query and report success if
+ * failed.
+ **********************************************************************/
+ib_api_status_t
+osmtest_wrong_sm_key_ignored( IN osmtest_t * const p_osmt)
+{
+  ib_api_status_t status = IB_SUCCESS;
+  osmv_user_query_t user;
+  osmv_query_req_t req;
+  ib_portinfo_record_t record;
+  osmtest_req_context_t context;
+  osmtest_req_context_t *p_context = &context;
+  uint8_t port_num = 1;
+
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_get_port_rec );
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_INFO ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_INFO,
+               "osmtest_wrong_sm_key_ignored: "
+               "Try PortRecord for port with LID 0x%X Num:0x%X.\n",
+               cl_ntoh16( p_osmt->local_port.sm_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.
+   */
+  cl_memclr( &req, sizeof( req ) );
+  cl_memclr( &user, sizeof( user ) );
+  cl_memclr( &record, sizeof( record ) );
+
+  record.lid = p_osmt->local_port.sm_lid;
+  record.port_num = port_num;
+  user.p_attr = &record;
+
+  p_context->p_osmt = p_osmt;
+
+  req.query_type = OSMV_QUERY_PORT_REC_BY_LID_AND_NUM;
+  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 = p_context;
+  req.pfn_query_cb = osmtest_query_res_cb;
+  req.p_query_input = &user;
+  req.sm_key = 9999;
+  context.result.p_result_madw = NULL;
+
+  status = osmv_query_sa( p_osmt->h_bind, &req );
+
+  /* since we use a wrong sm_key we should geta timeout */
+  if( status != IB_TIMEOUT )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_wrong_sm_key_ignored: ERR 0010: "
+               "Did not get a timeout but got (%s).\n", ib_get_err_str( status ) );
+      goto Exit;
+    }
+  else
+    {
+      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;
+    }
+
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_write_port_info( IN osmtest_t * const p_osmt,
+                         IN FILE * fh,
+                         IN const ib_portinfo_record_t * const p_rec )
+{
+  int result;
+  cl_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_port_info );
+
+  result = fprintf( fh,
+                    "DEFINE_PORT\n"
+                    "lid                     0x%X\n"
+                    "port_num                0x%X\n"
+                    "m_key                   0x%016" PRIx64 "\n"
+                    "subnet_prefix           0x%016" PRIx64 "\n"
+                    "base_lid                0x%X\n"
+                    "master_sm_base_lid      0x%X\n"
+                    "capability_mask         0x%X\n"
+                    "diag_code               0x%X\n"
+                    "m_key_lease_period      0x%X\n"
+                    "local_port_num          0x%X\n"
+                    "link_width_enabled      0x%X\n"
+                    "link_width_supported    0x%X\n"
+                    "link_width_active       0x%X\n"
+                    "link_speed_supported    0x%X\n"
+                    "port_state              %s\n"
+                    "state_info2             0x%X\n"
+                    "mpb                     0x%X\n"
+                    "lmc                     0x%X\n"
+                    "link_speed              0x%X\n"
+                    "mtu_smsl                0x%X\n"
+                    "vl_cap                  0x%X\n"
+                    "vl_high_limit           0x%X\n"
+                    "vl_arb_high_cap         0x%X\n"
+                    "vl_arb_low_cap          0x%X\n"
+                    "mtu_cap                 0x%X\n"
+                    "vl_stall_life           0x%X\n"
+                    "vl_enforce              0x%X\n"
+                    "m_key_violations        0x%X\n"
+                    "p_key_violations        0x%X\n"
+                    "q_key_violations        0x%X\n"
+                    "guid_cap                0x%X\n"
+                    "subnet_timeout          0x%X\n"
+                    "resp_time_value         0x%X\n"
+                    "error_threshold         0x%X\n"
+                    "END\n\n",
+                    cl_ntoh16( p_rec->lid ),
+                    p_rec->port_num,
+                    cl_ntoh64( p_rec->port_info.m_key ),
+                    cl_ntoh64( p_rec->port_info.subnet_prefix ),
+                    cl_ntoh16( p_rec->port_info.base_lid ),
+                    cl_ntoh16( p_rec->port_info.master_sm_base_lid ),
+                    cl_ntoh32( p_rec->port_info.capability_mask ),
+                    cl_ntoh16( p_rec->port_info.diag_code ),
+                    cl_ntoh16( p_rec->port_info.m_key_lease_period ),
+                    p_rec->port_info.local_port_num,
+                    p_rec->port_info.link_width_enabled,
+                    p_rec->port_info.link_width_supported,
+                    p_rec->port_info.link_width_active,
+                    ib_port_info_get_link_speed_sup( &p_rec->port_info ),
+                    ib_get_port_state_str( ib_port_info_get_port_state
+                                           ( &p_rec->port_info ) ),
+                    p_rec->port_info.state_info2,
+                    ib_port_info_get_mpb( &p_rec->port_info ),
+                    ib_port_info_get_lmc( &p_rec->port_info ),
+                    p_rec->port_info.link_speed, p_rec->port_info.mtu_smsl,
+                    p_rec->port_info.vl_cap, p_rec->port_info.vl_high_limit,
+                    p_rec->port_info.vl_arb_high_cap,
+                    p_rec->port_info.vl_arb_low_cap,
+                    p_rec->port_info.mtu_cap,
+                    p_rec->port_info.vl_stall_life,
+                    p_rec->port_info.vl_enforce,
+                    cl_ntoh16( p_rec->port_info.m_key_violations ),
+                    cl_ntoh16( p_rec->port_info.p_key_violations ),
+                    cl_ntoh16( p_rec->port_info.q_key_violations ),
+                    p_rec->port_info.guid_cap,
+                    ib_port_info_get_timeout(&p_rec->port_info),
+                    p_rec->port_info.resp_time_value,
+                    p_rec->port_info.error_threshold );
+
+  if( result < 0 )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_write_port_info: ERR 001: "  "Write failed.\n" );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_write_path_info( IN osmtest_t * const p_osmt,
+                         IN FILE * fh,
+                         IN const ib_path_rec_t * const p_rec )
+{
+  int result;
+  cl_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_path_info );
+
+  result = fprintf( fh,
+                    "DEFINE_PATH\n"
+                    "dgid                    0x%016" PRIx64 " 0x%016" PRIx64
+                    "\nsgid                    0x%016" PRIx64 " 0x%016" PRIx64
+                    "\ndlid                    0x%X\n"
+                    "slid                    0x%X\n"
+                    "# hop_flow_raw          0x%X\n"
+                    "# tclass                0x%X\n"
+                    "# num_path              0x%X\n"
+                    "pkey                    0x%X\n"
+                    "# sl                    0x%X\n"
+                    "# mtu                   0x%X\n"
+                    "# rate                  0x%X\n"
+                    "# pkt_life              0x%X\n"
+                    "# preference            0x%X\n" "END\n\n",
+                    cl_ntoh64( p_rec->dgid.unicast.prefix ),
+                    cl_ntoh64( p_rec->dgid.unicast.interface_id ),
+                    cl_ntoh64( p_rec->sgid.unicast.prefix ),
+                    cl_ntoh64( p_rec->sgid.unicast.interface_id ),
+                    cl_ntoh16( p_rec->dlid ), cl_ntoh16( p_rec->slid ),
+                    cl_ntoh32( p_rec->hop_flow_raw ), p_rec->tclass,
+                    p_rec->num_path, cl_ntoh16( p_rec->pkey ), p_rec->sl,
+                    p_rec->mtu, p_rec->rate, p_rec->pkt_life,
+                    p_rec->preference );
+
+  if( result < 0 )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_write_path_info: ERR 002: "  "Write failed.\n" );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_write_node_info( IN osmtest_t * const p_osmt,
+                         IN FILE * fh,
+                         IN const ib_node_record_t * const p_rec )
+{
+  int result;
+  cl_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_node_info );
+
+  result = fprintf( fh,
+                    "DEFINE_NODE\n"
+                    "lid                     0x%X\n"
+                    "base_version            0x%X\n"
+                    "class_version           0x%X\n"
+                    "node_type               0x%X # (%s)\n"
+                    "num_ports               0x%X\n"
+                    "sys_guid                0x%016" PRIx64 "\n"
+                    "node_guid               0x%016" PRIx64 "\n"
+                    "port_guid               0x%016" PRIx64 "\n"
+                    "partition_cap           0x%X\n"
+                    "device_id               0x%X\n"
+                    "revision                0x%X\n"
+                    "# port_num              0x%X\n"
+                    "# vendor_id             0x%X\n"
+                    "# node_desc             %s\n"
+                    "END\n\n",
+                    cl_ntoh16( p_rec->lid ),
+                    p_rec->node_info.base_version,
+                    p_rec->node_info.class_version,
+                    p_rec->node_info.node_type,
+                    ib_get_node_type_str( p_rec->node_info.node_type ),
+                    p_rec->node_info.num_ports,
+                    cl_ntoh64( p_rec->node_info.sys_guid ),
+                    cl_ntoh64( p_rec->node_info.node_guid ),
+                    cl_ntoh64( p_rec->node_info.port_guid ),
+                    cl_ntoh16( p_rec->node_info.partition_cap ),
+                    cl_ntoh16( p_rec->node_info.device_id ),
+                    cl_ntoh32( p_rec->node_info.revision ),
+                    ib_node_info_get_local_port_num( &p_rec->node_info ),
+                    cl_ntoh32( ib_node_info_get_vendor_id
+                               ( &p_rec->node_info ) ),
+                    p_rec->node_desc.description );
+
+  if( result < 0 )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_write_node_info: ERR 003: "  "Write failed.\n" );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+#if 0
+
+/*  HACK: we do not support link records for now. */
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_write_link( IN osmtest_t * const p_osmt,
+                    IN FILE * fh,
+                    IN const ib_link_record_t * const p_rec )
+{
+  int result;
+  cl_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_link );
+
+  result = fprintf( fh,
+                    "DEFINE_LINK\n"
+                    "from_lid                0x%X\n"
+                    "from_port_num           0x%X\n"
+                    "to_port_num             0x%X\n"
+                    "to_lid                  0x%X\n"
+                    "END\n\n",
+                    cl_ntoh16( p_rec->from_lid ),
+                    p_rec->from_port_num,
+                    p_rec->to_port_num, cl_ntoh16( p_rec->to_lid ) );
+
+  if( result < 0 )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_write_link: ERR 004: "  "Write failed.\n" );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_write_all_link_recs( IN osmtest_t * const p_osmt,
+                             IN FILE * fh )
+{
+  osmtest_req_context_t context;
+  const ib_link_record_t *p_rec;
+  uint32_t i;
+  cl_status_t status;
+  size_t num_recs;
+  int result;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_link_recs );
+
+  cl_memclr( &context, sizeof( context ) );
+
+  /*
+   * Do a blocking query for all NodeRecords in the subnet.
+   */
+  status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_LINK_RECORD,
+                                 sizeof( *p_rec ), &context );
+
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_write_all_link_recs: ERR 005: "
+               "osmtest_get_all_recs failed (%s)\n",
+               ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+  /*
+   * Write the received records out to the file.
+   */
+  num_recs = context.result.result_cnt;
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "osmtest_write_all_link_recs: "
+               "Received %u records.\n", num_recs );
+    }
+
+  result = fprintf( fh, "#\n" "# Link Records\n" "#\n" );
+  if( result < 0 )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_write_all_link_recs: ERR 006: "
+               "Write failed.\n" );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  for( i = 0; i < num_recs; i++ )
+    {
+      p_rec =
+        ( ib_link_record_t * ) osmv_get_query_result( context.result.
+                                                      p_result_madw, i );
+
+      osmtest_write_link( 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 );
+}
+
+#endif
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_get_path_rec_by_lid_pair( IN osmtest_t * const p_osmt,
+                                  IN ib_net16_t slid,
+                                  IN ib_net16_t dlid,
+                                  IN osmtest_req_context_t *p_context)
+{
+  cl_status_t status = IB_SUCCESS;
+  osmv_query_req_t req;
+  osmv_lid_pair_t lid_pair;
+
+  OSM_LOG_ENTER( &p_osmt->log,  osmtest_get_path_rec_by_lid_pair);
+
+  cl_memclr( p_context, sizeof( *p_context ) );
+
+  p_context->p_osmt = p_osmt;
+  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 = p_context;
+  req.pfn_query_cb = osmtest_query_res_cb;
+
+  req.query_type = OSMV_QUERY_PATH_REC_BY_LIDS;
+
+  lid_pair.dest_lid = dlid;
+  lid_pair.src_lid = slid;
+
+  req.p_query_input = &lid_pair;
+  req.sm_key = 0;
+
+  osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+           "osmtest_get_path_rec_by_lid_pair: "
+           "Query for path from 0x%X to 0x%X\n",
+           slid,dlid );
+  status = osmv_query_sa( p_osmt->h_bind, &req );
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_get_path_rec_by_lid_pair: ERR 0053: "
+               "ib_query failed (%s)\n", ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+  status = (*p_context).result.status;
+
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_get_path_rec_by_lid_pair: ERR 0067: "
+               "ib_query failed (%s).\n", ib_get_err_str( status ) );
+
+      if( status == IB_REMOTE_ERROR )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_get_path_rec_by_lid_pair: "
+                   "Remote error = %s.\n",
+                   ib_get_mad_status_str( osm_madw_get_mad_ptr
+                                          ( (*p_context).result.
+                                            p_result_madw ) ) );
+        }
+      goto Exit;
+    }
+
+
+ Exit:
+
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+#ifdef VENDOR_RMPP_SUPPORT
+/**********************************************************************
+ASSUMES RMPP IMPL
+**********************************************************************/
+static ib_api_status_t
+osmtest_write_all_node_recs( IN osmtest_t * const p_osmt,
+                             IN FILE * fh )
+{
+  osmtest_req_context_t context;
+  const ib_node_record_t *p_rec;
+  uint32_t i;
+  cl_status_t status;
+  size_t num_recs;
+  int result;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_node_recs );
+
+  cl_memclr( &context, 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,
+               "osmtest_write_all_node_recs: ERR 0022: "
+               "osmtest_get_all_recs failed (%s)\n",
+               ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+  /*
+   * Write the received records out to the file.
+   */
+  num_recs = context.result.result_cnt;
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "osmtest_write_all_node_recs: "
+               "Received %u records.\n", num_recs );
+    }
+
+  result = fprintf( fh, "#\n" "# Node Records\n" "#\n" );
+  if( result < 0 )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_write_all_node_recs: ERR 0023: "
+               "Write failed.\n" );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  for( i = 0; i < num_recs; i++ )
+    {
+      p_rec = osmv_get_query_node_rec( context.result.p_result_madw, i );
+      osmtest_write_node_info( 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 );
+}
+
+
+/**********************************************************************
+ * ASSUMES RMPP
+ **********************************************************************/
+static ib_api_status_t
+osmtest_write_all_port_recs( IN osmtest_t * const p_osmt,
+                             IN FILE * fh )
+{
+  osmtest_req_context_t context;
+  const ib_portinfo_record_t *p_rec;
+  uint32_t i;
+  cl_status_t status;
+  size_t num_recs;
+  int result;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_port_recs );
+
+  cl_memclr( &context, sizeof( context ) );
+
+  /*
+   * Do a blocking query for all NodeRecords in the subnet.
+   */
+  status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_PORTINFO_RECORD,
+                                 sizeof( *p_rec ), &context );
+
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_write_all_port_recs: ERR 007: "
+               "osmtest_get_all_recs failed (%s)\n",
+               ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+  /*
+   * Write the received records out to the file.
+   */
+  num_recs = context.result.result_cnt;
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "osmtest_write_all_port_recs: "
+               "Received %u records.\n", num_recs );
+    }
+
+  result = fprintf( fh, "#\n" "# PortInfo Records\n" "#\n" );
+  if( result < 0 )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_write_all_port_recs: ERR 0024: "  "Write failed.\n" );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  for( i = 0; i < num_recs; i++ )
+    {
+      p_rec = osmv_get_query_portinfo_rec( context.result.p_result_madw, i );
+      osmtest_write_port_info( 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 );
+}
+
+/**********************************************************************
+ASSUMES RMPP IMPL
+**********************************************************************/
+static ib_api_status_t
+osmtest_write_all_path_recs(
+                            IN osmtest_t * const p_osmt,
+                            IN FILE * fh )
+{
+  osmtest_req_context_t context;
+  const ib_path_rec_t *p_rec;
+  uint32_t i;
+  cl_status_t status;
+  size_t num_recs;
+  int result;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_path_recs );
+
+  cl_memclr( &context, sizeof( context ) );
+
+  /*
+   * Do a blocking query for all records in the subnet.
+   */
+  status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_PATH_RECORD,
+                                 sizeof( *p_rec ), &context );
+
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_write_all_path_recs: ERR 0025: "
+               "osmtest_get_all_recs failed (%s)\n",
+               ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+  /*
+   * Write the received records out to the file.
+   */
+  num_recs = context.result.result_cnt;
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "osmtest_write_all_path_recs: "
+               "Received %u records.\n", num_recs );
+    }
+
+  result = fprintf( fh, "#\n" "# Path Records\n" "#\n" );
+  if( result < 0 )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_write_all_path_recs: ERR 0026: "
+               "Write failed.\n" );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  for( i = 0; i < num_recs; i++ )
+    {
+      p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i );
+      osmtest_write_path_info( 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 );
+}
+
+#else
+
+/*
+ * NON RMPP BASED QUERY FOR ALL NODES: BASED ON THE MAX LID GIVEN BY THE USER:
+ */
+static ib_api_status_t
+osmtest_write_all_node_recs(
+                            IN osmtest_t * const p_osmt,
+                            IN FILE * fh )
+{
+  osmtest_req_context_t context;
+  node_t *p_node;
+  node_t *p_guid_node;
+  const ib_node_record_t *p_rec;
+  cl_status_t status = CL_SUCCESS;
+  int result;
+  uint16_t lid;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_node_recs );
+
+  result = fprintf( fh, "#\n" "# Node Records\n" "#\n" );
+  if( result < 0 )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_write_all_node_recs: ERR 0027: "
+               "Write failed.\n" );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  /*
+   * Go over all LIDS in the range 1 to max_lid and do a
+   * NodeRecord query by that lid.
+   */
+  for (lid = 1; lid <= p_osmt->max_lid; lid++) {
+    /* prepare the qury context */
+    cl_memclr( &context, sizeof( context ) );
+
+    status = osmtest_get_node_rec_by_lid( p_osmt, cl_ntoh16( lid ), &context );
+    if( status != IB_SUCCESS )
+      {
+        if ( (status != IB_INVALID_PARAMETER) && (status != IB_SA_MAD_STATUS_NO_RECORDS))
+          {
+            osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                     "osmtest_write_all_node_recs: ERR 0028: "
+                     "failed to get node info for LID:0x%02X.(%s)\n",
+                     cl_ntoh16( lid ),
+                     ib_get_err_str( status ) );
+            goto Exit;
+          }
+        else
+          {
+            osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                     "osmtest_write_all_node_recs: WRN 0121: "
+                     "failed to get node info for LID:0x%02X.(%s)\n",
+                     cl_ntoh16( lid ),
+                     ib_get_err_str( status ) );
+            status = IB_SUCCESS;
+          }
+      }
+    else
+      {
+        /* OK we got something */
+        p_rec = osmv_get_query_node_rec( context.result.p_result_madw, 0);
+        osmtest_write_node_info( p_osmt, fh, p_rec );
+
+        /* create a subnet object */
+        p_node = node_new(  );
+        CL_ASSERT( p_node != NULL );
+
+        /* copy the info to the subnet node object */
+        p_node->rec = *p_rec;
+
+        cl_qmap_insert( &p_osmt->exp_subn.node_lid_tbl,
+                        p_node->rec.lid, &p_node->map_item );
+
+        p_guid_node = node_new(  );
+        CL_ASSERT( p_guid_node != NULL );
+
+        *p_guid_node = *p_node;
+
+        cl_qmap_insert( &p_osmt->exp_subn.node_guid_tbl,
+                        p_guid_node->rec.node_info.node_guid,
+                        &p_guid_node->map_item );
+
+      }
+
+    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;
+      }
+  }
+
+ 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 );
+}
+
+/*
+ * GET ALL PORT RECORDS IN THE FABRIC -
+ * one by one by using the node info received
+ */
+
+static ib_api_status_t
+osmtest_write_all_port_recs( IN osmtest_t * const p_osmt,
+                             IN FILE * fh )
+{
+  osmtest_req_context_t context;
+  const ib_node_record_t *p_node_rec;
+  const ib_portinfo_record_t *p_rec;
+  uint8_t port_num;
+  cl_status_t status = CL_SUCCESS;
+  cl_qmap_t *p_tbl;
+  node_t *p_node;
+  port_t *p_port;
+  int result;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_port_recs );
+
+  cl_memclr( &context, sizeof( context ) );
+
+  /* print header */
+  result = fprintf( fh, "#\n" "# PortInfo Records\n" "#\n" );
+  if( result < 0 )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_write_all_port_recs: ERR 0029: "  "Write failed.\n" );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  /* use the pre-explored set of nodes */
+  p_tbl = &p_osmt->exp_subn.node_lid_tbl;
+  p_node = ( node_t * ) cl_qmap_head( p_tbl );
+
+  /*
+   * Go over all LIDS in the range 1 to max_lid and do a
+   * NodeRecord query by that lid.
+   */
+  while( p_node != ( node_t * ) cl_qmap_end( p_tbl ) )
+    {
+
+      p_node_rec = &(p_node->rec);
+
+      /* go through all ports of the node: */
+      for (port_num = 0; port_num <= p_node_rec->node_info.num_ports; port_num++) {
+        /* prepare the qury context */
+        cl_memclr( &context, sizeof( context ) );
+
+        status = osmtest_get_port_rec_by_num( p_osmt,
+                                              p_node_rec->lid,
+                                              port_num,
+                                              &context );
+        if( status != IB_SUCCESS )
+          {
+            if( (status != IB_INVALID_PARAMETER) && (status != IB_SA_MAD_STATUS_NO_RECORDS))
+              {
+                osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                         "osmtest_write_all_port_recs: WRN 0121: "
+                         "Error encountered getting port info for LID:0x%04X Num:0x%02X.(%s)\n",
+                         p_node_rec->lid,  port_num,
+                         ib_get_err_str( status ) );
+                goto Exit;
+              }
+            else
+              {
+                osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                         "osmtest_write_all_port_recs: WRN 0121: "
+                         "failed to get port info for LID:0x%04X Num:0x%02X.(%s)\n",
+                         p_node_rec->lid,  port_num,
+                         ib_get_err_str( status ) );
+                status = IB_SUCCESS;
+              }
+          }
+        else
+          {
+            /* OK we got something */
+            p_rec = osmv_get_query_portinfo_rec( context.result.p_result_madw, 0);
+            osmtest_write_port_info( p_osmt, fh, p_rec );
+
+            /* create a subnet object */
+            p_port = port_new(  );
+            CL_ASSERT( p_port != NULL );
+
+            /* copy the info to the subnet node object */
+            p_port->rec = *p_rec;
+
+            cl_qmap_insert( &p_osmt->exp_subn.port_key_tbl,
+                            port_gen_id(p_node_rec->lid, port_num), &p_port->map_item );
+          }
+
+        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;
+          }
+      }
+      p_node = ( node_t * ) cl_qmap_next( &p_node->map_item );
+    }
+
+  /* we must set the exist status to avoid abort of the over all algorith */
+
+ 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 );
+}
+
+/**********************************************************************
+ASSUMES NO RMPP
+**********************************************************************/
+static ib_api_status_t
+osmtest_write_all_path_recs( IN osmtest_t * const p_osmt,
+                             IN FILE * fh )
+{
+  osmtest_req_context_t context;
+  const ib_path_rec_t *p_rec;
+  cl_status_t status = CL_SUCCESS;
+  int num_recs, i;
+  cl_qmap_t *p_tbl;
+  node_t *p_src_node, *p_dst_node;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_path_recs );
+
+  cl_memclr( &context, sizeof( context ) );
+
+  /*
+   * Go over all nodes that exist in the subnet
+   * for each pair that are not switch nodes get the path record
+   */
+
+  context.p_osmt = p_osmt;
+
+  p_tbl = &p_osmt->exp_subn.node_lid_tbl;
+
+  p_src_node = ( node_t * ) cl_qmap_head( p_tbl );
+
+  while( p_src_node != ( node_t * ) cl_qmap_end( p_tbl ) ) {
+    /* HACK we use capability_mask to know diff a CA node from switch node */
+    /* if(p_src_node->rec.node_info.capability_mask  ) { */
+    p_dst_node = ( node_t * ) cl_qmap_head( p_tbl );
+
+    while( p_dst_node != ( node_t * ) cl_qmap_end( p_tbl ) ) {
+      /* HACK we use capability_mask to know diff a CA node from switch node */
+      /* if (p_dst_node->rec.node_info.capability_mask) { */
+
+      /* query for it: */
+      status = osmtest_get_path_rec_by_lid_pair( p_osmt,
+                                                 p_src_node->rec.lid,
+                                                 p_dst_node->rec.lid,
+                                                 &context);
+
+      if( status != IB_SUCCESS )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                   "osmtest_write_all_path_recs: WRN 0121: "
+                   "failed to get path info from LID:0x%X To LID:0x%X.(%s)\n",
+                   p_src_node->rec.lid, p_dst_node->rec.lid,
+                   ib_get_err_str( status ) );
+        }
+      else
+        {
+          /* we might have received several records */
+          num_recs = context.result.result_cnt;
+          for (i = 0; i < num_recs; i++) {
+            p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i);
+            osmtest_write_path_info( p_osmt, fh, p_rec );
+          }
+        }
+      /*  } */
+
+      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;
+        }
+
+      /* next one please */
+      p_dst_node = ( node_t * ) cl_qmap_next( &p_dst_node->map_item );
+    }
+    /* } */
+
+    p_src_node = ( node_t * ) cl_qmap_next( &p_src_node->map_item );
+  }
+
+  /*
+   * 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 );
+}
+
+#endif
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_create_inventory_file( IN osmtest_t * const p_osmt )
+{
+  FILE *fh;
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_create_inventory_file );
+
+  fh = fopen( p_osmt->opt.file_name, "w" );
+  if( fh == NULL )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_create_inventory_file: ERR 0079: "
+               "Unable to open inventory file (%s).\n" );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  /* HACK: the order is important: nodes ports paths */
+  status = osmtest_write_all_node_recs( p_osmt, fh );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  status = osmtest_write_all_port_recs( p_osmt, fh );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  if (! p_osmt->opt.ignore_path_records)
+    {
+      status = osmtest_write_all_path_recs( p_osmt, fh );
+      if( status != IB_SUCCESS )
+        goto Exit;
+    }
+
+  /*
+    status = osmtest_write_all_link_recs( p_osmt, fh );
+    if( status != IB_SUCCESS )
+    goto Exit;
+  */
+  fclose( fh );
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_stress_large_rmpp_pr( IN osmtest_t * const p_osmt )
+{
+  ib_api_status_t status = IB_SUCCESS;
+  uint64_t num_recs = 0;
+  uint64_t num_queries = 0;
+  uint32_t delta_recs;
+  uint32_t delta_queries;
+  uint32_t print_freq = 0;
+  struct timeval start_tv,end_tv;
+  long sec_diff,usec_diff;
+  float ratio;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_large_rmpp_pr );
+  gettimeofday( &start_tv, NULL );
+  printf("-I- Start time is : %09ld:%06ld [sec:usec]\n",start_tv.tv_sec, (long)start_tv.tv_usec);
+
+  while( num_queries < STRESS_LARGE_PR_RMPP_THR )
+    {
+      delta_recs = 0;
+      delta_queries = 0;
+
+      status = osmtest_stress_path_recs_by_guid( p_osmt, &delta_recs,
+                                                 &delta_queries );
+      if( status != IB_SUCCESS )
+        goto Exit;
+
+      num_recs += delta_recs;
+      num_queries += delta_queries;
+
+      print_freq += delta_recs;
+      if( print_freq > 10000 )
+        {
+          gettimeofday( &end_tv, NULL );
+          if (end_tv.tv_usec > start_tv.tv_usec) {
+              sec_diff = end_tv.tv_sec-start_tv.tv_sec;
+               usec_diff = end_tv.tv_usec-start_tv.tv_usec;
+           } else {
+               sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;
+               usec_diff =   1000000 - (start_tv.tv_usec - end_tv.tv_usec);
+           }
+           printf("-I- End time is : %09ld:%06ld [sec:usec]\n",
+                  end_tv.tv_sec, (long)end_tv.tv_usec);
+           printf("-I- Quering %" PRId64 " Path Record queries CA to CA (rmpp) \n\ttook %04ld:%06ld [sec:usec]\n",num_queries,
+                sec_diff,usec_diff);
+           if (num_recs == 0)
+               ratio = 0;
+           else
+               ratio =   (float) (num_queries / num_recs);
+           printf( "-I- Queries to Record Ratio is %" PRIu64 " records, %" PRIu64 " queries : %.2f \n",
+                  num_recs, num_queries, ratio);
+           print_freq = 0;
+        }
+    }
+
+ Exit:
+   gettimeofday( &end_tv, NULL );
+   printf("-I- End time is : %09ld:%06ld [sec:usec]\n",
+          end_tv.tv_sec, (long)end_tv.tv_usec);
+   if (end_tv.tv_usec > start_tv.tv_usec) {
+       sec_diff = end_tv.tv_sec-start_tv.tv_sec;
+       usec_diff = end_tv.tv_usec-start_tv.tv_usec;
+   } else {
+       sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;
+       usec_diff =   1000000 - (start_tv.tv_usec - end_tv.tv_usec);
+   }
+
+   printf("-I- Quering %" PRId64 " Path Record queries (rmpp) took %04ld:%06ld [sec:usec]\n",num_queries,
+          sec_diff,usec_diff);
+
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+
+static ib_api_status_t
+osmtest_stress_large_rmpp( IN osmtest_t * const p_osmt )
+{
+  ib_api_status_t status = IB_SUCCESS;
+  uint64_t num_recs = 0;
+  uint64_t num_queries = 0;
+  uint32_t delta_recs;
+  uint32_t delta_queries;
+  uint32_t print_freq = 0;
+  struct timeval start_tv,end_tv;
+  struct timezone tz;
+  long sec_diff,usec_diff;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_large_rmpp );
+  gettimeofday( &start_tv, &tz );
+  printf("-I- Start time is : %09ld:%06ld [sec:usec]\n",start_tv.tv_sec, (long)start_tv.tv_usec);
+
+  while( num_queries < STRESS_LARGE_RMPP_THR )
+    {
+      delta_recs = 0;
+      delta_queries = 0;
+
+      status = osmtest_stress_node_recs_large( p_osmt, &delta_recs,
+                                               &delta_queries );
+      if( status != IB_SUCCESS )
+        goto Exit;
+
+      status = osmtest_stress_path_recs_large( p_osmt, &delta_recs,
+                                               &delta_queries );
+      if( status != IB_SUCCESS )
+        goto Exit;
+
+      status = osmtest_stress_port_recs_large( p_osmt, &delta_recs,
+                                               &delta_queries );
+      if( status != IB_SUCCESS )
+        goto Exit;
+
+      num_recs += delta_recs;
+      num_queries += delta_queries;
+
+      print_freq += delta_recs;
+
+      if( print_freq > 100000 )
+        {
+          gettimeofday( &end_tv, &tz );
+          if (end_tv.tv_usec > start_tv.tv_usec) {
+              sec_diff = end_tv.tv_sec-start_tv.tv_sec;
+               usec_diff = end_tv.tv_usec-start_tv.tv_usec;
+           } else {
+               sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;
+               usec_diff =   1000000 - (start_tv.tv_usec - end_tv.tv_usec);
+           }
+           printf("-I- End time is : %09ld:%06ld [sec:usec]\n",
+                  end_tv.tv_sec, (long)end_tv.tv_usec);
+           printf("-I- Quering %" PRId64 " large mixed queries (rmpp) took %04ld:%06ld [sec:usec]\n",num_queries,
+                sec_diff,usec_diff);
+           printf( "%" PRIu64 " records, %" PRIu64 " queries\n",
+                  num_recs, num_queries );
+           print_freq = 0;
+        }
+    }
+
+ Exit:
+   gettimeofday( &end_tv, &tz );
+   printf("-I- End time is : %09ld:%06ld [sec:usec]\n",
+          end_tv.tv_sec, (long)end_tv.tv_usec);
+   if (end_tv.tv_usec > start_tv.tv_usec) {
+       sec_diff = end_tv.tv_sec-start_tv.tv_sec;
+       usec_diff = end_tv.tv_usec-start_tv.tv_usec;
+   } else {
+       sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;
+       usec_diff =   1000000 - (start_tv.tv_usec - end_tv.tv_usec);
+   }
+
+   printf("-I- Quering %" PRId64 " large mixed queries (rmpp) took %04ld:%06ld [sec:usec]\n",num_queries,
+          sec_diff,usec_diff);
+
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_stress_small_rmpp( IN osmtest_t * const p_osmt )
+{
+  ib_api_status_t status = IB_SUCCESS;
+  uint64_t num_recs = 0;
+  uint64_t num_queries = 0;
+  uint32_t delta_recs;
+  uint32_t delta_queries;
+  uint32_t print_freq = 0;
+  int      num_timeouts = 0;
+  struct timeval start_tv,end_tv;
+  struct timezone tz;
+  long sec_diff,usec_diff;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_small_rmpp );
+  gettimeofday( &start_tv, &tz );
+  printf("-I- Start time is : %09ld:%06ld [sec:usec]\n",start_tv.tv_sec, (long)start_tv.tv_usec);
+  while( (num_queries < STRESS_SMALL_RMPP_THR) && (num_timeouts < 100) )
+    {
+      delta_recs = 0;
+      delta_queries = 0;
+
+      status = osmtest_stress_port_recs_small( p_osmt, &delta_recs,
+                                               &delta_queries );
+
+      num_recs += delta_recs;
+      num_queries += delta_queries;
+
+      print_freq += delta_recs;
+      if( print_freq > 5000 )
+        {
+          gettimeofday( &end_tv, &tz );
+          printf( "%" PRIu64 " records, %" PRIu64 " queries\n",
+                  num_recs, num_queries );
+          if (end_tv.tv_usec > start_tv.tv_usec) {
+              sec_diff = end_tv.tv_sec-start_tv.tv_sec;
+               usec_diff = end_tv.tv_usec-start_tv.tv_usec;
+           } else {
+               sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;
+               usec_diff =   1000000 - (start_tv.tv_usec - end_tv.tv_usec);
+           }
+           printf("-I- End time is : %09ld:%06ld [sec:usec]\n",
+                  end_tv.tv_sec, (long)end_tv.tv_usec);
+           printf("-I- Quering %" PRId64 " port_info queries (single mad) took %04ld:%06ld [sec:usec]\n",num_queries,
+                sec_diff,usec_diff);
+           print_freq = 0;
+        }
+    }
+  gettimeofday( &end_tv, &tz );
+  printf("-I- End time is : %09ld:%06ld [sec:usec]\n",
+         end_tv.tv_sec, (long)end_tv.tv_usec);
+  if (end_tv.tv_usec > start_tv.tv_usec) {
+      sec_diff = end_tv.tv_sec-start_tv.tv_sec;
+      usec_diff = end_tv.tv_usec-start_tv.tv_usec;
+  } else {
+      sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;
+      usec_diff =   1000000 - (start_tv.tv_usec - end_tv.tv_usec);
+  }
+
+  printf("-I- Quering %" PRId64 " port_info queries (single mad) took %04ld:%06ld [sec:usec]\n",num_queries,
+          sec_diff,usec_diff);
+  if (num_timeouts > 50) 
+  {
+    status = IB_TIMEOUT;
+  }
+  /* Exit: */
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+osmtest_prepare_db_generic( IN osmtest_t * const p_osmt,
+                            IN cl_qmap_t * const p_tbl )
+{
+  generic_t *p_generic;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_prepare_db_generic );
+
+  p_generic = ( generic_t * ) cl_qmap_head( p_tbl );
+
+  while( p_generic != ( generic_t * ) cl_qmap_end( p_tbl ) )
+    {
+      p_generic->count = 0;
+      p_generic = ( generic_t * ) cl_qmap_next( &p_generic->map_item );
+    }
+
+  OSM_LOG_EXIT( &p_osmt->log );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+static void
+osmtest_prepare_db( IN osmtest_t * const p_osmt )
+{
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_prepare_db );
+
+  osmtest_prepare_db_generic( p_osmt, &p_osmt->exp_subn.node_lid_tbl );
+  osmtest_prepare_db_generic( p_osmt, &p_osmt->exp_subn.path_tbl );
+
+  OSM_LOG_EXIT( &p_osmt->log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_check_missing_nodes( IN osmtest_t * const p_osmt )
+{
+  const node_t *p_node;
+  cl_status_t status = IB_SUCCESS;
+  cl_qmap_t *p_tbl;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_check_missing_nodes );
+
+  p_tbl = &p_osmt->exp_subn.node_lid_tbl;
+
+  p_node = ( node_t * ) cl_qmap_head( p_tbl );
+
+  while( p_node != ( node_t * ) cl_qmap_end( p_tbl ) )
+    {
+      if( p_node->count == 0 )
+        {
+          /*
+           * This node was not reported by the SA
+           */
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_check_missing_nodes: ERR 0080: "
+                   "Missing node 0x%016" PRIx64 ".\n",
+                   cl_ntoh64( p_node->rec.node_info.node_guid ) );
+          status = IB_ERROR;
+        }
+
+      p_node = ( node_t * ) cl_qmap_next( &p_node->map_item );
+    }
+
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_check_missing_ports( IN osmtest_t * const p_osmt )
+{
+  const port_t *p_port;
+  cl_status_t status = IB_SUCCESS;
+  cl_qmap_t *p_tbl;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_check_missing_ports );
+
+  p_tbl = &p_osmt->exp_subn.port_key_tbl;
+
+  p_port = ( port_t * ) cl_qmap_head( p_tbl );
+
+  while( p_port != ( port_t * ) cl_qmap_end( p_tbl ) )
+    {
+      if( p_port->count == 0 )
+        {
+          /*
+           * This port was not reported by the SA
+           */
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_check_missing_ports: ERR 0081: "
+                   "Missing port LID:0x%X Num:0x%X.\n",
+                   cl_ntoh16( p_port->rec.lid), p_port->rec.port_num);
+          status = IB_ERROR;
+        }
+
+      p_port = ( port_t * ) cl_qmap_next( &p_port->map_item );
+    }
+
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_check_missing_paths( IN osmtest_t * const p_osmt )
+{
+  const path_t *p_path;
+  cl_status_t status = IB_SUCCESS;
+  cl_qmap_t *p_tbl;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_check_missing_paths );
+
+  p_tbl = &p_osmt->exp_subn.path_tbl;
+
+  p_path = ( path_t * ) cl_qmap_head( p_tbl );
+
+  while( p_path != ( path_t * ) cl_qmap_end( p_tbl ) )
+    {
+      if( p_path->count == 0 )
+        {
+          /*
+           * This path was not reported by the SA
+           */
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_check_missing_paths: ERR 0051: "
+                   "SA did not return path SLID 0x%X to DLID 0x%X.\n",
+                   cl_ntoh16( p_path->rec.slid ),
+                   cl_ntoh16( p_path->rec.dlid ) );
+          status = IB_ERROR;
+          goto Exit;
+        }
+
+      p_path = ( path_t * ) cl_qmap_next( &p_path->map_item );
+    }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+inline uint32_t
+osmtest_path_rec_key_get( IN const ib_path_rec_t * const p_rec )
+{
+  return ( p_rec->dlid << 16 | p_rec->slid );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+osmtest_path_rec_kay_is_valid( IN osmtest_t * const p_osmt,
+                               IN const path_t * const p_path )
+{
+  if( ( p_path->comp.dlid == 0 ) || ( p_path->comp.slid == 0 ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_path_rec_kay_is_valid: ERR 008: "
+               "SLID and DLID must be specified for defined paths.\n" );
+      return ( FALSE );
+    }
+
+  return ( TRUE );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_path_data( IN osmtest_t * const p_osmt,
+                            IN path_t * const p_path,
+                            IN const ib_path_rec_t * const p_rec )
+{
+  cl_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_path_data );
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_path_data: "
+               "Checking path SLID 0x%X to DLID 0x%X.\n",
+               cl_ntoh16( p_rec->slid ), cl_ntoh16( p_rec->dlid ) );
+    }
+
+
+  /*
+   * Has this record already been returned?
+   */
+  if( p_path->count != 0 )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_path_data: ERR 0056: "
+               "Already received path SLID 0x%X to DLID 0x%X.\n",
+               cl_ntoh16( p_rec->slid ), cl_ntoh16( p_rec->dlid ) );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  ++p_path->count;
+
+  /*
+   * Check the fields the user wants checked.
+   */
+  if( ( p_path->comp.dgid.unicast.interface_id &
+        p_path->rec.dgid.unicast.interface_id ) !=
+      ( p_path->comp.dgid.unicast.interface_id &
+        p_rec->dgid.unicast.interface_id ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_path_data: ERR 009: "
+               "DGID mismatch on path SLID 0x%X to DLID 0x%X.\n"
+               "\t\t\t\tExpected 0x%016" PRIx64 " 0x%016" PRIx64 ",\n"
+               "\t\t\t\tReceived 0x%016" PRIx64 " 0x%016" PRIx64 ".\n",
+               cl_ntoh16( p_path->rec.slid ),
+               cl_ntoh16( p_path->rec.dlid ),
+               cl_ntoh64( p_path->rec.dgid.unicast.prefix ),
+               cl_ntoh64( p_path->rec.dgid.unicast.interface_id ),
+               cl_ntoh64( p_rec->dgid.unicast.prefix ),
+               cl_ntoh64( p_rec->dgid.unicast.interface_id ) );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  /*
+   * Check the fields the user wants checked.
+   */
+  if( ( p_path->comp.sgid.unicast.interface_id &
+        p_path->rec.sgid.unicast.interface_id ) !=
+      ( p_path->comp.sgid.unicast.interface_id &
+        p_rec->sgid.unicast.interface_id ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_path_data: ERR 0011: "
+               "SGID mismatch on path SLID 0x%X to DLID 0x%X.\n"
+               "\t\t\t\tExpected 0x%016" PRIx64 " 0x%016" PRIx64 ",\n"
+               "\t\t\t\tReceived 0x%016" PRIx64 " 0x%016" PRIx64 ".\n",
+               cl_ntoh16( p_path->rec.slid ),
+               cl_ntoh16( p_path->rec.dlid ),
+               cl_ntoh64( p_path->rec.sgid.unicast.prefix ),
+               cl_ntoh64( p_path->rec.sgid.unicast.interface_id ),
+               cl_ntoh64( p_rec->sgid.unicast.prefix ),
+               cl_ntoh64( p_rec->sgid.unicast.interface_id ) );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  /*
+   * Compare the fields the user wishes to validate.
+   */
+  if( ( p_path->comp.pkey & p_path->rec.pkey ) !=
+      ( p_path->comp.pkey & p_rec->pkey ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_path_data: ERR 0012: "
+               "PKEY mismatch on path SLID 0x%X to DLID 0x%X.\n"
+               "\t\t\t\tExpected 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_path->rec.slid ),
+               cl_ntoh16( p_path->rec.dlid ),
+               cl_ntoh64( p_path->rec.pkey ), cl_ntoh64( p_rec->pkey ) );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_node_data( IN osmtest_t * const p_osmt,
+                            IN node_t * const p_node,
+                            IN const ib_node_record_t * const p_rec )
+{
+  cl_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_node_data );
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_node_data: "
+               "Checking node 0x%016" PRIx64 ", LID 0x%X.\n",
+               cl_ntoh64( p_rec->node_info.node_guid ),
+               cl_ntoh16( p_rec->lid ) );
+    }
+
+  /*
+   * Has this record already been returned?
+   */
+  if( p_node->count != 0 )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_node_data: ERR 0013: "
+               "Already received node 0x%016" PRIx64 ".\n",
+               cl_ntoh64( p_node->rec.node_info.node_guid ) );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  ++p_node->count;
+
+  /*
+   * Compare the fields the user wishes to validate.
+   */
+  if( ( p_node->comp.lid & p_node->rec.lid ) !=
+      ( p_node->comp.lid & p_rec->lid ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_node_data: ERR 0014: "
+               "Field mismatch node 0x%016" PRIx64 ", LID 0x%X.\n"
+               "\t\t\t\tExpected LID 0x%X, received 0x%X.\n",
+               cl_ntoh64( p_rec->node_info.node_guid ),
+               cl_ntoh16( p_rec->lid ), p_node->rec.lid, p_rec->lid );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  if( ( p_node->comp.node_info.base_version &
+        p_node->rec.node_info.base_version ) !=
+      ( p_node->comp.node_info.base_version &
+        p_rec->node_info.base_version ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_node_data: ERR 0015: "
+               "Field mismatch node 0x%016" PRIx64 ", LID 0x%X.\n"
+               "\t\t\t\tExpected base_version 0x%X, received 0x%X.\n",
+               cl_ntoh64( p_rec->node_info.node_guid ),
+               cl_ntoh16( p_rec->lid ),
+               p_node->rec.node_info.base_version,
+               p_rec->node_info.base_version );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  if( ( p_node->comp.node_info.class_version &
+        p_node->rec.node_info.class_version ) !=
+      ( p_node->comp.node_info.class_version &
+        p_rec->node_info.class_version ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_node_data: ERR 0016: "
+               "Field mismatch node 0x%016" PRIx64 ", LID 0x%X.\n"
+               "\t\t\t\tExpected class_version 0x%X, received 0x%X.\n",
+               cl_ntoh64( p_rec->node_info.node_guid ),
+               cl_ntoh16( p_rec->lid ),
+               p_node->rec.node_info.class_version,
+               p_rec->node_info.class_version );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  if( ( p_node->comp.node_info.node_type &
+        p_node->rec.node_info.node_type ) !=
+      ( p_node->comp.node_info.node_type & p_rec->node_info.node_type ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_node_data: ERR 0017: "
+               "Field mismatch node 0x%016" PRIx64 ", LID 0x%X.\n"
+               "\t\t\t\tExpected node_type 0x%X, received 0x%X.\n",
+               cl_ntoh64( p_rec->node_info.node_guid ),
+               cl_ntoh16( p_rec->lid ),
+               p_node->rec.node_info.node_type,
+               p_rec->node_info.node_type );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  if( ( p_node->comp.node_info.sys_guid &
+        p_node->rec.node_info.sys_guid ) !=
+      ( p_node->comp.node_info.sys_guid & p_rec->node_info.sys_guid ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_node_data: ERR 0018: "
+               "Field mismatch node 0x%016" PRIx64 ", LID 0x%X.\n"
+               "\t\t\t\tExpected sys_guid 0x%016" PRIx64
+               ", received 0x%016" PRIx64 ".\n",
+               cl_ntoh64( p_rec->node_info.node_guid ),
+               cl_ntoh16( p_rec->lid ),
+               cl_ntoh64( p_node->rec.node_info.sys_guid ),
+               cl_ntoh64( p_rec->node_info.sys_guid ) );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  if( ( p_node->comp.node_info.node_guid &
+        p_node->rec.node_info.node_guid ) !=
+      ( p_node->comp.node_info.node_guid & p_rec->node_info.node_guid ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_node_data: ERR 0019: "
+               "Field mismatch node 0x%016" PRIx64 ", LID 0x%X.\n"
+               "\t\t\t\tExpected node_guid 0x%016" PRIx64
+               ", received 0x%016" PRIx64 ".\n",
+               cl_ntoh64( p_rec->node_info.node_guid ),
+               cl_ntoh16( p_rec->lid ),
+               cl_ntoh64( p_node->rec.node_info.node_guid ),
+               cl_ntoh64( p_rec->node_info.node_guid ) );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  if( ( p_node->comp.node_info.port_guid &
+        p_node->rec.node_info.port_guid ) !=
+      ( p_node->comp.node_info.port_guid & p_rec->node_info.port_guid ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_node_data: ERR 0031: "
+               "Field mismatch node 0x%016" PRIx64 ", LID 0x%X.\n"
+               "\t\t\t\tExpected port_guid 0x%016" PRIx64
+               ", received 0x%016" PRIx64 ".\n",
+               cl_ntoh64( p_rec->node_info.node_guid ),
+               cl_ntoh16( p_rec->lid ),
+               cl_ntoh64( p_node->rec.node_info.port_guid ),
+               cl_ntoh64( p_rec->node_info.port_guid ) );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  if( ( p_node->comp.node_info.partition_cap &
+        p_node->rec.node_info.partition_cap ) !=
+      ( p_node->comp.node_info.partition_cap &
+        p_rec->node_info.partition_cap ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_node_data: ERR 0032: "
+               "Field mismatch node 0x%016" PRIx64 ", LID 0x%X.\n"
+               "\t\t\t\tExpected partition_cap 0x%X"
+               ", received 0x%X.\n",
+               cl_ntoh64( p_rec->node_info.node_guid ),
+               cl_ntoh16( p_rec->lid ),
+               cl_ntoh16( p_node->rec.node_info.partition_cap ),
+               cl_ntoh16( p_rec->node_info.partition_cap ) );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  if( ( p_node->comp.node_info.device_id &
+        p_node->rec.node_info.device_id ) !=
+      ( p_node->comp.node_info.device_id & p_rec->node_info.device_id ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_node_data: ERR 0033: "
+               "Field mismatch node 0x%016" PRIx64 ", LID 0x%X.\n"
+               "\t\t\t\tExpected device_id 0x%X"
+               ", received 0x%X.\n",
+               cl_ntoh64( p_rec->node_info.node_guid ),
+               cl_ntoh16( p_rec->lid ),
+               cl_ntoh16( p_node->rec.node_info.device_id ),
+               cl_ntoh16( p_rec->node_info.device_id ) );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  if( ( p_node->comp.node_info.revision &
+        p_node->rec.node_info.revision ) !=
+      ( p_node->comp.node_info.revision & p_rec->node_info.revision ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_node_data: ERR 0034: "
+               "Field mismatch node 0x%016" PRIx64 ", LID 0x%X.\n"
+               "\t\t\t\tExpected revision 0x%X"
+               ", received 0x%X.\n",
+               cl_ntoh64( p_rec->node_info.node_guid ),
+               cl_ntoh16( p_rec->lid ),
+               cl_ntoh32( p_node->rec.node_info.revision ),
+               cl_ntoh32( p_rec->node_info.revision ) );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_node_rec( IN osmtest_t * const p_osmt,
+                           IN const ib_node_record_t * const p_rec )
+{
+  cl_status_t status = IB_SUCCESS;
+  node_t *p_node;
+  const cl_qmap_t *p_tbl;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_node_rec );
+
+  /*
+   * Find proper node record in the database.
+   */
+  p_tbl = &p_osmt->exp_subn.node_lid_tbl;
+  p_node = ( node_t * ) cl_qmap_get( p_tbl, p_rec->lid );
+  if( p_node == ( node_t * ) cl_qmap_end( p_tbl ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_node_rec: ERR 0035: "
+               "Unexpected node 0x%016" PRIx64 ", LID 0x%X.\n",
+               cl_ntoh64( p_rec->node_info.node_guid ),
+               cl_ntoh16( p_rec->lid ) );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  status = osmtest_validate_node_data( p_osmt, p_node, p_rec );
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_port_data( IN osmtest_t * const p_osmt,
+                            IN port_t * const p_port,
+                            IN const ib_portinfo_record_t * const p_rec )
+{
+  cl_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_port_data );
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: "
+               "Checking port LID 0x%X, Num 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num);
+    }
+
+  /*
+   * Has this record already been returned?
+   */
+  if( p_port->count != 0 )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0036: "
+               "Already received port LID 0x%X, Num 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num);
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  ++p_port->count;
+
+  /*
+   * Compare the fields the user wishes to validate.
+   */
+  if( ( p_port->comp.lid & p_port->rec.lid ) !=
+      ( p_port->comp.lid & p_rec->lid ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0037: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected LID 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.lid, p_rec->lid );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  if( ( p_port->comp.port_num & p_port->rec.port_num ) !=
+      ( p_port->comp.port_num & p_rec->port_num ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0038: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected port_num 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_num, p_rec->port_num );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  if( ( p_port->comp.port_info.m_key & p_port->rec.port_info.m_key ) !=
+      ( p_port->comp.port_info.m_key & p_rec->port_info.m_key ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0039: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected m_key 0x%016" PRIx64 ", received 0x%016" PRIx64 ".\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.m_key, p_rec->port_info.m_key );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.subnet_prefix & p_port->rec.port_info.subnet_prefix ) !=
+      ( p_port->comp.port_info.subnet_prefix & p_rec->port_info.subnet_prefix ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0040: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected subnet_prefix 0x%016" PRIx64 ", received 0x%016" PRIx64 ".\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.subnet_prefix, p_rec->port_info.subnet_prefix );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.base_lid & p_port->rec.port_info.base_lid ) !=
+      ( p_port->comp.port_info.base_lid & p_rec->port_info.base_lid ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0041: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected base_lid 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.base_lid, p_rec->port_info.base_lid );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.master_sm_base_lid & p_port->rec.port_info.master_sm_base_lid ) !=
+      ( p_port->comp.port_info.master_sm_base_lid & p_rec->port_info.master_sm_base_lid ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0042: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected master_sm_base_lid 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.master_sm_base_lid, p_rec->port_info.master_sm_base_lid );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.capability_mask & p_port->rec.port_info.capability_mask ) !=
+      ( p_port->comp.port_info.capability_mask & p_rec->port_info.capability_mask ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0043: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected capability_mask 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.capability_mask, p_rec->port_info.capability_mask );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.diag_code & p_port->rec.port_info.diag_code ) !=
+      ( p_port->comp.port_info.diag_code & p_rec->port_info.diag_code ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0044: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected diag_code 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.diag_code, p_rec->port_info.diag_code );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.m_key_lease_period & p_port->rec.port_info.m_key_lease_period ) !=
+      ( p_port->comp.port_info.m_key_lease_period & p_rec->port_info.m_key_lease_period ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0045: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected m_key_lease_period 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.m_key_lease_period, p_rec->port_info.m_key_lease_period );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.local_port_num & p_port->rec.port_info.local_port_num ) !=
+      ( p_port->comp.port_info.local_port_num & p_rec->port_info.local_port_num ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0046: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected local_port_num 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.local_port_num, p_rec->port_info.local_port_num );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.link_width_enabled & p_port->rec.port_info.link_width_enabled ) !=
+      ( p_port->comp.port_info.link_width_enabled & p_rec->port_info.link_width_enabled ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0047: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected link_width_enabled 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.link_width_enabled, p_rec->port_info.link_width_enabled );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.link_width_supported & p_port->rec.port_info.link_width_supported ) !=
+      ( p_port->comp.port_info.link_width_supported & p_rec->port_info.link_width_supported ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0048: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected link_width_supported 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.link_width_supported, p_rec->port_info.link_width_supported );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.link_width_active & p_port->rec.port_info.link_width_active ) !=
+      ( p_port->comp.port_info.link_width_active & p_rec->port_info.link_width_active ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0049: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected link_width_active 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.link_width_active, p_rec->port_info.link_width_active );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.link_speed & p_port->rec.port_info.link_speed ) !=
+      ( p_port->comp.port_info.link_speed & p_rec->port_info.link_speed ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0054: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected link_speed 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.link_speed, p_rec->port_info.link_speed );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.state_info1 & p_port->rec.port_info.state_info1 ) !=
+      ( p_port->comp.port_info.state_info1 & p_rec->port_info.state_info1 ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0057: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected state_info1 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.state_info1, p_rec->port_info.state_info1 );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.state_info2 & p_port->rec.port_info.state_info2 ) !=
+      ( p_port->comp.port_info.state_info2 & p_rec->port_info.state_info2 ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0058: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected state_info2 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.state_info2, p_rec->port_info.state_info2 );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.mkey_lmc & p_port->rec.port_info.mkey_lmc ) !=
+      ( p_port->comp.port_info.mkey_lmc & p_rec->port_info.mkey_lmc ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0059: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected mkey_lmc 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.mkey_lmc, p_rec->port_info.mkey_lmc );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.link_speed & p_port->rec.port_info.link_speed ) !=
+      ( p_port->comp.port_info.link_speed & p_rec->port_info.link_speed ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0060: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected link_speed 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.link_speed, p_rec->port_info.link_speed );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.mtu_smsl & p_port->rec.port_info.mtu_smsl ) !=
+      ( p_port->comp.port_info.mtu_smsl & p_rec->port_info.mtu_smsl ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0061: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected mtu_smsl 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.mtu_smsl, p_rec->port_info.mtu_smsl );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.vl_cap & p_port->rec.port_info.vl_cap ) !=
+      ( p_port->comp.port_info.vl_cap & p_rec->port_info.vl_cap ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0062: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected vl_cap 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.vl_cap, p_rec->port_info.vl_cap );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.vl_high_limit & p_port->rec.port_info.vl_high_limit ) !=
+      ( p_port->comp.port_info.vl_high_limit & p_rec->port_info.vl_high_limit ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0082: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected vl_high_limit 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.vl_high_limit, p_rec->port_info.vl_high_limit );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.vl_arb_high_cap & p_port->rec.port_info.vl_arb_high_cap ) !=
+      ( p_port->comp.port_info.vl_arb_high_cap & p_rec->port_info.vl_arb_high_cap ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0083: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected vl_arb_high_cap 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.vl_arb_high_cap, p_rec->port_info.vl_arb_high_cap );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.vl_arb_low_cap & p_port->rec.port_info.vl_arb_low_cap ) !=
+      ( p_port->comp.port_info.vl_arb_low_cap & p_rec->port_info.vl_arb_low_cap ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0084: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected vl_arb_low_cap 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.vl_arb_low_cap, p_rec->port_info.vl_arb_low_cap );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.mtu_cap & p_port->rec.port_info.mtu_cap ) !=
+      ( p_port->comp.port_info.mtu_cap & p_rec->port_info.mtu_cap ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0085: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected mtu_cap 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.mtu_cap, p_rec->port_info.mtu_cap );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  /* this is a dynamic attribute
+     if( ( p_port->comp.port_info.vl_stall_life & p_port->rec.port_info.vl_stall_life ) !=
+     ( p_port->comp.port_info.vl_stall_life & p_rec->port_info.vl_stall_life ) )
+     {
+     osm_log( &p_osmt->log, OSM_LOG_ERROR,
+     "osmtest_validate_port_data: ERR 0129: "
+     "Field mismatch port LID 0x%X Num:0x%X.\n"
+     "\t\t\t\tExpected vl_stall_life 0x%X, received 0x%X.\n",
+     cl_ntoh16( p_rec->lid ), p_rec->port_num,
+     p_port->rec.port_info.vl_stall_life, p_rec->port_info.vl_stall_life );
+     status = IB_ERROR;
+     goto Exit;
+     }
+  */
+
+  if( ( p_port->comp.port_info.vl_enforce & p_port->rec.port_info.vl_enforce ) !=
+      ( p_port->comp.port_info.vl_enforce & p_rec->port_info.vl_enforce ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0086: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected vl_enforce 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.vl_enforce, p_rec->port_info.vl_enforce );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.m_key_violations & p_port->rec.port_info.m_key_violations ) !=
+      ( p_port->comp.port_info.m_key_violations & p_rec->port_info.m_key_violations ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0087: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected m_key_violations 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.m_key_violations, p_rec->port_info.m_key_violations );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.p_key_violations & p_port->rec.port_info.p_key_violations ) !=
+      ( p_port->comp.port_info.p_key_violations & p_rec->port_info.p_key_violations ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0088: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected p_key_violations 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.p_key_violations, p_rec->port_info.p_key_violations );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.q_key_violations & p_port->rec.port_info.q_key_violations ) !=
+      ( p_port->comp.port_info.q_key_violations & p_rec->port_info.q_key_violations ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0089: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected q_key_violations 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.q_key_violations, p_rec->port_info.q_key_violations );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.guid_cap & p_port->rec.port_info.guid_cap ) !=
+      ( p_port->comp.port_info.guid_cap & p_rec->port_info.guid_cap ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0090: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected guid_cap 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.guid_cap, p_rec->port_info.guid_cap );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.subnet_timeout & p_port->rec.port_info.subnet_timeout ) !=
+      ( p_port->comp.port_info.subnet_timeout & p_rec->port_info.subnet_timeout ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0091: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected subnet_timeout 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               ib_port_info_get_timeout(&p_port->rec.port_info),
+               ib_port_info_get_timeout(&p_rec->port_info) );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.resp_time_value & p_port->rec.port_info.resp_time_value ) !=
+      ( p_port->comp.port_info.resp_time_value & p_rec->port_info.resp_time_value ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0092: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected resp_time_value 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.resp_time_value, p_rec->port_info.resp_time_value );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+
+  if( ( p_port->comp.port_info.error_threshold & p_port->rec.port_info.error_threshold ) !=
+      ( p_port->comp.port_info.error_threshold & p_rec->port_info.error_threshold ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_data: ERR 0093: "
+               "Field mismatch port LID 0x%X Num:0x%X.\n"
+               "\t\t\t\tExpected error_threshold 0x%X, received 0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num,
+               p_port->rec.port_info.error_threshold, p_rec->port_info.error_threshold );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_port_rec( IN osmtest_t * const p_osmt,
+                           IN const ib_portinfo_record_t * const p_rec )
+{
+  cl_status_t status = IB_SUCCESS;
+  port_t *p_port;
+  const cl_qmap_t *p_tbl;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_port_rec );
+
+  /*
+   * Find proper port record in the database. (we use by guid - since lid is not unique)
+   */
+  p_tbl = &p_osmt->exp_subn.port_key_tbl;
+  p_port = ( port_t * ) cl_qmap_get( p_tbl, port_gen_id( p_rec->lid, p_rec->port_num));
+  if( p_port == ( port_t * ) cl_qmap_end( p_tbl ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_port_rec: ERR 0094: "
+               "Unexpected port LID 0x%X, Num:0x%X.\n",
+               cl_ntoh16( p_rec->lid ), p_rec->port_num );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  status = osmtest_validate_port_data( p_osmt, p_port, p_rec );
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_path_rec( IN osmtest_t * const p_osmt,
+                           IN const ib_path_rec_t * const p_rec )
+{
+  cl_status_t status = IB_SUCCESS;
+  path_t *p_path;
+  const cl_qmap_t *p_tbl;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_path_rec );
+
+  /*
+   * Find proper path record in the database.
+   */
+  p_tbl = &p_osmt->exp_subn.path_tbl;
+  p_path =
+    ( path_t * ) cl_qmap_get( p_tbl, osmtest_path_rec_key_get( p_rec ) );
+  if( p_path == ( path_t * ) cl_qmap_end( p_tbl ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_path_rec: ERR 0095: "
+               "Unexpected path SLID 0x%X to DLID 0x%X.\n",
+               cl_ntoh16( p_rec->slid ), cl_ntoh16( p_rec->dlid ) );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  status = osmtest_validate_path_data( p_osmt, p_path, p_rec );
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+#ifdef VENDOR_RMPP_SUPPORT
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_all_node_recs( IN osmtest_t * const p_osmt )
+{
+  osmtest_req_context_t context;
+  const ib_node_record_t *p_rec;
+  uint32_t i;
+  cl_status_t status;
+  size_t num_recs;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_all_node_recs );
+
+  cl_memclr( &context, 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,
+               "osmtest_validate_all_node_recs: ERR 0096: "
+               "osmtest_get_all_recs failed (%s)\n",
+               ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+  num_recs = context.result.result_cnt;
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "osmtest_validate_all_node_recs: "
+               "Received %u records.\n", num_recs );
+    }
+
+  /*
+   * Compare the received records to the database.
+   */
+  osmtest_prepare_db( p_osmt );
+
+  for( i = 0; i < num_recs; i++ )
+    {
+      p_rec = osmv_get_query_node_rec( context.result.p_result_madw, i );
+
+      status = osmtest_validate_node_rec( p_osmt, p_rec );
+      if( status != IB_SUCCESS )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_validate_all_node_recs: ERR 0097: "
+                   "osmtest_valid_node_rec failed (%s)\n",
+                   ib_get_err_str( status ) );
+          goto Exit;
+        }
+    }
+
+  status = osmtest_check_missing_nodes( p_osmt );
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_all_node_recs: ERR 0098: "
+               "osmtest_check_missing_nodes failed (%s)\n",
+               ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+ 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 );
+}
+#endif
+
+#ifdef VENDOR_RMPP_SUPPORT
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_all_path_recs( IN osmtest_t * const p_osmt )
+{
+  osmtest_req_context_t context;
+  const ib_path_rec_t *p_rec;
+  uint32_t i;
+  cl_status_t status;
+  size_t num_recs;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_all_path_recs );
+
+  cl_memclr( &context, sizeof( context ) );
+
+  /*
+   * Do a blocking query for all PathRecords in the subnet.
+   */
+  status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_PATH_RECORD,
+                                 sizeof( *p_rec ), &context );
+
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_all_path_recs: ERR 0099: "
+               "osmtest_get_all_recs failed (%s)\n",
+               ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+  num_recs = context.result.result_cnt;
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "osmtest_validate_all_path_recs: "
+               "Received %u records.\n", num_recs );
+    }
+
+  /*
+   * Compare the received records to the database.
+   */
+  osmtest_prepare_db( p_osmt );
+
+  for( i = 0; i < num_recs; i++ )
+    {
+      p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i );
+
+      status = osmtest_validate_path_rec( p_osmt, p_rec );
+      if( status != IB_SUCCESS )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_validate_all_path_recs: ERR 00100: " 
+                   "osmtest_valid_node_rec failed (%s)\n",
+                   ib_get_err_str( status ) );
+          goto Exit;
+        }
+    }
+
+  status = osmtest_check_missing_paths( p_osmt );
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_all_path_recs: ERR 00101: " 
+               "osmtest_check_missing_paths failed (%s)\n",
+               ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+ 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 );
+}
+#endif
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_single_path_rec_lid_pair( IN osmtest_t * const p_osmt,
+                                           IN path_t * const p_path )
+{
+  osmtest_req_context_t context;
+  const ib_path_rec_t *p_rec;
+  cl_status_t status = IB_SUCCESS;
+  size_t num_recs;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_path_rec_lid_pair );
+
+  cl_memclr( &context, sizeof( context ) );
+
+  status = osmtest_get_path_rec_by_lid_pair( p_osmt,
+                                             p_path->rec.slid,
+                                             p_path->rec.dlid,
+                                             &context);
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_single_path_rec_lid_pair: ERR 00102: " 
+               "ib_query failed (%s)\n", ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+  num_recs = context.result.result_cnt;
+  if( num_recs != 1 )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_single_path_rec_lid_pair: ERR 00103: " 
+               "Too many records.  Expected 1, received %u.\n", num_recs );
+
+      status = IB_ERROR;
+    }
+  else
+    {
+      p_rec = osmv_get_query_path_rec( context.result.p_result_madw, 0 );
+
+      status = osmtest_validate_path_data( p_osmt, p_path, p_rec );
+      if( status != IB_SUCCESS )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_validate_single_path_rec_lid_pair: ERR 00104: " 
+                   "osmtest_validate_path_data failed (%s)\n",
+                   ib_get_err_str( status ) );
+        }
+    }
+
+ 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
+osmtest_validate_single_node_rec_lid( IN osmtest_t * const p_osmt,
+                                      IN ib_net16_t const lid,
+                                      IN node_t * const p_node )
+{
+  cl_status_t status = IB_SUCCESS;
+  osmv_user_query_t user;
+  osmv_query_req_t req;
+  ib_node_record_t record;
+
+  osmtest_req_context_t context;
+  const ib_node_record_t *p_rec;
+  int num_recs, i;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_node_rec_lid );
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+               "osmtest_validate_single_node_rec_lid: "
+               "Getting NodeRecord for node with LID 0x%X.\n",
+               cl_ntoh16( lid ) );
+    }
+
+  cl_memclr( &context, sizeof( context ) );
+  cl_memclr( &req, sizeof( req ) );
+  cl_memclr( &user, sizeof( user ) );
+  cl_memclr( &record, sizeof( record ) );
+
+  record.lid = lid;
+
+  context.p_osmt = p_osmt;
+  user.comp_mask = IB_NR_COMPMASK_LID;
+  user.attr_id = IB_MAD_ATTR_NODE_RECORD;
+  user.attr_offset = cl_ntoh16( (uint16_t) ( sizeof( record ) >> 3 ) );
+  user.p_attr = &record;
+
+  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;
+  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,
+               "osmtest_validate_single_node_rec_lid: ERR 00105: " 
+               "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,
+               "osmtest_validate_single_node_rec_lid: ERR 00106: " 
+               "ib_query failed (%s).\n", ib_get_err_str( status ) );
+
+      if( status == IB_REMOTE_ERROR )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_validate_single_node_rec_lid: "
+                   "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,
+           "osmtest_validate_single_node_rec_lid: "
+           "Received %d nodes\n", num_recs);
+
+  for( i = 0; i < num_recs; i++ )
+    {
+      p_rec = osmv_get_query_node_rec( context.result.p_result_madw, i );
+
+      status = osmtest_validate_node_rec( p_osmt, p_rec );
+      if( status != IB_SUCCESS )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_validate_single_node_rec_lid: ERR 00107: " 
+                   "osmtest_validate_node_data failed (%s)\n",
+                   ib_get_err_str( status ) );
+        }
+    }
+
+ 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
+osmtest_validate_single_port_rec_lid( IN osmtest_t * const p_osmt,
+                                      IN port_t * const p_port )
+{
+  osmtest_req_context_t context;
+
+  const ib_portinfo_record_t *p_rec;
+  cl_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_port_rec_lid );
+
+  cl_memclr( &context, sizeof( context ) );
+
+  context.p_osmt = p_osmt;
+  osmtest_get_port_rec_by_num( p_osmt,
+                               p_port->rec.lid,
+                               p_port->rec.port_num,
+                               &context);
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_single_port_rec_lid: ERR 00108: " 
+               "ib_query failed (%s).\n", ib_get_err_str( status ) );
+
+      goto Exit;
+    }
+
+  /* we should have got exactly one port */
+  p_rec = osmv_get_query_portinfo_rec( context.result.p_result_madw, 0);
+  status = osmtest_validate_port_rec( p_osmt, p_rec );
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_single_port_rec_lid: ERR 00109: " 
+               "osmtest_validate_port_data failed (%s)\n",
+               ib_get_err_str( status ) );
+    }
+
+ 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
+osmtest_validate_single_path_rec_guid_pair( IN osmtest_t * const p_osmt,
+                                            IN const osmv_guid_pair_t *
+                                            const p_pair )
+{
+  osmtest_req_context_t context;
+  const ib_path_rec_t *p_rec;
+  cl_status_t status = IB_SUCCESS;
+  size_t num_recs;
+  osmv_query_req_t req;
+  uint32_t i;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_path_rec_guid_pair );
+
+  cl_memclr( &context, sizeof( context ) );
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_single_path_rec_guid_pair: "
+               "\n\t\t\t\tChecking src 0x%016" PRIx64
+               " to dest 0x%016" PRIx64 ".\n",
+               cl_ntoh64( p_pair->src_guid ),
+               cl_ntoh64( p_pair->dest_guid ) );
+    }
+
+  context.p_osmt = p_osmt;
+
+  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.query_type = OSMV_QUERY_PATH_REC_BY_PORT_GUIDS;
+  req.p_query_input = p_pair;
+  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,
+               "osmtest_validate_single_path_rec_guid_pair: ERR 00110: " 
+               "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,
+               "osmtest_validate_single_path_rec_guid_pair: ERR 00111: " 
+               "ib_query failed (%s).\n", ib_get_err_str( status ) );
+
+      if( status == IB_REMOTE_ERROR )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_validate_single_path_rec_guid_pair: "
+                   "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,
+           "osmtest_validate_single_path_rec_guid_pair: "
+           "Got: %u records\n",
+           num_recs);
+  
+  for( i = 0; i < num_recs; i++ )
+    {
+      p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i );
+
+      /*
+       * Make sure the GUID values are correct
+       */
+      if( p_rec->dgid.unicast.interface_id != p_pair->dest_guid )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_validate_single_path_rec_guid_pair: ERR 00112: " 
+                   "Destination GUID mismatch.\n"
+                   "\t\t\t\texpected 0x%016" PRIx64
+                   ", received 0x%016" PRIx64 ".\n",
+                   cl_ntoh64( p_pair->dest_guid ),
+                   cl_ntoh64( p_rec->dgid.unicast.interface_id ) );
+        }
+
+      if( p_rec->sgid.unicast.interface_id != p_pair->src_guid )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_validate_single_path_rec_guid_pair: ERR 00113: " 
+                   "Source GUID mismatch.\n"
+                   "\t\t\t\texpected 0x%016" PRIx64
+                   ", received 0x%016" PRIx64 ".\n",
+                   cl_ntoh64( p_pair->src_guid ),
+                   cl_ntoh64( p_rec->sgid.unicast.interface_id ) );
+        }
+
+      status = osmtest_validate_path_rec( p_osmt, p_rec );
+      if( status != IB_SUCCESS )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_validate_single_path_rec_guid_pair: ERR 00114: " 
+                   "osmtest_validate_path_data failed (%s)\n",
+                   ib_get_err_str( status ) );
+        }
+      if (status != IB_SUCCESS )
+      {
+        osm_dump_path_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );
+      }
+    }
+
+ 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
+osmtest_validate_single_path_recs( IN osmtest_t * const p_osmt )
+{
+  path_t *p_path;
+  cl_status_t status = IB_SUCCESS;
+  const cl_qmap_t *p_path_tbl;
+/* We skip node to node path record validation since it might contains 
+   UNEXISTANT PATHS , i.e when using UPDN */
+  osmv_guid_pair_t guid_pair;
+  uint16_t cnt;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_path_recs );
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "osmtest_validate_single_path_recs: "
+               "Validating individual path record queries.\n" );
+    }
+  p_path_tbl = &p_osmt->exp_subn.path_tbl;
+
+  osmtest_prepare_db( p_osmt );
+
+  /*
+   * Walk the list of all path records, and ask for each one
+   * specifically.  Make sure we get it.
+   */
+  cnt = 0;
+  p_path = ( path_t * ) cl_qmap_head( p_path_tbl );
+  while( p_path != ( path_t * ) cl_qmap_end( p_path_tbl ) )
+    {
+      status = osmtest_validate_single_path_rec_lid_pair( p_osmt, p_path );
+      if( status != IB_SUCCESS )
+        goto Exit;
+      cnt++;
+      p_path = ( path_t * ) cl_qmap_next( &p_path->map_item );
+    }
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "osmtest_validate_single_path_recs: "
+               "Total of %u path records validated using LID based query.\n", cnt );
+    }
+
+  status = osmtest_check_missing_paths( p_osmt );
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_single_path_recs: ERR 00115: " 
+               "osmtest_check_missing_paths failed (%s)\n",
+               ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+  /*
+   * Do the whole thing again with port GUID pairs.
+   * Note that multiple path records may be returned
+   * for each guid pair if LMC > 0.
+   */
+  osmtest_prepare_db( p_osmt );
+  cnt = 0;
+  p_path = ( path_t * ) cl_qmap_head( p_path_tbl );
+  while( p_path != ( path_t * ) cl_qmap_end( p_path_tbl ) )
+    {
+      guid_pair.src_guid = p_path->rec.sgid.unicast.interface_id;
+      guid_pair.dest_guid = p_path->rec.dgid.unicast.interface_id;
+      status =
+       osmtest_validate_single_path_rec_guid_pair( p_osmt,
+                                                   &guid_pair );
+      if( status != IB_SUCCESS )
+        goto Exit;
+      cnt++;
+      p_path = ( path_t * ) cl_qmap_next( &p_path->map_item );
+    }
+
+
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "osmtest_validate_single_path_recs: "
+               "Total of %u path records validated using GUID based query.\n", cnt );
+    }
+
+  status = osmtest_check_missing_paths( p_osmt );
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_single_path_recs: ERR 00116: " 
+               "osmtest_check_missing_paths failed (%s)\n",
+               ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_single_node_recs( IN osmtest_t * const p_osmt )
+{
+  node_t *p_node;
+  cl_status_t status = IB_SUCCESS;
+  const cl_qmap_t *p_node_lid_tbl;
+  uint16_t cnt = 0;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_node_recs );
+
+  p_node_lid_tbl = &p_osmt->exp_subn.node_lid_tbl;
+
+  osmtest_prepare_db( p_osmt );
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "osmtest_validate_single_node_recs: "
+               "Validating individual node record queries.\n" );
+    }
+
+  /*
+   * Walk the list of all node records, and ask for each one
+   * specifically.  Make sure we get it.
+   */
+  p_node = ( node_t * ) cl_qmap_head( p_node_lid_tbl );
+  while( p_node != ( node_t * ) cl_qmap_end( p_node_lid_tbl ) )
+    {
+      status = osmtest_validate_single_node_rec_lid( p_osmt,
+                                                     (ib_net16_t) cl_qmap_key ((cl_map_item_t*)p_node),
+                                                     p_node );
+      cnt++;
+      p_node = ( node_t * ) cl_qmap_next( &p_node->map_item );
+    }
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "osmtest_validate_single_node_recs: "
+               "Total of %u node records validated.\n", cnt );
+    }
+
+  status = osmtest_check_missing_nodes( p_osmt );
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_single_node_recs: ERR 00117: " 
+               "osmtest_check_missing_nodes (%s)\n",
+               ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_single_port_recs( IN osmtest_t * const p_osmt )
+{
+  port_t *p_port;
+  cl_status_t status = IB_SUCCESS;
+  const cl_qmap_t *p_port_key_tbl;
+  uint16_t cnt = 0;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_port_recs );
+
+  p_port_key_tbl = &p_osmt->exp_subn.port_key_tbl;
+
+  osmtest_prepare_db( p_osmt );
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "osmtest_validate_single_port_recs: "
+               "Validating individual port record queries.\n" );
+    }
+
+  /*
+   * Walk the list of all port records, and ask for each one
+   * specifically.  Make sure we get it.
+   */
+  p_port = ( port_t * ) cl_qmap_head( p_port_key_tbl );
+  while( p_port != ( port_t * ) cl_qmap_end( p_port_key_tbl ) )
+    {
+      status = osmtest_validate_single_port_rec_lid( p_osmt, p_port );
+      cnt++;
+      p_port = ( port_t * ) cl_qmap_next( &p_port->map_item );
+    }
+
+
+  if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+               "osmtest_validate_single_port_recs: "
+               "Total of %u port records validated.\n", cnt );
+    }
+
+
+  status = osmtest_check_missing_ports( p_osmt );
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_validate_single_port_recs: ERR 00118: " 
+               "osmtest_check_missing_paths failed (%s)\n",
+               ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_validate_against_db( IN osmtest_t * const p_osmt )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_against_db );
+
+#ifdef VENDOR_RMPP_SUPPORT
+  status = osmtest_validate_all_node_recs( p_osmt );
+  if( status != IB_SUCCESS )
+    goto Exit;
+#endif
+
+  status = osmtest_validate_single_node_recs( p_osmt );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+#ifdef VENDOR_RMPP_SUPPORT
+  if (! p_osmt->opt.ignore_path_records)
+    {
+      status = osmtest_validate_all_path_recs( p_osmt );
+      if( status != IB_SUCCESS )
+        goto Exit;
+    }
+#endif
+
+  status = osmtest_validate_single_port_recs( p_osmt );
+  if( status != IB_SUCCESS )
+    goto Exit;
+
+  if (! p_osmt->opt.ignore_path_records)
+    {
+      status = osmtest_validate_single_path_recs( p_osmt );
+      if( status != IB_SUCCESS )
+        goto Exit;
+    }
+
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static const osmtest_token_t *
+str_get_token( IN char *const p_str )
+{
+  const osmtest_token_t *p_tok;
+  uint32_t index = 0;
+
+  p_tok = &token_array[index];
+
+  while( p_tok->val != OSMTEST_TOKEN_UNKNOWN )
+  {
+    if( strnicmp( p_str, p_tok->str, p_tok->str_size ) == 0 )
+      return ( p_tok );
+    
+    p_tok = &token_array[++index];
+  }
+
+  return ( NULL );
+}
+
+/**********************************************************************
+   Returns true if not whitespace character encountered before EOL.
+**********************************************************************/
+static boolean_t
+str_skip_white( IN char line[],
+                IN OUT uint32_t * const p_offset )
+{
+  while( ( ( line[*p_offset] == '\t' ) ||
+           ( line[*p_offset] == ' ' ) ) &&
+         ( line[*p_offset] != '\n' ) && ( line[*p_offset] != '\0' ) )
+    {
+      ++*p_offset;
+    }
+
+  if( ( line[*p_offset] == '\n' ) || ( line[*p_offset] == '\0' ) )
+    return ( FALSE );
+  else
+    return ( TRUE );
+}
+
+/**********************************************************************
+   Returns true if not whitespace character encountered before EOL.
+**********************************************************************/
+static void
+str_skip_token( IN char line[],
+                IN OUT uint32_t * const p_offset )
+{
+  while( ( line[*p_offset] != '\t' ) &&
+         ( line[*p_offset] != ' ' ) && ( line[*p_offset] != '\0' ) )
+    {
+      ++*p_offset;
+    }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_parse_node( IN osmtest_t * const p_osmt,
+                    IN FILE * const fh,
+                    IN OUT uint32_t * const p_line_num )
+{
+  ib_api_status_t status = IB_SUCCESS;
+  uint32_t offset;
+  char line[OSMTEST_MAX_LINE_LEN];
+  boolean_t done = FALSE;
+  node_t *p_node;
+  node_t *p_guid_node;
+  const osmtest_token_t *p_tok;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_parse_node );
+
+  p_node = node_new(  );
+  CL_ASSERT( p_node != NULL );
+
+  /*
+   * Parse the inventory file and create the database.
+   */
+  while( !done )
+    {
+      if( fgets( line, OSMTEST_MAX_LINE_LEN, fh ) == NULL )
+        {
+          /*
+           * End of file in the middle of a definition.
+           */
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_parse_node: ERR 00119: " 
+                   "Unexpected end of file.\n" );
+          status = IB_ERROR;
+          goto Exit;
+        }
+
+      ++*p_line_num;
+
+      /*
+       * Skip whitespace
+       */
+      offset = 0;
+      if( !str_skip_white( line, &offset ) )
+        continue;       /* whole line was whitespace */
+
+      p_tok = str_get_token( &line[offset] );
+      if( p_tok == NULL )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_parse_node: ERR 00120: " 
+                   "Ignoring line %u with unknown token: %s.\n",
+                   *p_line_num, &line[offset] );
+          continue;
+        }
+
+      if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                   "osmtest_parse_node: "
+                   "Found '%s' (line %u).\n", p_tok->str, *p_line_num );
+        }
+
+      str_skip_token( line, &offset );
+
+      switch ( p_tok->val )
+        {
+        case OSMTEST_TOKEN_COMMENT:
+          break;
+
+        case OSMTEST_TOKEN_LID:
+          p_node->comp.lid = 0xFFFF;
+          p_node->rec.lid =
+            cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_node: "
+                       "lid = 0x%X.\n", cl_ntoh16( p_node->rec.lid ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_BASE_VERSION:
+          p_node->comp.node_info.base_version = 0xFF;
+          p_node->rec.node_info.base_version =
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_node: "
+                       "base_version = 0x%X.\n",
+                       p_node->rec.node_info.base_version );
+            }
+          break;
+
+        case OSMTEST_TOKEN_CLASS_VERSION:
+          p_node->comp.node_info.class_version = 0xFF;
+          p_node->rec.node_info.class_version =
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_node: "
+                       "class_version = 0x%X.\n",
+                       p_node->rec.node_info.class_version );
+            }
+          break;
+
+        case OSMTEST_TOKEN_NODE_TYPE:
+          p_node->comp.node_info.node_type = 0xFF;
+          p_node->rec.node_info.node_type =
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_node: "
+                       "node_type = 0x%X.\n",
+                       p_node->rec.node_info.node_type );
+            }
+          break;
+
+        case OSMTEST_TOKEN_NUM_PORTS:
+          p_node->comp.node_info.num_ports = 0xFF;
+          p_node->rec.node_info.num_ports =
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_node: "
+                       "num_ports = 0x%X.\n",
+                       p_node->rec.node_info.num_ports );
+            }
+          break;
+
+        case OSMTEST_TOKEN_SYS_GUID:
+          p_node->comp.node_info.sys_guid = 0xFFFFFFFFFFFFFFFFULL;
+          p_node->rec.node_info.sys_guid =
+            cl_hton64( strtoull( &line[offset], NULL, 0 ) );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_node: "
+                       "sys_guid = 0x%016" PRIx64 ".\n",
+                       cl_ntoh64( p_node->rec.node_info.sys_guid ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_NODE_GUID:
+          p_node->comp.node_info.node_guid = 0xFFFFFFFFFFFFFFFFULL;
+          p_node->rec.node_info.node_guid =
+            cl_hton64( strtoull( &line[offset], NULL, 0 ) );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_node: "
+                       "node_guid = 0x%016" PRIx64 ".\n",
+                       cl_ntoh64( p_node->rec.node_info.node_guid ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_PORT_GUID:
+          p_node->comp.node_info.port_guid = 0xFFFFFFFFFFFFFFFFULL;
+          p_node->rec.node_info.port_guid =
+            cl_hton64( strtoull( &line[offset], NULL, 0 ) );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_node: "
+                       "port_guid = 0x%016" PRIx64 ".\n",
+                       cl_ntoh64( p_node->rec.node_info.port_guid ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_PARTITION_CAP:
+          p_node->comp.node_info.partition_cap = 0xFFFF;
+          p_node->rec.node_info.partition_cap = cl_hton16( ( uint16_t )
+                                                           strtoul( &line
+                                                                    [offset],
+                                                                    NULL,
+                                                                    0 ) );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_node: "
+                       "partition_cap = 0x%X.\n",
+                       cl_ntoh16( p_node->rec.node_info.partition_cap ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_DEVICE_ID:
+          p_node->comp.node_info.device_id = 0xFFFF;
+          p_node->rec.node_info.device_id = cl_hton16( ( uint16_t )
+                                                       strtoul( &line
+                                                                [offset],
+                                                                NULL, 0 ) );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_node: "
+                       "device_id = 0x%X.\n",
+                       cl_ntoh16( p_node->rec.node_info.device_id ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_REVISION:
+          p_node->comp.node_info.revision = 0xFFFFFFFF;
+          p_node->rec.node_info.revision =
+            cl_hton32( strtoul( &line[offset], NULL, 0 ) );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_node: "
+                       "revision = 0x%X.\n",
+                       cl_ntoh32( p_node->rec.node_info.revision ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_PORT_NUM:
+          p_node->comp.node_info.port_num_vendor_id |=
+            IB_NODE_INFO_PORT_NUM_MASK;
+          p_node->rec.node_info.port_num_vendor_id |=
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_node: "
+                       "local_port_num = 0x%X.\n",
+                       ib_node_info_get_local_port_num( &p_node->rec.
+                                                        node_info ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_VENDOR_ID:
+          p_node->comp.node_info.port_num_vendor_id |=
+            IB_NODE_INFO_VEND_ID_MASK;
+          p_node->rec.node_info.port_num_vendor_id |=
+            cl_hton32( strtoul( &line[offset], NULL, 0 ) );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_node: "
+                       "vendor_id = 0x%X.\n",
+                       cl_ntoh32( ib_node_info_get_vendor_id
+                                  ( &p_node->rec.node_info ) ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_END:
+          done = TRUE;
+          break;
+
+        default:
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_parse_node: ERR 00121: " 
+                   "Ignoring line %u with unknown token: %s.\n",
+                   *p_line_num, &line[offset] );
+
+          break;
+        }
+    }
+
+  /*
+   * Make sure the user specified enough information, then
+   * add this object to the database.
+   */
+  if( p_node->comp.lid == 0 )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_parse_node: ERR 00122: " 
+               "LID must be specified for defined nodes.\n" );
+      node_delete( p_node );
+      goto Exit;
+    }
+
+  cl_qmap_insert( &p_osmt->exp_subn.node_lid_tbl,
+                  p_node->rec.lid, &p_node->map_item );
+
+  p_guid_node = node_new(  );
+  CL_ASSERT( p_node != NULL );
+
+  *p_guid_node = *p_node;
+
+  cl_qmap_insert( &p_osmt->exp_subn.node_guid_tbl,
+                  p_guid_node->rec.node_info.node_guid,
+                  &p_guid_node->map_item );
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_parse_port( IN osmtest_t * const p_osmt,
+                    IN FILE * const fh,
+                    IN OUT uint32_t * const p_line_num )
+{
+  ib_api_status_t status = IB_SUCCESS;
+  uint32_t offset;
+  char line[OSMTEST_MAX_LINE_LEN];
+  boolean_t done = FALSE;
+  port_t *p_port;
+  const osmtest_token_t *p_tok;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_parse_port );
+
+  p_port = port_new(  );
+  CL_ASSERT( p_port != NULL );
+
+  /*
+   * Parse the inventory file and create the database.
+   */
+  while( !done )
+    {
+      if( fgets( line, OSMTEST_MAX_LINE_LEN, fh ) == NULL )
+        {
+          /*
+           * End of file in the middle of a definition.
+           */
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_parse_port: ERR 00123: " 
+                   "Unexpected end of file.\n" );
+          status = IB_ERROR;
+          goto Exit;
+        }
+
+      ++*p_line_num;
+
+      /*
+       * Skip whitespace
+       */
+      offset = 0;
+      if( !str_skip_white( line, &offset ) )
+        continue;       /* whole line was whitespace */
+
+      p_tok = str_get_token( &line[offset] );
+      if( p_tok == NULL )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_parse_port: ERR 00124: " 
+                   "Ignoring line %u with unknown token: %s.\n",
+                   *p_line_num, &line[offset] );
+          continue;
+        }
+
+      if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                   "osmtest_parse_port: "
+                   "Found '%s' (line %u).\n", p_tok->str, *p_line_num );
+        }
+
+      str_skip_token( line, &offset );
+
+      switch ( p_tok->val )
+        {
+        case OSMTEST_TOKEN_COMMENT:
+          break;
+
+        case OSMTEST_TOKEN_LID:
+          p_port->comp.lid = 0xFFFF;
+          p_port->rec.lid =
+            cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "lid = 0x%X.\n", cl_ntoh16( p_port->rec.lid ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_PORT_NUM:
+          p_port->comp.port_num = 0xFF;
+          p_port->rec.port_num =
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "port_num = 0x%u.\n",
+                       p_port->rec.port_num );
+            }
+          break;
+
+        case OSMTEST_TOKEN_MKEY:
+          p_port->comp.port_info.m_key = 0xFFFFFFFFFFFFFFFFULL;
+          p_port->rec.port_info.m_key =
+            cl_hton64( strtoull( &line[offset], NULL, 0 ) );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "m_key = 0x%016" PRIx64 ".\n",
+                       cl_ntoh64( p_port->rec.port_info.m_key ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_SUBN_PREF:
+          p_port->comp.port_info.subnet_prefix = 0xFFFFFFFFFFFFFFFFULL;
+          p_port->rec.port_info.subnet_prefix =
+            cl_hton64( strtoull( &line[offset], NULL, 0 ) );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "subnet_prefix = 0x%016" PRIx64 ".\n",
+                       cl_ntoh64( p_port->rec.port_info.subnet_prefix ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_BASE_LID:
+          p_port->comp.port_info.base_lid = 0xFFFF;
+          p_port->rec.port_info.base_lid =
+            cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "base_lid = 0x%X.\n", cl_ntoh16( p_port->rec.port_info.base_lid ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_SM_BASE_LID:
+          p_port->comp.port_info.master_sm_base_lid = 0xFFFF;
+          p_port->rec.port_info.master_sm_base_lid =
+            cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "master_sm_base_lid = 0x%X.\n",
+                       cl_ntoh16( p_port->rec.port_info.master_sm_base_lid ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_CAP_MASK:
+          p_port->comp.port_info.capability_mask = 0xFFFFFFFF;
+          p_port->rec.port_info.capability_mask =
+            cl_hton32( ( uint32_t ) strtoul( &line[offset], NULL, 0 ) );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "capability_mask = 0x%X.\n",
+                       cl_ntoh32( p_port->rec.port_info.capability_mask ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_DIAG_CODE:
+          p_port->comp.port_info.diag_code = 0xFFFF;
+          p_port->rec.port_info.diag_code =
+            cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "diag_code = 0x%X.\n",
+                       cl_ntoh16( p_port->rec.port_info.diag_code ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_MKEY_LEASE_PER:
+          p_port->comp.port_info.m_key_lease_period = 0xFFFF;
+          p_port->rec.port_info.m_key_lease_period =
+            cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "m_key_lease_period = 0x%X.\n",
+                       cl_ntoh16( p_port->rec.port_info.m_key_lease_period ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_LOC_PORT_NUM:
+          p_port->comp.port_info.local_port_num = 0xFF;
+          p_port->rec.port_info.local_port_num =
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "local_port_num = 0x%u.\n",
+                       p_port->rec.port_info.local_port_num );
+            }
+          break;
+
+        case OSMTEST_TOKEN_LINK_WID_EN:
+          p_port->comp.port_info.link_width_enabled = 0xFF;
+          p_port->rec.port_info.link_width_enabled =
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "link_width_enabled = 0x%u.\n",
+                       p_port->rec.port_info.link_width_enabled );
+            }
+          break;
+
+        case OSMTEST_TOKEN_LINK_WID_SUP:
+          p_port->comp.port_info.link_width_supported = 0xFF;
+          p_port->rec.port_info.link_width_supported =
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "link_width_supported = 0x%u.\n",
+                       p_port->rec.port_info.link_width_supported );
+            }
+          break;
+
+        case OSMTEST_TOKEN_LINK_WID_ACT:
+          p_port->comp.port_info.link_width_active = 0xFF;
+          p_port->rec.port_info.link_width_active =
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "link_width_active = 0x%u.\n",
+                       p_port->rec.port_info.link_width_active );
+            }
+          break;
+
+        case OSMTEST_TOKEN_LINK_SPEED_SUP:
+          p_port->comp.port_info.state_info1 = 0xFF;
+          ib_port_info_set_link_speed_sup(
+                                          ( uint8_t ) strtoul( &line[offset], NULL, 0 ),
+                                          &p_port->rec.port_info);
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "link_speed_supported = 0x%u.\n",
+                       ib_port_info_get_link_speed_sup(&p_port->rec.port_info));
+            }
+          break;
+
+        case OSMTEST_TOKEN_PORT_STATE:
+          str_skip_white( line, &offset );
+          p_port->comp.port_info.state_info1 = 0xFF;
+          ib_port_info_set_port_state(&p_port->rec.port_info,
+                                      ib_get_port_state_from_str(&line[offset]));
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "port_state = 0x%u.\n",
+                       ib_port_info_get_port_state(&p_port->rec.port_info));
+            }
+          break;
+
+        case OSMTEST_TOKEN_STATE_INFO2:
+          p_port->comp.port_info.state_info2 = 0xFF;
+          p_port->rec.port_info.state_info2 =
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "state_info2 = 0x%u.\n",
+                       p_port->rec.port_info.state_info2 );
+            }
+          break;
+
+        case OSMTEST_TOKEN_MKEY_PROT_BITS:
+          p_port->comp.port_info.mkey_lmc = 0xFF;
+          ib_port_info_set_mpb(
+                               &p_port->rec.port_info,
+                               ( uint8_t ) strtoul( &line[offset], NULL, 0 ));
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "mpb = 0x%u.\n",
+                       ib_port_info_get_mpb(&p_port->rec.port_info) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_LMC:
+          p_port->comp.port_info.mkey_lmc = 0xFF;
+          ib_port_info_set_lmc(
+                               &p_port->rec.port_info,
+                               ( uint8_t ) strtoul( &line[offset], NULL, 0 ) );
+
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "lmc = 0x%u.\n",
+                       ib_port_info_get_lmc(&p_port->rec.port_info) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_LINK_SPEED:
+          p_port->comp.port_info.link_speed = 0xFF;
+          p_port->rec.port_info.link_speed =
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "link_speed = 0x%u.\n",
+                       p_port->rec.port_info.link_speed );
+            }
+          break;
+
+        case OSMTEST_TOKEN_MTU_SMSL:
+          p_port->comp.port_info.mtu_smsl = 0xFF;
+          p_port->rec.port_info.mtu_smsl =
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "mtu_smsl = 0x%u.\n",
+                       p_port->rec.port_info.mtu_smsl );
+            }
+          break;
+
+        case OSMTEST_TOKEN_VL_CAP:
+          p_port->comp.port_info.vl_cap = 0xFF;
+          p_port->rec.port_info.vl_cap =
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "vl_cap = 0x%u.\n",
+                       p_port->rec.port_info.vl_cap );
+            }
+          break;
+
+        case OSMTEST_TOKEN_VL_HIGH_LIMIT:
+          p_port->comp.port_info.vl_high_limit = 0xFF;
+          p_port->rec.port_info.vl_high_limit =
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "vl_high_limit = 0x%u.\n",
+                       p_port->rec.port_info.vl_high_limit );
+            }
+          break;
+
+        case OSMTEST_TOKEN_VL_ARB_HIGH_CAP:
+          p_port->comp.port_info.vl_arb_high_cap = 0xFF;
+          p_port->rec.port_info.vl_arb_high_cap =
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "vl_arb_high_cap = 0x%u.\n",
+                       p_port->rec.port_info.vl_arb_high_cap );
+            }
+          break;
+
+        case OSMTEST_TOKEN_VL_ARB_LOW_CAP:
+          p_port->comp.port_info.vl_arb_low_cap = 0xFF;
+          p_port->rec.port_info.vl_arb_low_cap =
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "vl_arb_low_cap = 0x%u.\n",
+                       p_port->rec.port_info.vl_arb_low_cap );
+            }
+          break;
+
+        case OSMTEST_TOKEN_MTU_CAP:
+          p_port->comp.port_info.mtu_cap = 0xFF;
+          p_port->rec.port_info.mtu_cap =
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "mtu_cap = 0x%u.\n",
+                       p_port->rec.port_info.mtu_cap );
+            }
+          break;
+
+        case OSMTEST_TOKEN_VL_STALL_LIFE:
+          p_port->comp.port_info.vl_stall_life = 0xFF;
+          p_port->rec.port_info.vl_stall_life =
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "vl_stall_life = 0x%u.\n",
+                       p_port->rec.port_info.vl_stall_life );
+            }
+          break;
+
+        case OSMTEST_TOKEN_VL_ENFORCE:
+          p_port->comp.port_info.vl_enforce = 0xFF;
+          p_port->rec.port_info.vl_enforce =
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "vl_enforce = 0x%u.\n",
+                       p_port->rec.port_info.vl_enforce );
+            }
+          break;
+
+        case OSMTEST_TOKEN_MKEY_VIOL:
+          p_port->comp.port_info.m_key_violations = 0xFFFF;
+          p_port->rec.port_info.m_key_violations =
+            cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "m_key_violations = 0x%X.\n",
+                       cl_ntoh16( p_port->rec.port_info.m_key_violations ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_PKEY_VIOL:
+          p_port->comp.port_info.p_key_violations = 0xFFFF;
+          p_port->rec.port_info.p_key_violations =
+            cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "p_key_violations = 0x%X.\n",
+                       cl_ntoh16( p_port->rec.port_info.p_key_violations ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_QKEY_VIOL:
+          p_port->comp.port_info.q_key_violations = 0xFFFF;
+          p_port->rec.port_info.q_key_violations =
+            cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "q_key_violations = 0x%X.\n",
+                       cl_ntoh16( p_port->rec.port_info.q_key_violations ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_GUID_CAP:
+          p_port->comp.port_info.guid_cap = 0xFF;
+          p_port->rec.port_info.guid_cap =
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "guid_cap = 0x%u.\n",
+                       p_port->rec.port_info.guid_cap );
+            }
+          break;
+
+        case OSMTEST_TOKEN_SUBN_TIMEOUT:
+          p_port->comp.port_info.subnet_timeout = 0x1F;
+          p_port->rec.port_info.subnet_timeout =
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "subnet_timeout = 0x%u.\n",
+                       ib_port_info_get_timeout(&p_port->rec.port_info) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_RESP_TIME_VAL:
+          p_port->comp.port_info.resp_time_value = 0xFF;
+          p_port->rec.port_info.resp_time_value =
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "resp_time_value = 0x%u.\n",
+                       p_port->rec.port_info.resp_time_value );
+            }
+          break;
+
+        case OSMTEST_TOKEN_ERR_THRESHOLD:
+          p_port->comp.port_info.error_threshold = 0xFF;
+          p_port->rec.port_info.error_threshold =
+            ( uint8_t ) strtoul( &line[offset], NULL, 0 );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_port: "
+                       "error_threshold = 0x%u.\n",
+                       p_port->rec.port_info.error_threshold );
+            }
+          break;
+
+        case OSMTEST_TOKEN_END:
+          done = TRUE;
+          break;
+
+        default:
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_parse_port: ERR 00125: " 
+                   "Ignoring line %u with unknown token: %s.\n",
+                   *p_line_num, &line[offset] );
+
+          break;
+        }
+    }
+
+  /*
+   * Make sure the user specified enough information, then
+   * add this object to the database.
+   */
+  if( p_port->comp.lid == 0 )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_parse_port: ERR 00126: " 
+               "LID must be specified for defined ports.\n" );
+      port_delete( p_port );
+      goto Exit;
+    }
+
+  cl_qmap_insert( &p_osmt->exp_subn.port_key_tbl,
+                  port_gen_id(p_port->rec.lid, p_port->rec.port_num),
+                  &p_port->map_item );
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_parse_path( IN osmtest_t * const p_osmt,
+                    IN FILE * const fh,
+                    IN OUT uint32_t * const p_line_num )
+{
+  ib_api_status_t status = IB_SUCCESS;
+  uint32_t offset;
+  char line[OSMTEST_MAX_LINE_LEN];
+  boolean_t done = FALSE;
+  path_t *p_path;
+  const osmtest_token_t *p_tok;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_parse_path );
+
+  p_path = path_new(  );
+  CL_ASSERT( p_path != NULL );
+
+  /*
+   * Parse the inventory file and create the database.
+   */
+  while( !done )
+    {
+      if( fgets( line, OSMTEST_MAX_LINE_LEN, fh ) == NULL )
+        {
+          /*
+           * End of file in the middle of a definition.
+           */
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_parse_path: ERR 00127: " 
+                   "Unexpected end of file.\n" );
+          status = IB_ERROR;
+          goto Exit;
+        }
+
+      ++*p_line_num;
+
+      /*
+       * Skip whitespace
+       */
+      offset = 0;
+      if( !str_skip_white( line, &offset ) )
+        continue;       /* whole line was whitespace */
+
+      p_tok = str_get_token( &line[offset] );
+      if( p_tok == NULL )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_parse_path: ERR 00128: " 
+                   "Ignoring line %u with unknown token: %s.\n",
+                   *p_line_num, &line[offset] );
+          continue;
+        }
+
+      if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                   "osmtest_parse_path: "
+                   "Found '%s' (line %u).\n", p_tok->str, *p_line_num );
+        }
+
+      str_skip_token( line, &offset );
+
+      switch ( p_tok->val )
+        {
+        case OSMTEST_TOKEN_COMMENT:
+          break;
+
+        case OSMTEST_TOKEN_DGID:
+          p_path->comp.dgid.unicast.prefix = 0xFFFFFFFFFFFFFFFFULL;
+          p_path->comp.dgid.unicast.interface_id = 0xFFFFFFFFFFFFFFFFULL;
+
+          str_skip_white( line, &offset );
+          p_path->rec.dgid.unicast.prefix =
+            cl_hton64( strtoull( &line[offset], NULL, 0 ) );
+          str_skip_token( line, &offset );
+          p_path->rec.dgid.unicast.interface_id =
+            cl_hton64( strtoull( &line[offset], NULL, 0 ) );
+
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_path: "
+                       "dgid = 0x%016" PRIx64 " 0x%016" PRIx64 ".\n",
+                       cl_ntoh64( p_path->rec.dgid.unicast.prefix ),
+                       cl_ntoh64( p_path->rec.dgid.unicast.interface_id ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_SGID:
+          p_path->comp.sgid.unicast.prefix = 0xFFFFFFFFFFFFFFFFULL;
+          p_path->comp.sgid.unicast.interface_id = 0xFFFFFFFFFFFFFFFFULL;
+
+          str_skip_white( line, &offset );
+          p_path->rec.sgid.unicast.prefix =
+            cl_hton64( strtoull( &line[offset], NULL, 0 ) );
+          str_skip_token( line, &offset );
+          p_path->rec.sgid.unicast.interface_id =
+            cl_hton64( strtoull( &line[offset], NULL, 0 ) );
+
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_path: "
+                       "sgid = 0x%016" PRIx64 " 0x%016" PRIx64 ".\n",
+                       cl_ntoh64( p_path->rec.sgid.unicast.prefix ),
+                       cl_ntoh64( p_path->rec.sgid.unicast.interface_id ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_DLID:
+          p_path->comp.dlid = 0xFFFF;
+          p_path->rec.dlid =
+            cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_path: "
+                       "dlid = 0x%X.\n", cl_ntoh16( p_path->rec.dlid ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_SLID:
+          p_path->comp.slid = 0xFFFF;
+          p_path->rec.slid =
+            cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_path: "
+                       "slid = 0x%X.\n", cl_ntoh16( p_path->rec.slid ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_PKEY:
+          p_path->comp.pkey = 0xFFFF;
+          p_path->rec.pkey =
+            cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );
+          if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+            {
+              osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                       "osmtest_parse_path: "
+                       "pkey = 0x%X.\n", cl_ntoh16( p_path->rec.pkey ) );
+            }
+          break;
+
+        case OSMTEST_TOKEN_END:
+          done = TRUE;
+          break;
+
+        default:
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_parse_path: ERR 00129: " 
+                   "Ignoring line %u with unknown token: %s.\n",
+                   *p_line_num, &line[offset] );
+
+          break;
+        }
+    }
+
+  /*
+   * Make sure the user specified enough information, then
+   * add this object to the database.
+   */
+  if( osmtest_path_rec_kay_is_valid( p_osmt, p_path ) == FALSE )
+    {
+      path_delete( p_path );
+      goto Exit;
+    }
+
+  cl_qmap_insert( &p_osmt->exp_subn.path_tbl,
+                  osmtest_path_rec_key_get( &p_path->rec ),
+                  &p_path->map_item );
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+osmtest_create_db( IN osmtest_t * const p_osmt )
+{
+  FILE *fh;
+  ib_api_status_t status = IB_SUCCESS;
+  uint32_t offset;
+  char line[OSMTEST_MAX_LINE_LEN];
+  uint32_t line_num = 0;
+  const osmtest_token_t *p_tok;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_create_db );
+
+  fh = fopen( p_osmt->opt.file_name, "r" );
+  if( fh == NULL )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_create_db: ERR 00130: " 
+               "Unable to open inventory file (%s).\n" ,p_osmt->opt.file_name);
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+  /*
+   * Parse the inventory file and create the database.
+   */
+  while( fgets( line, OSMTEST_MAX_LINE_LEN, fh ) != NULL )
+    {
+      line_num++;
+
+      /*
+       * Skip whitespace
+       */
+      offset = 0;
+      if( !str_skip_white( line, &offset ) )
+        continue;       /* whole line was whitespace */
+
+      p_tok = str_get_token( &line[offset] );
+      if( p_tok == NULL )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_create_db: ERR 00131: " 
+                   "Ignoring line %u: %s.\n", line_num, &line[offset] );
+          continue;
+        }
+
+      if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+                   "osmtest_create_db: "
+                   "Found '%s' (line %u).\n", p_tok->str, line_num );
+        }
+
+      switch ( p_tok->val )
+        {
+        case OSMTEST_TOKEN_COMMENT:
+          break;
+
+        case OSMTEST_TOKEN_DEFINE_NODE:
+          status = osmtest_parse_node( p_osmt, fh, &line_num );
+          break;
+
+        case OSMTEST_TOKEN_DEFINE_PORT:
+          status = osmtest_parse_port( p_osmt, fh, &line_num );
+          break;
+
+        case OSMTEST_TOKEN_DEFINE_PATH:
+          status = osmtest_parse_path( p_osmt, fh, &line_num );
+          break;
+
+        default:
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_create_db: ERR 00132: " 
+                   "Ignoring line %u: %s.\n", line_num, &line[offset] );
+          break;
+        }
+
+      if( status != IB_SUCCESS )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_create_db: ERR 00133: " 
+                   "Bad status received during parsing (%s).\n",
+                   ib_get_err_str( status ) );
+          fclose( fh );
+          goto Exit;
+        }
+    }
+
+  fclose( fh );
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+   Returns the index in the local port attribute array for the
+   user's selection.
+**********************************************************************/
+static uint32_t
+osmtest_get_user_port( IN osmtest_t * const p_osmt,
+                       IN const ib_port_attr_t p_attr_array[],
+                       IN uint32_t const num_ports )
+{
+  uint32_t i;
+  uint32_t choice = 0;
+  boolean_t done_flag = FALSE;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_get_user_port );
+
+  /*
+   * User needs prompting for the local port GUID with which
+   * to bind.
+   */
+
+  while( done_flag == FALSE )
+    {
+      printf( "\nChoose a local port number with which to bind:\n\n" );
+      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( p_attr_array[i].port_guid ),
+                  p_attr_array[i].lid,
+                  ib_get_port_state_str( p_attr_array[i].link_state ) );
+        }
+
+      printf( "\nEnter choice (1-%u): ", i );
+      scanf( "%u", &choice );
+      if( choice > num_ports )
+        printf( "\nError: Lame choice!\n" );
+      else
+        done_flag = TRUE;
+
+    }
+  printf("\n");
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( choice - 1 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_bind( IN osmtest_t * p_osmt,
+              IN uint16_t max_lid,
+              IN ib_net64_t guid OPTIONAL )
+{
+  uint32_t port_index;
+  ib_api_status_t status;
+  uint32_t num_ports = GUID_ARRAY_SIZE;
+  ib_port_attr_t attr_array[GUID_ARRAY_SIZE];
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_bind );
+
+  /*
+   * Call the transport layer for a list of local port
+   * GUID values.
+   */
+  status = osm_vendor_get_all_port_attr( p_osmt->p_vendor,
+                                         attr_array, &num_ports );
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_bind: ERR 00134: " 
+               "Failure getting local port attributes (%s)\n",
+               ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+  if( guid == 0 )
+    {
+      /*
+       * User needs prompting for the local port GUID with which
+       * to bind.
+       */
+      port_index = osmtest_get_user_port( p_osmt, attr_array, num_ports );
+
+      if( num_ports == 0 )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_bind: ERR 00135: " 
+                   "No local ports.  Unable to proceed.\n",
+                   ib_get_err_str( status ) );
+          goto Exit;
+        }
+      guid = attr_array[port_index].port_guid;
+    }
+  else
+    {
+      for( port_index = 0; port_index < num_ports; port_index++ )
+        {
+          if( attr_array[port_index].port_guid == guid )
+            break;
+        }
+
+      if( port_index == num_ports )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_bind: ERR 00136: " 
+                   "No local port with guid 0x%016" PRIx64 ".\n",
+                   cl_ntoh64( guid ) );
+          status = IB_NOT_FOUND;
+          goto Exit;
+        }
+    }
+
+  /*
+   * Copy the port info for the selected port.
+   */
+  cl_memcpy( &p_osmt->local_port, &attr_array[port_index],
+             sizeof( p_osmt->local_port ) );
+
+  /* bind to the SA */
+  osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+           "osmtest_bind: "
+           "Using port SM_LID:0x%04X\n",
+           p_osmt->local_port.sm_lid);
+  p_osmt->max_lid = max_lid;
+
+  p_osmt->h_bind =
+    osmv_bind_sa(p_osmt->p_vendor, &p_osmt->mad_pool, guid);
+
+  if(  p_osmt->h_bind == OSM_BIND_INVALID_HANDLE )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_bind: ERR 00137: "        "Unable to bind to SA\n" );
+      status = IB_ERROR;
+      goto Exit;
+    }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osmtest_run( IN osmtest_t * const p_osmt )
+{
+  ib_api_status_t status = IB_SUCCESS;
+
+  OSM_LOG_ENTER( &p_osmt->log, osmtest_run );
+
+  status = osmtest_validate_sa_class_port_info(p_osmt);
+  if( status != IB_SUCCESS )
+    {
+      osm_log( &p_osmt->log, OSM_LOG_ERROR,
+               "osmtest_run: ERR 00138: " 
+               "Could not obtain SA ClassPortInfo (%s)\n",
+               ib_get_err_str( status ) );
+      goto Exit;
+    }
+
+  if( p_osmt->opt.flow == 1 )
+    {
+      status = osmtest_create_inventory_file( p_osmt );
+      if( status != IB_SUCCESS )
+        {
+          osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                   "osmtest_run: ERR 00139: " 
+                   "Inventory file create failed (%s)\n",
+                   ib_get_err_str( status ) );
+          goto Exit;
+        }
+    }
+  else
+    {
+      if( p_osmt->opt.flow == 5 )
+        {
+          switch ( p_osmt->opt.stress )
+            {
+            case 0:
+            case 1:        /* small response SA query stress */
+              status = osmtest_stress_small_rmpp( p_osmt );
+              if( status != IB_SUCCESS )
+                {
+                  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                           "osmtest_run: ERR 00140: " 
+                           "Small RMPP stress test failed (%s)\n",
+                           ib_get_err_str( status ) );
+                  goto Exit;
+                }
+              break;
+            case 2:        /* large response SA query stress */
+              status = osmtest_stress_large_rmpp( p_osmt );
+              if( status != IB_SUCCESS )
+                {
+                  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                           "osmtest_run: ERR 00141: " 
+                           "Large RMPP stress test failed (%s)\n",
+                           ib_get_err_str( status ) );
+                  goto Exit;
+                }
+              break;
+            case 3:        /* large response Path Record SA query stress */
+                status = osmtest_create_db( p_osmt );
+                if( status != IB_SUCCESS )
+                  {
+                    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                             "osmtest_run: ERR 00143: " 
+                             "Database creation failed (%s)\n",
+                             ib_get_err_str( status ) );
+                    goto Exit;
+                  }
+
+                status = osmtest_stress_large_rmpp_pr( p_osmt );
+                if( status != IB_SUCCESS )
+                {
+                    osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                         "osmtest_run: ERR 00142: " 
+                         "Large RMPP stress test failed (%s)\n",
+                         ib_get_err_str( status ) );
+                    goto Exit;
+                }
+                break;
+            default:
+                osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                     "osmtest_run: ERR 00143: " 
+                     "Unknown stress test value %u.\n",
+                     p_osmt->opt.stress );
+                break;
+            }
+        }
+      else
+        {
+
+          /*
+           * Run normal validition tests.
+           */
+          if (!p_osmt->opt.flow || p_osmt->opt.flow == 2)
+            {
+              status = osmtest_create_db( p_osmt );
+              if( status != IB_SUCCESS )
+                {
+                  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                           "osmtest_run: ERR 00143: " 
+                           "Database creation failed (%s)\n",
+                           ib_get_err_str( status ) );
+                  goto Exit;
+                }
+
+              status = osmtest_validate_against_db( p_osmt );
+              if( status != IB_SUCCESS )
+                {
+                  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                           "osmtest_run: ERR 00144: " 
+                           "SA validation again database failure (%s)\n",
+                           ib_get_err_str( status ) );
+                  goto Exit;
+                }
+            }
+
+          if (!p_osmt->opt.flow)
+            {
+              status = osmtest_wrong_sm_key_ignored( p_osmt );
+              if( status != IB_SUCCESS )
+                {
+                  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                           "osmtest_run: ERR 00145: " 
+                           "Try wrong SM_Key failed (%s)\n",
+                           ib_get_err_str( status ) );
+                  goto Exit;
+                }
+            }
+
+          if (!p_osmt->opt.flow || p_osmt->opt.flow == 3)
+            {
+              status = osmt_run_service_records_flow( p_osmt );
+              if( status != IB_SUCCESS )
+                {
+                  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                           "osmtest_run: ERR 00146: " 
+                           "Service Flow failed (%s)\n",
+                           ib_get_err_str( status ) );
+                  goto Exit;
+                }
+            }
+
+#ifdef OSM_VENDOR_INTF_MTL /*  only available for now on mVAPI */
+          if (!p_osmt->opt.flow || p_osmt->opt.flow == 4)
+            {
+              status = osmt_run_inform_info_flow( p_osmt );
+              if( status != IB_SUCCESS )
+                {
+                  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                           "osmtest_run: ERR 00147: " 
+                           "Inform Info Flow Failed: (%s)\n",
+                           ib_get_err_str( status ) );
+                  goto Exit;
+                }
+            }
+
+          /*
+           * since it generate a huge file - we run it only
+           * if explicitly required to
+           */
+          if (p_osmt->opt.flow == 7)
+            {
+              status = osmt_run_slvl_and_vlarb_records_flow(p_osmt);
+              if( status != IB_SUCCESS )
+                {
+                  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                           "osmtest_run: ERR 00148: " 
+                           "Fail to get SLtoVL and VL Arbitration Tables (%s)\n",
+                           ib_get_err_str( status ) );
+                  goto Exit;
+                }
+            }
+
+          if (p_osmt->opt.flow == 8)
+            {
+              status = osmt_run_trap64_65_flow( p_osmt  );
+              if( status != IB_SUCCESS )
+              {
+                osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                         "osmtest_run: ERR 00150: " 
+                         "Trap 64/65 Flow Failed: (%s)\n",
+                         ib_get_err_str( status ) );
+                goto Exit;
+              }
+            }
+
+#endif
+
+          if (!p_osmt->opt.flow || p_osmt->opt.flow == 6)
+            {
+              status = osmt_run_mcast_flow( p_osmt );
+              if( status != IB_SUCCESS )
+                {
+                  osm_log( &p_osmt->log, OSM_LOG_ERROR,
+                           "osmtest_run: ERR 00149: " 
+                           "Multicast Flow Failed: (%s)\n",
+                           ib_get_err_str( status ) );
+                  goto Exit;
+                }
+            }
+
+          osm_log( &p_osmt->log, OSM_LOG_INFO,
+                   "osmtest_run: "
+                   "\n\n***************** ALL TESTS PASS *****************\n\n" );
+
+        }
+    }
+
+ Exit:
+  OSM_LOG_EXIT( &p_osmt->log );
+  return ( status );
+}
diff --git a/trunk/ulp/opensm/user/osmtest/osmtest.h b/trunk/ulp/opensm/user/osmtest/osmtest.h
new file mode 100644 (file)
index 0000000..005f0e2
--- /dev/null
@@ -0,0 +1,519 @@
+/*
+ * 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$
+ */
+
+
+
+/*
+ * 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 <vendor/osm_vendor_api.h>
+#include <vendor/osm_vendor_sa_api.h>
+#include "osmtest_base.h"
+#include "osmtest_subnet.h"
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_helper.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 );
+#endif /* _OSMTEST_H_ */
diff --git a/trunk/ulp/opensm/user/osmtest/osmtest_base.h b/trunk/ulp/opensm/user/osmtest/osmtest_base.h
new file mode 100644 (file)
index 0000000..c287419
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * 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$
+ */
+
+
+
+/*
+ * 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/trunk/ulp/opensm/user/osmtest/osmtest_subnet.h b/trunk/ulp/opensm/user/osmtest/osmtest_subnet.h
new file mode 100644 (file)
index 0000000..1bb7e89
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+ * 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$
+ */
+
+
+
+/*
+ * 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 <complib/cl_qmap.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_log.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 = cl_zalloc( sizeof( *p_obj ) );
+       return ( p_obj );
+}
+
+static inline void
+node_delete( IN node_t * p_obj )
+{
+       cl_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 uniq 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 = cl_zalloc( sizeof( *p_obj ) );
+       return ( p_obj );
+}
+
+static inline void
+port_delete( IN port_t * p_obj )
+{
+       cl_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 = cl_zalloc( sizeof( *p_obj ) );
+       return ( p_obj );
+}
+
+static inline void
+path_delete( IN path_t * p_obj )
+{
+       cl_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;
+#if 0
+  cl_qmap_t port_lid_tbl;
+  cl_qmap_t port_guid_tbl;
+#endif
+  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_init
+* NAME
+*      subnet_init
+*
+* 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